Randheer Singh
ServiceNow Employee

In Part 1, we covered the fundamentals of REST API Access Policies, and in Part 2, we went deep on Auth Scope, OAuth Entity Linking, and MIAC. Both stopped at the REST boundary. But Basic Auth doesn't only enter through REST — it also rides in through SOAP, JSONv2, PDF, Excel, and export processors. If you lock down REST and stop there, those surfaces are still wide open.

This post closes the gap end-to-end. By the time you finish, you'll be able to deny Basic Auth across every inbound surface, and re-enable it only for the specific integrations that genuinely need it — tightly scoped, on your terms.

This blog content applies to Xanadu, Yokohama, Zurich, and Australia releases. One exception: Machine Identity Access Controls (MIAC) was introduced in Zurich. Future releases may change behavior — always refer to the product documentation for the latest details.

 

Why Eliminate Basic Auth?
Basic Authentication sends a static username and password on every request. It can't enforce MFA, the credentials don't rotate, and reused passwords make it the favorite target of credential-stuffing campaigns. It's also one of the first things compliance auditors flag for programmatic access. Moving integrations to OAuth, mTLS, or ID Token (Federated Token) removes the static-secret problem — but only if you actually stop accepting Basic Auth at the door.


The Mental Model: Two Enforcement Surfaces

ServiceNow enforces inbound authentication through two distinct mechanisms, depending on the surface:

Surface Controlled by

REST APIs (Table, Import Set, Knowledge, Scripted REST, etc.)

REST API Access Policy

Everything else — SOAP, JSONv2, PDF, Excel, export, and other non-public processors

The "Apply to all non-public processors" flag on an Authentication Profile, plus per-processor overrides

 

A non-public processor is any processor that requires authentication (as opposed to public processors, which allow anonymous access).

The "Apply to all non-public processors" flag covers these — with one deliberate exception: the REST API processor, which is governed separately by REST API Access Policy (Part A). So, in practice, this flag covers every authenticated processor except REST.
Keep this split in mind: a REST API Access Policy will not protect your SOAP or JSONv2 endpoints. That's exactly the gap this post closes.

 

Step 0 — Know What You're Up Against

Before you deny anything, find out who's actually using Basic Auth today. Flipping a global deny without knowing your dependencies is how live integrations break.

The Machine Identity Console lists all inbound integrations on your instance, including which ones are currently authenticating with Basic Auth. Start there: it tells you exactly which third-party integrations you need to migrate to OAuth/mTLS or carve out before you tighten the screws.

For any account that must keep Basic Auth (at least temporarily), apply this hygiene baseline first:

  • Web Service Access Only = true — the account can't log into the UI, only call APIs.

  • Strong, complex password — long, random, unique.

  • Least-privilege role — only the roles the integration genuinely needs, nothing inherited "just in case."

  • IP restriction wherever feasible — lock the account to the integration's known source ranges.

Rule of thumb: every surviving Basic Auth account should be WSAO=true, least-privilege, IP-restricted, and on your migration list. Carve-outs are temporary, not permanent.

 

Part A — Restricting Basic Auth on REST APIs

 

Step 1 — Lock It Down Globally

Create a Global REST API Access Policy and associate Inbound Authentication Profiles for only the methods you want to allow — OAuth, mTLS, and ID Token (Federated Token). Deliberately leave Basic Auth out.

 

Global API Access PolicyGlobal API Access Policy

 

Remember the core rule from Part 1: once a policy is linked, only the methods in that policy are allowed — everything else is blocked. With Basic Auth absent from the global policy, it's now denied across all REST APIs.

Remember:
No policy = default access (OAuth, ID Token, mTLS, and Basic Auth all work).
Policy linked = only what's in the policy works. Omit Basic Auth = Basic Auth blocked.

 

Step 2 — Carve Out the Integrations That Genuinely Need Basic Auth

Some legacy integrations can't move to OAuth yet. Because the most specific policy wins (Part 1), you create an API-level policy that overrides the global one for just that API — and in it, you include Basic Auth alongside the other methods you still want to accept.

