Most federation compromises do not break the protocol, they exploit an implementation that skipped one validation step. SAML, OAuth 2.0 and OpenID Connect are mature standards, but every service provider, relying party, client and resource server has to implement its own checks, and a missing audience comparison or a lenient redirect URI match turns a sound design into an account takeover. This guide is for application security testers, identity engineers and the teams who commission penetration tests. It sets out what to test in each protocol, in what order, how to build the tests into delivery pipelines, and how to measure coverage. It is defensive: it lists the checks an implementation must pass, not attack tooling or payloads.
Key takeaways
- Test the relying side hardest: service providers, OAuth clients and resource servers make most validation decisions, and they are written by many more teams than identity providers are.
- Turn the standards into test cases: RFC 9700, RFC 8725, OpenID Connect Core section 3.1.3.7, the OWASP SAML Security Cheat Sheet and OWASP ASVS 5.0 chapters V9 and V10 already describe what must be rejected.
- Every check is a negative test: a passing login proves little; the evidence is that tampered, replayed, expired, wrongly addressed and wrongly signed messages are refused.
- Automate the protocol suite: keep a regression set of negative cases in CI, and use the OpenID Foundation conformance suite for OpenID Connect and FAPI deployments.
- Machine flows count too: client credentials, token exchange and workload federation carry the same validation duties as user sign-in and are often left out of scope.
Why protocol testing needs its own plan
General web application testing finds injection and access control flaws, but federation bugs sit in message handling that scanners rarely exercise. A SAML response that passes signature verification can still log the tester in as someone else if the code reads the identity from an element outside the signed block. An OAuth client that accepts an authorisation code from the wrong issuer works perfectly in every happy-path test. These flaws only appear when a tester deliberately alters one property of a valid message at a time and watches what the implementation accepts.
The Penetration Testing Guide and API Penetration Testing Guide cover scoping and rules of engagement. This guide covers the protocol layer they leave to specialists. For protocol design itself see the OAuth 2.0 Security Best Current Practice (RFC 9700) Guide and the SAML Security Guide.
Scoping: which component makes which decision
Map each component before testing, because the same flaw class belongs to different owners.
| Component | Decisions it owns | Typical owner | Test priority |
|---|---|---|---|
| SAML identity provider | Signing key protection, assertion content, NameID format | Identity team or IdP vendor (customer configuration) | Configuration review |
| SAML service provider | Signature coverage, audience, destination, time bounds, InResponseTo, replay | Every application team | High: many implementations |
| OAuth authorisation server | Redirect URI matching, PKCE enforcement, grant restrictions, code reuse, consent | Identity team or platform (customer configuration) | Configuration and negative testing |
| OAuth client or OIDC relying party | CSRF protection, issuer binding, ID Token validation, token storage | Every application team | High: many implementations |
| Resource server (API) | Audience, scope enforcement, signature and algorithm checks | Every API team | High: often trusts any valid token |
| Machine clients | Client authentication, secret handling, token exchange limits | Platform and integration teams | Often missed |
Hosted identity providers are configured by the customer, so test the settings you control (registered redirect URIs, allowed grants, token lifetimes, signing algorithms) rather than the provider's platform, unless the provider's own testing policy permits more.
SAML service provider test cases
The OWASP SAML Security Cheat Sheet lists the validation every service provider must perform. Each becomes a negative test against a valid baseline response captured from a test identity provider.
| Check | What the SP must do | Negative test (expect rejection) |
|---|---|---|
| Signature coverage | Use only the assertion covered by the verified signature; confirm the signature reference points to that element | Response where the consumed assertion sits outside the signed element (signature wrapping) |
| Unsigned content | Require a signature on the response or assertion as configured | Signature removed entirely |
| Key selection | Verify against a locally configured key; ignore KeyInfo in the message | Response re-signed with a tester key supplied in KeyInfo |
| Schema validation | Validate against local, hardened schemas before use | Malformed or duplicated elements |
| Audience | Audience must equal the SP entity ID | Valid assertion issued for a different SP |
| Destination and Recipient | Destination must exactly match the ACS URL; check Recipient in SubjectConfirmationData | Assertion addressed to another ACS URL, or Destination missing |
| Time bounds | Enforce NotBefore and NotOnOrAfter on the assertion and the subject confirmation | Expired assertion |
| InResponseTo | Match the original AuthnRequest ID for SP-initiated flows | Response for a different request ID |
| Replay | Detect reuse of a response or assertion ID | Same response posted twice |
| Algorithms | Require RSA-SHA256 or stronger; reject SHA-1 signatures and digests | Response signed with SHA-1 |
Also test XML parser hardening (external entities and DTDs disabled) in line with OWASP XML guidance, since the cheat sheet treats input validation as a separate control. Record which library and version performs signature validation: a fix in one SP often needs repeating in every application that copied the same integration code. For forged assertions signed with a stolen IdP key, which no SP check can detect, see the Golden SAML and Federation Trust Abuse Defence Guide.
OAuth 2.0 authorisation server and client test cases
RFC 9700 (Best Current Practice, BCP 240, January 2025) supplies most of the pass criteria. OWASP ASVS 5.0 restates them as verifiable requirements, which makes it a convenient test catalogue.
| Area | Requirement | Source | Negative test |
|---|---|---|---|
| Redirect URI | Exact string match against pre-registered URIs (localhost port exception for native apps) | RFC 9700 s2.1, ASVS V10.4.1 | Added path segment, changed case, extra query parameter, different subdomain |
| Open redirectors | No open redirect on the AS or on pages hosting redirect URIs | RFC 9700 s4.11 | Redirect target pointing off-site through the client's own redirect page |
| PKCE | Mandatory for public clients; S256; verifier enforced when a challenge was sent | RFC 9700 s2.1.1 | Token request with wrong or missing verifier |
| PKCE downgrade | Reject a code_verifier when no code_challenge was sent | RFC 9700 s2.1.1 | Challenge stripped from the authorisation request, verifier sent later |
| Code reuse | Authorisation code usable once | ASVS V10.4.2 | Second redemption of the same code |
| Grant restriction | Each client allowed only the grants it needs; no password grant | RFC 9700 s2.4, ASVS V10.4.4 | Implicit or password grant request for a code-flow client |
| CSRF | One-time state bound to the user agent, unless PKCE support is confirmed | RFC 9700 s2.1, ASVS V10.2.1 | Callback with missing, reused or foreign state |
| Mix-up | Clients using several ASs bind the issuer to the request and check the iss response parameter (RFC 9207) | RFC 9700 s4.4, ASVS V10.2.2 | Response carrying a different issuer than the one the request went to |
| Refresh tokens | Public clients' refresh tokens sender-constrained or rotated | RFC 9700 s2.2.2, ASVS V10.4.5 | Old refresh token used after rotation; token replayed from another client |
| Consent | User consents to each authorisation request where client identity is not assured | ASVS V10.7.1 | Silent grant to a newly registered client |
Detail on each control sits in the OAuth Refresh Token Rotation and Expiry Guide and the OAuth for Native and Mobile Apps Guide.
OpenID Connect relying party test cases
OpenID Connect Core 1.0 section 3.1.3.7 defines ID Token validation. Test each step separately:
- Issuer: the iss claim must exactly match the expected issuer identifier. Present a token from a second test tenant on the same provider.
- Audience and azp: aud must contain the client's client_id and no untrusted audiences (ASVS V10.5.4). Present a valid token minted for another client of the same provider, the most common real-world gap.
- Signature and algorithm: the expected alg from registration, never whatever the header says. Test alg set to none and a switch from an asymmetric to a symmetric algorithm, which RFC 8725 section 2.1 describes as key confusion.
- Expiry and issue time: expired tokens refused; tokens with iat far from the current time refused per the client's tolerance.
- Nonce: required in the implicit flow and wherever the request sent one; a token with a missing or different nonce must be refused (ASVS V10.5.1).
- Subject binding: the account is keyed on iss plus sub, not on email (ASVS V10.5.2). Test a second identity with the same email address.
- Logout: back-channel logout tokens must not be accepted as ID Tokens and the reverse (ASVS V10.5.5). See the OpenID Connect Logout and Session Management Guide.
Resource server and JWT test cases
APIs that accept JWT access tokens must run the same checks as an OIDC client, and are often weaker because a gateway is assumed to have done it. RFC 8725 and ASVS V9 give the criteria:
- Algorithm allowlist: only configured algorithms accepted (RFC 8725 s3.1, ASVS V9.1.2).
- Signature before use: no claim read before validation succeeds (ASVS V9.1.1).
- Audience: token minted for another API refused (RFC 8725 s3.9, ASVS V9.2.3, V10.3.1).
- Header-driven key lookup: kid, jku and x5u values must not fetch keys from attacker-chosen locations (RFC 8725 s3.10).
- Token type confusion: an ID Token presented as an access token is refused, using explicit typ values where the issuer supports them (RFC 8725 s3.11 and s3.12).
- Scope enforcement: each endpoint checks the scopes or claims that define delegated authority (ASVS V10.3.2), tested per endpoint, not once per API.
The JWT Security Guide covers token design. Here the point is that each check needs its own failing test.
Where identity fits: machine and agent flows
Client credentials, token exchange, workload identity federation and agent delegation carry the same validation duties but are rarely in test scope because no human logs in. Add these to the plan:
- Client authentication: a confidential client's token request without its secret or private key JWT must fail; a secret from a retired client must fail.
- Federated workload trust: for CI or cloud OIDC federation, test that tokens from another repository, branch or project are refused by the trust policy. See the GitHub Actions OIDC Federation Hardening Guide.
- Token exchange limits: exchanged tokens must not gain scopes or audiences the subject token did not carry. See the OAuth Token Exchange and Delegation Guide.
- Dynamic registration: where clients can self-register, test what a newly registered client is allowed to request. See the OAuth Dynamic Client Registration Security Guide.
Choosing how to test
| Approach | Best for | Limits |
|---|---|---|
| Manual specialist testing with an intercepting proxy | New integrations, custom SAML or OAuth code, annual assurance | Point in time; depends on tester knowledge of the specs |
| Automated negative test suite in CI | Regression after library upgrades and refactoring | Only covers the cases written |
| OpenID Foundation conformance suite | OpenID Connect providers and relying parties, FAPI and FAPI2 profiles | Conformance, not full security assurance; does not cover SAML |
| Library and configuration review | Estates with many applications using shared SDKs | Misses bespoke validation code |
The OpenID Foundation conformance suite is published under the MIT licence and covers OpenID Connect, FAPI and FAPI2, FAPI-CIBA and related profiles; the certification programme runs on the same suite. Small organisations relying on a hosted provider and standard SDKs gain most from configuration review plus a short CI suite. Large organisations with custom federation code, many SPs or open banking obligations need specialist testing and conformance runs.
How to implement a protocol testing programme
The steps below are NHI Mgmt Group recommendations.
- Inventory: list every SAML SP, OAuth client, OIDC RP and token-accepting API, with the library that performs validation and the team that owns it.
- Build test identity providers: a dedicated test tenant and a second tenant for cross-tenant cases, never production signing keys.
- Write the negative catalogue: one case per row of the tables above, each with the expected rejection and log event.
- Pilot on one application per protocol: confirm the cases run safely and that failed logins create no side effects such as account linking.
- Add to CI: run the catalogue on every change to authentication code or identity libraries; block release on regression.
- Schedule specialist testing: annually and on any new federation, using the catalogue as the minimum scope.
- Roll back safely: fixes such as stricter audience or redirect matching can break real integrations, so deploy them behind configuration with a monitored warn period and a documented revert.
Detection and measurement
Each rejected test should leave a log event. If it does not, production attacks will not either. Log validation failures with the reason (audience, signature, expiry, replay, issuer, redirect mismatch) and alert on bursts. Track these metrics:
- Coverage: share of federated applications and token-accepting APIs with the negative catalogue in CI.
- Catalogue pass rate: percentage of negative cases correctly rejected, per application.
- Time to fix: median days to close protocol findings, by severity.
- Library currency: share of applications on supported versions of their SAML, OAuth and JWT libraries.
- Logging completeness: share of negative cases that produced a reason-coded log event.
Common failure patterns
- Testing only the login that works: functional tests confirm sign-in and nobody checks what is wrongly accepted.
- Trusting a valid token from the right provider: missing audience checks let a token for one application work in another on the same tenant.
- Lenient redirect matching: prefix or wildcard matching left in place from development.
- Reading identity from unsigned XML: SAML code that verifies a signature and then queries the document by tag name.
- Leaving machine flows out of scope: client credentials and federation trust policies untested because no user signs in. The OAuth and SaaS integration breaches page collects incidents where integration tokens were the way in.
- One-off fixes: a flaw fixed in one SP while copies of the same integration code remain elsewhere.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev 5 | CA-8 Penetration Testing; SA-11 Developer Testing and Evaluation | Specialist and pipeline testing |
| NIST SP 800-53 Rev 5 | IA-2, IA-8; SC-23 Session Authenticity | The controls under test |
| NIST CSF 2.0 | PR.AA-03; ID.IM-02 | Authentication of users and services; improvement from testing |
| OWASP ASVS 5.0 | V9 (self-contained tokens); V10 (OAuth and OIDC) | Test catalogue |
| MITRE ATT&CK | T1606.002 SAML Tokens; T1528 Steal Application Access Token; T1550.001 Application Access Token | Behaviours the checks constrain |
Practitioner checklist
- Inventory every SP, client, RP and token-accepting API with its validation library and owner.
- Stand up two test tenants and never test with production signing keys.
- Write one negative case per SAML, OAuth, OIDC and JWT requirement in this guide.
- Test audience with a valid token for another client on the same provider.
- Test redirect URIs with path, case, subdomain and query variations.
- Test algorithm handling, including none and asymmetric to symmetric switches.
- Include client credentials, token exchange and workload federation in scope.
- Run the catalogue in CI and the conformance suite for OIDC and FAPI deployments.
- Confirm every rejection writes a reason-coded log event.
Standards and references
- IETF: RFC 9700 Best Current Practice for OAuth 2.0 Security
- IETF: RFC 8725 JSON Web Token Best Current Practices
- OpenID Foundation: OpenID Connect Core 1.0
- OWASP: SAML Security Cheat Sheet
- OWASP: Application Security Verification Standard 5.0
- OpenID Foundation: Conformance Suite
- OpenID Foundation: OpenID Certification
Related NHI Mgmt Group resources: OAuth 2.0 and OpenID Connect Guide, SAML vs OIDC Guide, Burp Suite for Authorised Web Testing Guide, Fuzzing Guide.