Set up a read-only connection
~5–10 minutes on your ServiceNow instance. You create a read-only user and an OAuth app; InstanceGuard only ever reads. We physically cannot write — every call is HTTP GET, enforced in code. OAuth (client_credentials) is the recommended method: no password is ever stored.
1. Create a read-only integration user
- User Administration → Users → New. Set
User IDe.g.svc_instanceguard_ro. Check Web service access only and Internal Integration User. Make sure it is Active. - Assign
snc_read_only. This makes the account read-only at the platform level — writes are blocked by ServiceNow itself, regardless of any other role. We check for this and show it as the strongest guarantee. - Grant the read access it needs to see the configuration being audited (ACLs, business rules, script includes, roles, recent changes). Because
snc_read_onlyblocks every write, it is safe for the account to also hold broad read roles — includingadmin— for coverage; writes remain impossible. We refuse a connection only if the account is write-capable withoutsnc_read_onlyenforcing read-only. - If your instance restricts REST access by role, also grant
snc_platform_rest_api_access.
2. Register an OAuth app (client_credentials)
Requires Washington DC or later for inbound client_credentials. On older releases, contact us and we'll switch the connection to a supported mode.
- System OAuth → Application Registry → New. On current releases choose the New Inbound Integration Experience → OAuth – Client Credentials grant; on older ones use Create an OAuth API endpoint for external clients. Both work.
- Name it e.g.
InstanceGuard. Leave the Client ID / Secret auto-generated. Do not enable “Public Client.” - Set the app's run-as / OAuth Application User to your
svc_instanceguard_rouser. (In the deprecated UI this field may need to be added via Form Builder.) Tokens then act as that read-only user — this binding is required; without it every API call returns 401/403. - Confirm the system property
glide.oauth.inbound.client.credential.grant_type.enabledistrue(it is off by default — this is the master switch for the grant). - Copy the Client ID and Client Secret. The secret is shown once.
3. Let the token reach the platform APIs
On Zurich and later, OAuth clients are scoped by default and blocked from “unscoped” APIs — including the Table API InstanceGuard reads. This is the single most common setup snag, so do it up front:
- On the OAuth app, set Scope Restriction → Broadly Scoped.
- Add the built-in
useraccountscope to the app's OAuth Entity Scopes (grants full API access, still governed by the user's roles — and your user issnc_read_only).
4. Connect
Paste the instance URL, Client ID, and Client Secret into New connection, set the integration username, and click Validate. We immediately:
- request a token via
client_credentials(no password stored), - resolve which user the token authenticates as,
- enumerate that user's roles, and
- refuse the connection if any write-capable role is present without
snc_read_onlyenforcing read-only — surfaced as a trust signal.
Troubleshooting
If Validate fails, match the error to the fix:
- 401 on a Basic connection — the username/password is rejected. Reset the user's password (uncheck “Password needs reset”), or switch to OAuth.
- OAuth token request fails — the grant isn't enabled (step 2.4), the release predates Washington DC, or the Client Secret is wrong.
- 403 “Access to unscoped api is not allowed” — the token is scoped. Do step 3 (Broadly Scoped +
useraccount). This is expected on Zurich+. - Rejected: write-capable roles — the integration user can write. Add
snc_read_onlyso writes are platform-blocked, or use a read-only user.