Example: a CRM integration must reach the Table API using Basic Auth. Create a Table API policy and add the Basic Auth profile plus mTLS (and any others you need).

 

Overriding API Access PolicyOverriding API Access Policy

 

Common mistake: if you add ONLY Basic auth to this override, you just blocked OAuth and mTLS for that API. Always include every method you still want to accept.

 

Step 3 — Constrain the Carve-Out with Authentication Policies

A carve-out shouldn't mean "Basic Auth from anywhere, by anyone." Attach one or more Authentication Policies to the Basic Auth profile, using IP, Group, or Role filter criteria. Multiple policies use OR logic — if any policy evaluates true, the profile passes.

The recommended pattern: allow Basic Auth only for an explicitly exempted set of WSAO service accounts (for example, members of a dedicated "Basic Auth Exempted" group), and optionally only from trusted IP ranges.

 

Basic Auth With Restrictions Auth ProfileBasic Auth With Restrictions Auth Profile

 

 

 

API Authentication Policy for 'Basic Auth'  Auth ProfileAPI Authentication Policy for 'Basic Auth' Auth Profile

 


So the effective rule becomes: "Basic Auth on the Table API, but only for these exempted service accounts,  OR only from our corporate network."

 

Step 4 — Narrow the Table Scope

The Table API policy lets you pin the policy to individual tables rather than the whole API. If the CRM integration only needs `csm_consumer`, scope the policy to `csm_consumer` — the carve-out doesn't have to open every table.

 

API access Policy for Table APIAPI access Policy for Table API

 

 

Step 5 — Lock High-Privilege Accounts with MIAC (Zurich and later)

If the carve-out account is a high-privilege service account, you may still worry it could be repurposed to call unrelated APIs. Machine Identity Access Controls (MIAC) flips the model to deny-by-default: once enabled for a service account, all API access is blocked except the APIs and tables you explicitly allow — regardless of the account's roles, even admin.


Example: restrict the CRM service account to the Table API for `csm_consumer` only. If someone later tries to use it to pull `incident`, MIAC blocks it. MIAC works hand-in-hand with your REST API Access Policy.

 

6_Policy for CRM integration MIAC.png

 

 

Part B — Restricting Basic Auth on SOAP & Non-Public Processors

This is the surface most admins forget. REST API Access Policies don't touch it. Instead, there's a lesser-known field on the Authentication Profile table (`std_http_auth`).

 

The Lesser-Known Field

On an Authentication Profile, enable "Apply to all none public processors."

Yes, the checkbox label has a typo — it reads "Apply to all none public processors" (should be "non-public"). Search for it exactly as written so you can find the field.

 

When this flag is set, the profile is evaluated for all non-public processors — SOAP, JSONv2, PDF, Excel, export, and the rest — but not the REST API processor (REST is governed by Part A using the REST API access policies). So the play is straightforward: create a profile that allows OAuth, mTLS, and ID Token, enable this flag, and do not create a global Basic Auth profile for non-public processors.

 

7_Auth_profile for non public Process.png

 

 

How Evaluation Works

Precedence:
- No processor-to-profile mapping for a given processor → the platform uses the active GLOBAL profile (the one with "Apply to all non-public processors = true").
- A processor-to-profile mapping EXISTS for that processor → the mapping OVERRIDES the global profile for that processor only.

 

Step 1 — Create the Global Non-Public-Processor Profile

Create (or designate) an Authentication Profile allowing OAuth, mTLS, and ID Token, and enable "Apply to all none public processors." With no Basic Auth profile carrying this flag, Basic Auth is now denied across every non-public processor by default.

 

8_Auth profile mTls for non public.png

Note: You may have to add this field "Apply to all none public processors" to the form layout.

 

Step 2 — Override for a Specific Processor That Needs Basic Auth

When one processor genuinely needs Basic Auth (or a different method), create a Processor Access Policy mapping in the `sys_processor_profile_mapping` table for just that processor. This overrides the global behavior for that processor alone.

