Series · 5 partsExternal Perimeter IntelligencePart 5 · You are here
  1. 1The External Perimeter Is a Graph. The Port List Is Only One View.
  2. 2The Domain Resolved. Ownership Was Still a Hypothesis.
  3. 3The Vendor Was Out of Scope. The Trust Boundary Was Not.
  4. 4The Service Was Observed. The Application Was Still Unknown.
  5. 5The Login Page Was Public. The Identity Boundary Was Somewhere Else.You are here

Identity boundary mapping in 60 seconds

A public application redirects the browser to an identity provider. The user signs in, returns to /callback, and receives an application cookie. It is tempting to record “OIDC login” and move on. But the visible login page is only the first frame of a longer authority decision.

The application must still decide:

  • which issuer and client this response belongs to;
  • whether the callback belongs to the flow that this browser started;
  • which token type, signature algorithm, key, audience, nonce, and lifetime are acceptable;
  • which external identity becomes which local account;
  • which organisation, tenant, role, and permissions that account receives;
  • when a new local session is created, rotated, refreshed, revoked, or recovered;
  • whether logout, password reset, account disablement, and role changes alter existing sessions.

That sequence—not the login form—is the identity boundary. An identity provider can authenticate a person correctly while the customer application binds that identity to the wrong tenant, accepts a token intended for another client, preserves a pre-authentication session, or converts an ordinary claim into administrative authority.

The external pentester’s task is therefore not to attack the provider. It is to reconstruct the customer-controlled identity contract, then use approved test identities to verify the decisions that create local authority.

Authentication is not the same decision as authorization

Authentication answers a narrow question: which identity did a trusted authenticator establish? The business application has a different problem: what may that identity do here, in this tenant, with this object, at this point in the workflow?

OpenID Connect makes the distinction visible. An ID Token carries claims about an authentication event and an end user. The relying party still has to validate the token and decide how its claims map into local state. In particular, the OpenID Connect Core specification defines iss, sub, and aud as separate identity coordinates. A subject value is locally unique within an issuer; the same sub under a different issuer is not the same identity. The audience identifies the client for which the token was issued. A valid signature without those policy checks is not sufficient.

The JWT security best-practice document makes the application responsibility explicit: keys must belong to the trusted issuer, the issuer-subject pair must be valid for the application, and an audience intended for the recipient must be present and checked where tokens can serve multiple applications. See RFC 8725.

This produces a useful model:

The provider establishes an external identity. The application decides whether that identity is acceptable, which local principal it becomes, and which authority that principal receives.

When those three steps are collapsed into “SSO works,” the highest-value customer-controlled decisions disappear from the test plan.

The visible flow hides seven decision points

public entryLOGIN START authorization serverISSUER · CLIENT browser returnCALLBACK · STATE token policySIG · AUD · NONCE account bindingISS + SUB → USER authority conversionTENANT · ROLE · SCOPE local sessionROTATE · EXPIRE application actionOBJECT · EFFECT negative controlMUST BE DENIED REAL BOUNDARYexternal identity becomes local account, tenant, role and session authority
The login page starts the journey. Customer-controlled authority is created only after callback correlation, token policy, local account binding, role and tenant conversion, and session creation.

The seven points require different evidence.

Decision pointEvidence to preserveSecurity question
Login startApplication route, parameters, cookies, response, timestampDid the application initiate one specific flow for this browser?
Authorization requestIssuer host, client ID, redirect URI, scopes, state, nonce, PKCEIs the request bound to the correct provider, client, and return route?
CallbackReturn path, response mode, code or assertion, correlation stateCan a response be substituted, replayed, or attached to another flow?
Token validationToken type, header, claims, key source, validation resultAre signature, issuer, audience, nonce, time, and token purpose enforced?
Account bindingIssuer-subject pair and local account identifierCan two external identities collide or link to the same local account?
Authority conversionTenant, organisation, role, group, scope, entitlement sourceWhich claim or local record grants authority, and which one wins?
Local session and actionsCookie lifecycle, account context, API calls, object effectsDoes authority stay correct across login, refresh, change, and logout?

Map the identity contract before testing it

The first pass should be observational. Start from the approved application entry point and record the redirect chain without attempting to enumerate provider tenants or probe real user accounts. Public metadata, customer configuration, browser requests, response headers, and the supplied test accounts are usually enough to establish the contract.

