Home

Documentation

Documentation

Testing Your Resource App (SAML)

Verify that your protected API or MCP server accepts access tokens whose identity came from a SAML assertion, and that it resolves the right user.

Two testers, two purposes

Test Your Resource App (Beta): mints a real ID-JAG from your own SAML IdP, redeems it at your auth server, calls your API, and exports a signed conformance log. Use this when you run your own Authorization Server.

Test Your Resource App (guided): registers your resource against the playground's IdP and walks the five-step flow, using either the playground's Authorization Server or your own. Start here to verify token validation and user mapping.


Before you start

  1. Token validation: signature, iss, aud, exp, scopes. See REST API Setup (SAML).
  2. User resolution from sub_id: the composite key. This is what SAML testing actually exercises.
  3. Health endpoint: expose /health returning HTTP 200.
  4. If you run your own auth server: the validation order and cross-check in Own Auth Server (SAML).

The five steps

#StepWhat to check
1SAML SSOYou receive a signed assertion. Nothing of yours is involved yet.
2Assertion → Refresh TokenThe IdP accepts the bare <saml:Assertion>.
3Refresh Token → ID-JAGInspect the decoded ID-JAG: aud must equal your Authorization Server's issuer, and sub_id must carry the signed-in user's NameID.
4JWT Bearer GrantYour auth server (or the playground's) redeems the ID-JAG. Check iss, aud and scope on the resulting access token, and that sub_id was forwarded.
5API / MCP callA 200 means the chain works. Now verify it resolved the right user.

Verifying user resolution

A 200 on step 5 is necessary but not sufficient. A server that resolves users wrongly still answers 200. It just answers for the wrong user, or quietly creates a new one on every call. Neither shows up in a single happy-path run, so test for them directly:

Test with two issuers, same NameID

The collision only appears with more than one SAML issuer. Run the flow twice with the same NameID federated from two different IdP connections (or two SAML apps with different entity IDs), then confirm your database holds two distinct users, not one.

If you get one row, you are keying on the NameID alone. See Overview.

Also worth checking:

  • A NameID that is not an email. Switch the connection's NameID format to persistent or transient and re-run. The email claim will be absent, so confirm your JIT provisioning still succeeds instead of inserting a null or throwing.
  • An absent sp_name_qualifier. If your IdP omits it, confirm repeated logins resolve to the same user rather than provisioning a duplicate each time. A = comparison against NULL is the usual culprit.
  • A restarted Authorization Server. If anything of yours is keyed on the access token's sub, restart the AS and re-run. That id is opaque and AS-local (the playground regenerates it per process), so previously-stored rows are orphaned. Your data should still resolve, because it was keyed on sub_id.

Re-running steps

Fix and re-run only the failed step:

  • 401 / 403 on step 5: Fix your middleware, call again. The access token is still valid.
  • invalid_grant on step 4: The message names the reason. Shape and cross-check failures (issuer_mismatch, provider_not_saml_enabled, sp_name_qualifier_mismatch) mean your registered connection and the asserting IdP disagree. See Error Codes.
  • jti_replay on step 4: An ID-JAG is single-use. Re-run step 3 for a fresh one rather than replaying.
  • Expired ID-JAG: They last 5 minutes. Re-run step 3.

Conformance log

The Beta tester exports a signed JSON record containing the ID-JAG, the access token, and the API response. It is durable evidence that your resource app redeems SAML-derived grants correctly, which is useful when an IdP vendor asks you to demonstrate conformance. See Verifying Conformance Logs.


Next step

For IdP-side configuration (creating the SAML app, assigning users, registering the agent and its resource connection), see Enabling Cross App Access for SAML-Based Resource Apps.

These materials and any recommendations within are not legal, privacy, security, compliance, or business advice. These materials are intended for general informational purposes only and may not reflect the most current security, privacy, and legal developments nor all relevant issues. You are responsible for obtaining legal, security, privacy, compliance, or business advice from your own lawyer or other professional advisor and should not rely on the recommendations herein.

Presented byOkta Developer

Copyright © 2026 Okta. All rights reserved.