Example: a reporting tool calls `PDFProcessor` and you want to require OAuth specifically for it.

 

Overriding Processor Access PolicyOverriding Processor Access Policy

 

Common mistake: a processor mapping overrides the global non-public-processor profile for that processor — it doesn't add to it. Each mapping row points to a single authentication profile, so if you add only a Basic Auth mapping, you've just blocked OAuth and mTLS for that processor. Add a separate mapping row for each method that processor still needs to accept.

If instead a legacy tool must hit a specific processor with Basic Auth, map that processor to a Basic Auth profile here.

 

Step 3 — Constrain the Override

Just like REST, the overriding profile can carry Authentication Policies with IP and Group restrictions. Apply the same exempted-WSAO-only, IP-restricted pattern from Part A, Step 3.

 

Putting It Together

Here's how the platform evaluates an incoming request across both surfaces — REST on the left (Part A), non-public processors on the right (Part B):

 

basic_auth_eval_flow.svg

 

Your end state across both surfaces:

Surface Default posture Carve-out mechanism How it's constrained

REST APIs

Global policy: OAuth + mTLS + ID Token, no Basic Auth

API-level (or table-level) override policy that re-adds Basic Auth

Authentication Policies (exempted WSAO group + IP); MIAC for high-privilege accounts

SOAP & non-public processors

Global profile with "Apply to all non-public processors": OAuth + mTLS + ID Token, no Basic Auth

Per-processor mapping in sys_processor_profile_mapping

Authentication Policies (IP + Group) on the overriding profile

 

The principle is identical on both sides: deny Basic Auth globally, then add it back only where a specific, hygiene-checked integration requires it.

 

Testing & Validation

Verify each surface independently — don't assume.

  1. REST, Basic Auth blocked: call GET /api/now/table/incident with a Basic Auth header for a non-exempted account → expect 401 Unauthorized.

  2. REST, allowed method still works: call the same endpoint with an OAuth bearer token → expect 200.

  3. REST carve-out works (auth policies are OR'd — any one passing grants access):

    • Exempted WSAO account, Basic Auth, from any IP → expect 200 (the account policy passes on its own).

    • Non-exempted account, Basic Auth, from a trusted IP → expect 200 (the IP policy passes).

    • Non-exempted account, Basic Auth, from an untrusted IP → expect 401 (no policy matches).

  4. Non-public processor blocked: call a JSONv2 or SOAP endpoint (for example, GET /incident.do?JSONv2) with Basic Auth → expect 401.

  5. Processor override works: call the overridden processor (for example, PDFProcessor) with the method you mapped → expect success; with Basic Auth (if not mapped) → expect 401.

If any of these don't behave as expected, check policy precedence (most specific wins) and confirm the global non-public-processor profile is Active.

 

Common Mistakes

  • Adding only Basic Auth to an override — this silently blocks OAuth/mTLS for that API or processor and breaks working integrations. Always include every method you still accept.

  • Assuming the REST policy covers SOAP and processors — it doesn't. Part B is a separate mechanism.

  • Leaving a stale global Basic Auth profile active — if a Basic Auth profile still carries "Apply to all non-public processors," your processor lockdown is undone.

  • Carve-out accounts without hygiene — a permanent, broadly-privileged, non-IP-restricted Basic Auth account defeats the purpose. WSAO, least-privilege, IP-restricted, and on the migration list.

Summary

Concept Key point
Two surfaces

REST → API Access Policy; everything else → "Apply to all non-public processors" + per-processor overrides

Discovery first

Use Machine Identity Console to find current Basic Auth integrations before denying

Global deny

Omit Basic Auth from the global REST policy and the global non-public-processor profile

Scoped carve-outs

Re-add Basic Auth only via specific override policies/mappings, constrained by IP/Group/Role

MIAC

Deny-by-default allowlist for high-privilege service accounts (Zurich and later)

Hygiene

Every surviving Basic Auth account: WSAO, strong password, least privilege, IP-restricted

 

Further Reading

Questions about restricting Basic Auth across your inbound surfaces? Drop them in the comments.