For each application, record:

  1. Entry point: the customer URL that starts login, including regional, partner, admin, mobile, and recovery variants.
  2. Protocol role: relying party or client, authorization server or identity provider, resource server, and any broker between them.
  3. Issuer and endpoints: exact issuer identifier, authorization and token endpoints, key source, callback routes, logout routes, and recovery routes.
  4. Client context: client ID, redirect URI, response type, response mode, scopes, and whether PKCE, state, and nonce appear.
  5. Identity key: the fields used to bind the provider identity to a local account. Preferably this is the stable issuer-subject pair—not an editable email address or display name.
  6. Authority source: local database, provider group, application role, tenant membership, invitation, support override, or a combination.
  7. Session model: pre-login cookie, post-login cookie, refresh behavior, idle and absolute lifetime, concurrent sessions, logout, revocation, and device or tenant switching.
  8. Lifecycle edges: first login, invitation acceptance, account linking, email change, role change, tenant removal, password reset, MFA recovery, disablement, and deletion.

This inventory turns “uses SSO” into a falsifiable system model. Unknown fields stay marked unknown; they are not silently filled with provider defaults.

Protocol correctness is necessary, but policy creates the boundary

RFC 9700, the OAuth 2.0 Security Best Current Practice, recommends exact matching of registered redirect URIs, authorization code flows rather than exposing access tokens in browser URLs, and protections such as PKCE against authorization code injection. Those controls matter, but a protocol-compliant exchange can still lead to an unsafe local decision.

Consider four examples:

A trusted issuer, wrong audience. The signature is genuine and the token is current, but it was created for another client in the same identity estate. If the application verifies only the signature, it may accept authority never issued to it.

A correct user, wrong tenant. The issuer and subject are valid, but an organisation identifier is taken from a browser parameter after login rather than from verified membership. Authentication succeeds; tenant authorization fails.

A correct claim, wrong meaning. A provider group called billing-admin may be informational in one application and privileged in another. The danger is not the claim’s authenticity. It is an undocumented conversion from a broad directory group into a local administrative role.

A correct login, stale local session. The account is disabled or removed from a tenant at the provider, but an application session continues with cached authority. The authentication event was correct when it occurred; the lifecycle contract failed afterward.

The test plan should therefore distinguish two layers:

  • protocol acceptance: can this response, token, or assertion be accepted by this client?
  • business authority: after acceptance, which local account, tenant, role, objects, and effects become reachable?

Testing only the first layer produces a token checklist. Testing both layers produces an identity assessment.

The session is where external identity becomes local persistence

Federated login does not remove application session security. It moves the authentication event to another system, then asks the customer application to create and maintain local state.

Capture the unauthenticated cookie before login and compare it with the authenticated cookie after the callback. A privileged transition should not simply bless attacker-known pre-authentication state. OWASP’s session fixation testing guidance frames the core question: does the application issue a fresh session after successful authentication?

Rotation at login is only the first control. The same analysis belongs at every authority change:

TransitionExpected local behavior
Anonymous → authenticatedReplace or safely rotate the session; bind it to the authenticated principal
User → administratorRe-evaluate authority and rotate sensitive session state where appropriate
Tenant A → tenant BChange tenant context explicitly; prevent object and cache bleed
RefreshPreserve correct issuer, client, subject, tenant, and scope constraints
Password or MFA recoveryInvalidate or deliberately govern older sessions and recovery artifacts
Role or group removalRemove effective authority within a defined, testable interval
Account disablementDeny new sessions and revoke or expire existing sessions according to policy
LogoutTerminate the local session; distinguish local logout from provider SSO logout

Cookie flags are useful evidence, not a complete conclusion. Secure, HttpOnly, SameSite, Domain, Path, and lifetime settings describe how the browser handles an artifact. They do not prove that the server rotates it, revokes it, binds it to the correct tenant, or stops accepting it after the account changes.

Build a role and tenant matrix from controlled identities

Identity testing becomes defensible when every result has a comparison. Ask the customer for the smallest synthetic identity set that represents the important boundaries: unauthenticated, ordinary user, a second user in the same tenant, a user in another tenant, and one approved privileged role. Use customer-owned data and reversible actions.

The OWASP role-definition testing guidance starts from identifying and documenting the application’s roles. For a real assessment, extend that role list into a matrix of identity, tenant, object ownership, workflow state, and expected effect.

Test identityTenant contextObject relationFunctionExpected result
AnonymousNoneNoneView account dashboardDeny and start login
User AMeridianOwnerRead own invoiceAllow
User BMeridianSame tenantRead User A invoiceDeny unless explicitly shared
User CNorthwindOther tenantRead User A invoiceDeny
Billing adminMeridianTenant managedApprove invoiceAllow with recorded audit event
User AMeridianOwnerAssign admin roleDeny

The most important column is the expected result. Without it, an HTTP 200 is merely an observation. With it, the same response can prove either intended access or an authorization failure. Record the downstream effect as well: data returned, record changed, message queued, privilege granted, or nothing happened.

Negative controls make the finding believable

An identity result needs more than one successful request. A strong proof contains a valid control, an invalid comparison, and an observable effect.

identity hypothesisCLAIM → AUTHORITY? positive controlOWNER · ALLOW same tenantNON-OWNER · DENY other tenantDENY effect verificationREAD · CHANGE · EVENT repeat and boundONE VARIABLE defensible resultEVIDENCE · IMPACT CHANGE ONE VARIABLEidentity, tenant, role, object, state or session age STOP CONDITIONunexpected real-user data, cross-tenant effect or provider impact A successful request without a denied comparison does not locate the authorization boundary.
Change one authority variable at a time. The result becomes reportable only when the expected control, denied comparison, and real application effect establish the boundary.

Useful negative controls include:

  • the same object with a different approved user;
  • the same role in a different approved tenant;
  • the same session after logout, role removal, or account disablement;
  • the same callback with missing or mismatched flow correlation in a controlled test;
  • the same signed token with the wrong intended audience in a customer test environment;
  • the same function reached through UI and API routes;
  • the same business action in an invalid workflow state.

Do not turn this matrix into indiscriminate token mutation. The purpose is to isolate the customer’s validation and authorization decisions with the minimum requests necessary, not to flood an identity provider with malformed traffic.

Keep the provider outside the line of fire

The identity provider may be architecturally important and contractually out of scope. That is normal. The assessment can still evaluate the customer-controlled relying party, client registration, callback handler, account-linking logic, local role conversion, API authorization, and session lifecycle.

Before active testing, make the boundary explicit:

  • approved customer applications, callback routes, tenants, accounts, roles, and source addresses;
  • whether the customer can provide a test identity tenant or isolated federation configuration;
  • permitted login volume and MFA behavior;
  • prohibited actions such as password spraying, real-user discovery, unsolicited MFA prompts, provider-tenant enumeration, or testing provider infrastructure;
  • test objects and reversible effects;
  • contacts and stop conditions for lockout, cross-tenant access, production data, or unexpected provider behavior.

A provider hostname in a redirect is evidence of a trust relationship, not permission to test the provider. If a hypothesis can only be proved by acting against the provider or real users, stop and request a scope decision or a customer-controlled test environment.

A fictional identity-boundary review

Assume the previous article identified partners.meridian.example as a current, approved partner portal. The public route redirects to a corporate identity service, then returns to /auth/callback and creates a local session.

  1. The analyst records the initial application cookie, redirect chain, exact issuer, client ID, redirect URI, scopes, state, nonce, and PKCE parameters. No provider endpoints beyond the normal customer login flow are probed.
  2. Customer documentation confirms that the portal trusts one issuer and that partner membership should be stored locally. Two synthetic partner tenants and one billing-admin account are supplied.
  3. The valid flow proves that the issuer, callback, token, local account, tenant, and session can produce the expected User A dashboard. This is the positive control.
  4. Comparing the pre-login and post-login cookies shows rotation. Replaying the pre-login cookie after authentication remains anonymous. Session fixation is not supported.
  5. The application binds the external identity by issuer and subject, not by editable email. A second identity with the same synthetic email under the approved alternate test issuer does not collide with the first local account.
  6. The UI takes a workspace parameter, but the API derives effective tenant membership from the local session. Changing the browser parameter changes presentation only; cross-tenant objects remain denied.
  7. One problem remains: the billing-admin role is copied into the session at login and is not re-evaluated after customer administrators remove the role. The old session can approve a synthetic invoice until its eight-hour expiry. A new session is correctly denied.
  8. The analyst records the positive admin control, the removed-role negative expectation, the old and new session comparison, the synthetic approval event, timestamps, and cleanup. Testing stops after one reversible object demonstrates the stale-authority window.

The finding is not “the provider issued a bad token.” The provider authenticated and described the test identity correctly. The customer application retained local authority after the source of that authority changed. The fix therefore belongs in session invalidation, entitlement refresh, and revocation design—not in the provider’s login screen.

Evidence matrix

Observation or testWhat it supportsWhat it cannot proveRequired next step
Public route redirects to an identity providerAn identity relationship exists in this browser flowProvider ownership, tenant scope, or customer authorizationRecord exact issuer, client, callback, and customer confirmation
OIDC metadata exposes endpoints and keysPublished protocol configuration for an issuerThat the application trusts or validates every fieldCompare metadata with client behavior and configuration
Token signature validatesToken integrity under the selected key and algorithmTrusted issuer, intended audience, valid subject, or roleVerify the complete application acceptance policy
ID Token contains email, groups, tenant, and rolesThe issuer asserted those claimsWhich claims create local identity or authorityTrace account binding and role conversion
Callback succeeds with a normal flowOne positive authentication path worksResistance to substitution, replay, or correlation failureRun bounded negative controls
Cookie flags are presentBrowser handling restrictions existRotation, server revocation, tenant binding, or logoutCompare session behavior across lifecycle transitions
Different role sees different navigationThe UI presents role-specific contentServer-side function or object authorizationCompare direct approved API requests and effects
Cross-tenant request returns a generic denialOne tested path enforced a tenant boundaryAll object classes, alternate routes, or workflow statesExpand by risk and object class, not by blind enumeration
Removed role remains active in old sessionLocal authority can outlive its source for the measured timeUniversal account takeover or provider failureBound duration, functions, revocation behavior, and impact
Logout removes the browser cookieClient-side session artifact was clearedServer-side invalidation or provider-wide logoutReuse the old artifact safely and distinguish logout domains

What defenders should receive

The deliverable should let identity, application, and platform teams see the same boundary.

Identity contract. Issuer, client, callback, key source, subject key, accepted token types, audience, correlation controls, and lifecycle assumptions.

Authority conversion map. External claims and local records that determine account, tenant, role, scope, and exceptional access. Conflicts and precedence rules should be explicit.

Session lifecycle. Creation, rotation, refresh, expiry, logout, revocation, role change, tenant removal, disablement, and recovery behavior, with measured windows rather than vague labels.

Permission matrix. Synthetic identities, roles, tenants, objects, workflow states, expected results, observed results, and evidence references.

Rejected hypotheses. Controls that worked should remain in the record: audience mismatch was rejected, pre-login state was rotated, cross-tenant reads failed, account identities did not collide. They define the tested boundary and prevent future teams from repeating the same work.

Actionable finding. The smallest failing policy, its application owner, reproducible evidence, bounded effect, cleanup, and a retest that includes both positive and negative controls.

The series ends where active testing can finally begin

This series started with a simple claim: the external perimeter is a graph, and a port list is only one view. Each article then removed one dangerous shortcut.

  1. A company name became an entity graph, not an automatic target list.
  2. A domain relationship became attributed evidence, not assumed ownership or scope.
  3. A third-party platform became a customer-controlled trust boundary, not permission to test the vendor.
  4. A passive service observation became a current application model, not a vulnerability claim.
  5. A public login page became an identity, tenant, role, and session contract, not proof that authorization was understood.

Only now is the test team ready to move from intelligence into application hypotheses. It knows which organisation owns the surface, which names and services are current, which suppliers carry authority, which application workflows matter, which identities and tenants are approved, and what evidence will distinguish intended access from a security failure.

That is the real value of quieter external pentesting. Passive intelligence does not replace active testing. It ensures that each active request reaches a boundary the customer actually owns, asks a question the application can answer, and produces evidence a defender can use.

Sources & freshness

How current is this note?

Sources checkedAugust 29, 2026

The latest source-review, content-update, or publication date is shown.

ReviewPublic sources reviewed

Primary public records were checked. Environment-specific behavior remains outside the claim unless separately reproduced.