SurePassID Identity Provider
EAM EntraId Test Client Setup Guide
Purpose: Walk through creating a test Microsoft Entra ID External Authentication Method (EAM) client, running the Entra sign-in that invokes SurePassID as the MFA provider, and — critically — capturing the exact values from Entra that must be entered into the SurePassID
Eam.*configuration to complete wiring on the IdP side.For OIDC follow the instructions from your Relying Party (vendor application documents). idp.surepassid.com is used as the default host, but in an non-cloud environment this will be the host the the SurePassID Identity Provider is installed on.
Roles recap
| Role | Who | In this guide |
|---|---|---|
| OpenID Provider (OP) | SurePassID IdP | Exposes /eam/{domain}/*, issues the MFA
id_token. |
| Relying Party (RP / client) | Microsoft Entra ID | Redirects the user to us, consumes the id_token. |
| Subject | The Entra test user | Completes SurePass MFA. |
Entra ID is the client; SurePassID is the provider. EAM only satisfies the MFA (second factor) — Entra ID still does the first factor. This is a Microsoft limitation.
1. Prerequisites
On the SurePassID side (must exist before Entra config):
- A tenant/partner with a domain (used in
/eam/{domain}/...). - That partner has signing certificate** configured
(
SSOCert+SSOPassword). - The IdP is reachable over HTTPS at a public host,
e.g.
https://eam.surepassid.com. - The three SurePassID Identity Provider endpoints resolve for your
SurePassID account (domain) (even before final config):
https://idp.surepassid.com/eam/{domain}/.well-known/openid-configurationhttps://idp.surepassid.com/eam/{domain}/jwkshttps://idp.surepassid.com/eam/{domain}/authorize
On the Entra side:
- A test Entra ID tenant (do not pilot on production).
- Roles: Authentication Policy Administrator (or Global Administrator) to create the EAM method, and Application Administrator to register the app.
- One or more test users and a test security group to scope the method.
2. Entra ID setup process
Step 2.1 — Register the EAM application (App registration)
Entra Admin Center → Entra ID → App registrations → New registration.
- Name:
SurePassID EAM (Test). - Supported account types: Single tenant (this test tenant).
- Redirect URI: leave for now; the EAM feature supplies the platform redirect.
- Register.
🔑 CAPTURE — Application (client) ID. On the app Overview blade copy Application (client) ID (a GUID). This is entered as the App ID field of the External Authentication Method in Step 2.3. (It is not SurePassID
Eam.ClientId— that is the separate free-form Client ID string you set in Step 2.3.)
🔑 CAPTURE — Directory (tenant) ID. Also on Overview, copy Directory (tenant) ID. You need it to build the Entra OIDC metadata URL (
Eam.EntraOpenIdConfigurationUrl).
Step 2.2 — Note Entra's OpenID metadata URL
Entra's per-tenant OIDC discovery (used by SurePassID to validate
Entra's signed request object):
https://login.microsoftonline.com/<Directory (tenant) ID>/v2.0/.well-known/openid-configuration
🔑 CAPTURE — Entra OpenID configuration URL → SurePassID
Eam.EntraOpenIdConfigurationUrl. Optional: open it in a browser and confirm it returns JSON with ajwks_uri. SurePassID uses this to fetch Entra's public keys and verify therequestJWT signature.
Step 2.3 — Create the External Authentication Method
In the Microsoft Entra admin center (https://entra.microsoft.com), External Authentication Methods are managed under the Authentication methods policy, not directly under the Entra ID overview. Navigate:
Entra admin center → Protection → Authentication methods → Policies → Add external method
Notes if you don't see the option:
- The blade lives under Protection (older tenants showed it under Security). If you only see Entra ID → Overview, expand the left nav and open Protection (shield icon), then Authentication methods, then the Policies tab.
- Direct link:
https://entra.microsoft.com/#view/Microsoft_AAD_IAM/AuthenticationMethodsMenuBlade/~/AdminAuthMethods - Add external method only appears on the Policies tab (not on User registration details or Monitoring). If the tab shows only built-in methods (FIDO2, Passkey, etc.), scroll to the bottom of the methods list — "Add external method" is the last entry.
- Requires an Entra ID P2 license (you have this) and that you sign in with a role that can edit the authentication methods policy — Authentication Policy Administrator or Global Administrator. If you are only a lower-privileged admin the method list renders read-only and the Add external method button is hidden.
- External Authentication Methods is a relatively recent feature; ensure you are in the entra.microsoft.com portal (not the legacy Azure AD blade in portal.azure.com), where the option may not be surfaced.
The Add external method form has exactly three fields. Here is where each comes from and how it maps to SurePassID config:
- Client ID — a free-form identifier string you
choose for this method (for example
entraid-your-company-identifier). This is not the app-registration GUID. Entra places this exact value in theclient_idclaim of the signed request object it sends to your authorize endpoint, and SurePassID validates it againstEam.{domain}.ClientId(falling back toEam.ClientId). It also becomes the issuedid_tokenaud. It must matchEam.ClientIdexactly (case-sensitive). - Discovery Endpoint — the
SurePassID per-domain OIDC discovery URL (this points
Entra at your IdP so it can fetch your JWKS and endpoints):
https://saml2.surepassid.com/eam/<domain>/.well-known/openid-configuration - App ID — the Application (client) ID
GUID from the app registration in Step 2.1 (for example
7f3c9a12-4be8-4d61-9c02-1e5a8b7d6f40). This ties the EAM method to the Entra app registration you created; it is a different value from the Client ID string above.
⚠️ Do not confuse Client ID and App ID. They are two separate fields:
- Client ID = the string you invent (e.g.
entraid-your-company-identifier) → must equal SurePassIDEam.ClientId, is sent as the request objectclient_id, and becomes the tokenaud.- App ID = the app-registration GUID from Step 2.1 → links the method to the app registration.
Earlier revisions of this guide incorrectly said
Eam.ClientIdwas the app-registration GUID. It is the Client ID string, not the GUID.
After filling the three fields, Save.
ℹ️ There is no redirect URI field on this form. The Add external method blade exposes only the three fields above (Client ID, Discovery Endpoint, App ID). Entra's EAM feature uses a fixed, Microsoft-controlled
redirect_urithat you do not enter anywhere in the portal — so it is correct that you see no redirect field after saving.
ℹ️
redirect_urinow defaults automatically — no capture needed for the standard flow. Entra's EAM feature always uses the fixed, Microsoft-controlled valuehttps://login.microsoftonline.com/common/federation/externalauthprovider. SurePassID uses this as the default allow-list entry, so you do not have to enter it. Only setEam.RedirectUris(orEam.{domain}.RedirectUris) to override the default — e.g. for a national cloud (US Gov, China) whose host differs (see the national-cloud table in §4 for the exact values). The value is still validated (see §4): aredirect_urithat matches neither the default nor the override is rejected, preserving open-redirect protection.
ℹ️
acris now derived automatically — no capture needed for the standard flow. SurePassID computes the returnedacrfrom the actual second factor (see §4a for the rule and matrix). For every SurePassID MFA method the derived value ispossessionorinherence, which Entra accepts.Eam.Acris therefore optional and only used as an override when a tenant's policy demands a different exact string (see §4a). Sending a barepossessionis rejected (AADSTS5001257 / AADSTS5001258).
Step 2.4 — Enable & scope the method
- In the External method, set Enable = Yes.
- Target: add the test users/group only (not "All users").
- Save.
Step 2.5 — (If required) grant the app any consented permissions
For a minimal EAM id_token flow no Graph scopes are
needed. If your tenant policy requires admin consent for the app, grant
it under App registrations → API permissions → Grant admin
consent.
Step
2.6 — About the OIDC scope parameter (no Azure config
needed)
The EAM flow is an authentication flow that returns
an id_token — it is not an OAuth
access-token/resource flow, so there is nothing to configure for scopes
on either side:
- Inbound: Entra sends
scopeon the authorize request. SurePassID requires that it containsopenidand rejects the request otherwise (400 —"The 'openid' scope is required."). Any extra scopes Entra includes (e.g.profile,email) are accepted but ignored. - Advertised: SurePassID's discovery document
publishes
"scopes_supported": ["openid"]only. - Returned:
scopeis not echoed back and noscp/scopeclaim is added to the mintedid_token. There is nothing to "grant" or map — do not add Microsoft Graph or custom API scopes expecting them to flow through.
In short: leave scopes alone.
openidis guaranteed by Entra's EAM feature; SurePassID validates it is present and ignores the rest.
3. Fields to capture → SurePassID EAM config
Config source note (UI-first). EAM configuration is now database-backed (
EamConfigtable, one row per partner).EamConfigresolves each value DB row first, then falls back to theweb.configscoped key (Eam.{domain}.{Setting}) and finally the global key (Eam.{Setting}). Enter the captured values through the Admin UI → EAM Configuration screen (field labels fromOIDC_Admin_UI_Spec.md§4);web.configkeys remain supported only as a fallback for deployments not yet migrated. Direct SQL againstEamConfigis an optional fallback only.
Enter in Admin UI → EAM Configuration (select the
tenant / Partner Id), using the captured values:
| UI field | Column | Source (Entra step) | Notes |
|---|---|---|---|
| Enabled | [Enabled] |
(operator toggle) | Gates all eam/{domain}/* endpoints. Ships off. |
| Client Id (token aud) | [Client Id] |
Step 2.3 Client ID field (free-form string you chose) | NOT the app GUID. Must equal request-object
client_id; becomes token aud. |
| Entra OpenID Config URL | [Entra OpenId Configuration Url] |
Step 2.2 (built from tenant ID) | Validates Entra's signed request object. |
| Redirect URIs | [Redirect Uris] |
Optional override (see §4) | Leave blank to use the built-in Microsoft EAM default; set only to override (e.g. national cloud). |
| ACR | [Acr] |
Optional override (see §4a) | Leave blank to use the derived value; set to override verbatim. |
| Client Secret | [Client Secret] |
Optional shared secret | Not part of the standard EAM contract; write-only in the UI. |
Note: the Step 2.3 App ID field (= the Step 2.1 Application (client) ID GUID) is entered in Entra only to link the method to the app registration. SurePassID does not consume it, so it has no EAM config field.
Multi-tenant resolution. Every value is scoped per
tenant {domain} (the same value in the
eam/{domain}/... route and the account/domain entered on
SSOLogin.aspx). The DB EamConfig row is
keyed by Partner Id; when a value is absent it falls back
to the web.config scoped key, then the global key. Use
per-tenant rows/keys for ClientId (and
ClientSecret); RedirectUris, Acr,
and EntraOpenIdConfigurationUrl may be shared defaults
where tenants agree.
⚠️ Resolution & enablement model — read before setting global defaults.
Precedence per key:
EamConfigDB row (perPartner Id) →Eam.{domain}.{Setting}(web.config scoped) →Eam.{Setting}(web.config global) → built-in default. The DB row is the primary source; the web.config keys below are the fallback for un-migrated deployments. A blank value at one level falls back to the next level, not straight to the derived/built-in default. This matters most forAcrandRedirectUris:
Acr:Eam.{domain}.Acr→Eam.Acr→ derivedpossessionorinherence. If a globalEam.Acris set, it overrides the derived value for every tenant that doesn't set its own — so a stale globalEam.Acr(e.g.possessionorknowledge) will surface even when the tenant key is blank. LeaveEam.Acrunset unless you truly want a fixed acr for all tenants.RedirectUris:Eam.{domain}.RedirectUris→Eam.RedirectUris→ default Microsoft redirect. Same rule: a global value suppresses the built-in default.Enablement:
Eam.Enabledfollows the same fallback. When EAM is disabled for a domain the endpoints return 404 before any other key is read, so global default values sit inert and safe until a domain resolvesEnabled=true(scoped or global). This means global defaults are useful even when you can't authenticate against the global scope.Recommended posture (multi-tenant):
- Leave global
Eam.Enabledfalse/unset and enable per tenant (Eam.{domain}.Enabled=true). A globalEam.Enabled=trueturns EAM on for every resolvable partner domain.ClientId(andClientSecret) should normally be per-tenant — each Entra tenant assigns its own EAM app id, so a shared globalClientIdcausesclient_id-mismatch rejections.RedirectUris,Acr, andEntraOpenIdConfigurationUrlare safe/useful as global defaults (thoughEntraOpenIdConfigurationUrlis per-tenant whenever tenants differ).
Fallback: equivalent web.config keys.
The Admin UI table in §3 is the primary path. The keys below map
one-to-one to the same settings and are read only when no
EamConfig DB row supplies the value — use them for
deployments not yet migrated to the database (Release 2025.4).
| SurePassID key | Source (Entra step) | Example / format | Notes |
|---|---|---|---|
Eam.Enabled / Eam.{domain}.Enabled |
(operator toggle) | true |
Turns the endpoints on. Ships false. |
Eam.ClientId / Eam.{domain}.ClientId |
Step 2.3 Client ID field (free-form string you chose) | entraid-your-company-identifier |
NOT the app GUID. Must equal request-object
client_id; becomes token aud. |
| (no SurePassID key) | Step 2.3 App ID field = Step 2.1 Application (client) ID GUID | 7f3c9a12-4be8-4d61-9c02-1e5a8b7d6f40 |
Entered in Entra only, to link the method to the app registration. SurePassID does not consume it. |
Eam.RedirectUris /
Eam.{domain}.RedirectUris |
Optional override (see §4) | https://login.microsoftonline.com/common/federation/externalauthprovider |
Allow-list. Leave unset to use the built-in Microsoft EAM default. Set only to override (e.g. national cloud); comma/space separated for multiple; exact match. |
Eam.Acr / Eam.{domain}.Acr |
Optional override (see §4a) | possessionorinherence |
Leave unset to use the derived value. When set
(non-blank) it overrides the derived acr verbatim. |
Eam.EntraOpenIdConfigurationUrl /
Eam.{domain}.EntraOpenIdConfigurationUrl |
Step 2.2 (built from tenant ID) | https://login.microsoftonline.com/<tenantId>/v2.0/.well-known/openid-configuration |
Used to validate Entra's signed request object. |
Example single-tenant block (global fallback keys):
<add key="Eam.Enabled" value="true" />
<add key="Eam.ClientId" value="entraid-your-company-identifier" />
<!-- Eam.RedirectUris is optional; omit it to use the default Microsoft EAM redirect. -->
<!-- Eam.Acr is optional; omit it to use the derived possessionorinherence value. -->
<add key="Eam.EntraOpenIdConfigurationUrl" value="https://login.microsoftonline.com/22222222-3333-4444-5555-666666666666/v2.0/.well-known/openid-configuration" />Example per-tenant override for domain contoso (falls
back to the global keys for anything omitted):
<add key="Eam.contoso.Enabled" value="true" />
<add key="Eam.contoso.ClientId" value="entraid-your-company-identifier" />
<!-- Eam.contoso.RedirectUris override only for a non-default redirect (e.g. national cloud). -->
<!-- Eam.contoso.Acr override only if this tenant's policy needs a specific acr string. -->
<add key="Eam.contoso.EntraOpenIdConfigurationUrl" value="https://login.microsoftonline.com/22222222-3333-4444-5555-666666666666/v2.0/.well-known/openid-configuration" />Also confirm (not in web.config, but required): the
{domain}you used in the discovery URL maps to a SurePassID partner that has a signing cert. The domain lives in the URL path, not config.
4. Verifying the redirect_uri (and when to override it)
In the standard Entra EAM flow you do not need to
capture or configure redirect_uri at all — SurePassID
defaults the allow-list to Microsoft's fixed value
https://login.microsoftonline.com/common/federation/externalauthprovider.
Use this section only to verify the value Entra
actually sends, or to determine the correct override
for a non-standard deployment (e.g. a national cloud whose host
differs).
Entra sends a signed request object
(JAR) to the authorize endpoint. Its claims tell you the exact
redirect_uri, client_id,
response_type, response_mode, and
scope. (Note: your tenant may use parameter
mode with an id_token_hint instead of a JAR — the
traced parameters are the same.)
The
acris not captured here — SurePassID derives it automatically (see §4a).
EamAuthorize.HandleAuthorizeAsync already writes these
values to the diagnostic trace once the request object validates — you
do not need to add temporary logging:
- Ensure diagnostic tracing is enabled (
Server.Trace=1inweb.config). - Trigger a sign-in (Step 5) and open the trace log. Look for these
two lines:
- Non-sensitive OIDC parameters (always traced):
EamAuthorize.aspx: request object validated for domain=<domain> clientId=<client_id> response_type=<...> response_mode=<...> scope=<...> redirect_uri=<...>. - PII hints (
login_hint/sub) are logged separately on the "context stashed" line:EamAuthorize.aspx: context stashed for domain=<domain>. login_hint=<...> sub=<...>. Redirecting to SSOLogin.aspx...
- Non-sensitive OIDC parameters (always traced):
- Confirm the
redirect_urion the first line matches the built-in default. If it does (the usual case), leaveEam.RedirectUrisunset. If your tenant's value differs, setEam.RedirectUris(orEam.{domain}.RedirectUris) to that exact value to override the default. Theacrrequires no capture — it is derived topossessionorinherence(see §4a).
The full request object (raw JWT) is only traced when
Saml2.TraceSensitiveData=true. Leave itfalsein production; the claim-level lines above are enough to verify theredirect_uri.
National-cloud redirect_uri values (override reference)
Entra's EAM redirect always follows the pattern
https://{login-host}/common/federation/externalauthprovider;
only the login authority host changes per cloud. SurePassID defaults to
the commercial value, so set
Eam.RedirectUris (or
Eam.{domain}.RedirectUris) to the matching value below
only for a national-cloud tenant.
| Cloud | Login authority host | redirect_uri to configure |
|---|---|---|
| Azure Commercial (Global) — default, no config needed | login.microsoftonline.com |
https://login.microsoftonline.com/common/federation/externalauthprovider |
| Azure Government (GCC High & DoD / "Government High") | login.microsoftonline.us |
https://login.microsoftonline.us/common/federation/externalauthprovider |
| Azure China (21Vianet) | login.partner.microsoftonline.cn |
https://login.partner.microsoftonline.cn/common/federation/externalauthprovider |
Azure Government GCC High and DoD both use the same
login.microsoftonline.usauthority — there is no separate login host that distinguishes them, so theredirect_uriis identical for both. Always confirm the exact value against the captured request object (above) before relying on it.
Tip:
login_hintin the request object is the subject SurePassID will bind the tokensubto; the authenticated user'sLoginName/EamCallback.SubjectMatches).
4a.
acr / amr values SurePassID returns (and how
acr is derived)
Entra validates the minted id_token against two linked
rules:
amrmust be a recognized RFC 8176 method value, emitted as a JSON array (e.g."amr": ["otp"]). Exactly one value is sent (the second factor actually used); multiple values are rejected ('amr' claim must have exactly one value).acr(a single string) must express an authentication type different from the first factor. In EAM the first factor is always the Entra password — a knowledge factor — so the second-factoracrmust exclude knowledge. Entra accepts the combined "OR" formpossessionorinherence; a barepossessionis rejected (AADSTS5001257 / AADSTS5001258).
How SurePassID derives acr (no config
needed): every SurePassID second factor (OTP, push, security
key, SMS/voice, hardware token, biometric) is a possession or
inherence factor — never knowledge. So
SamlAuthContextMapper.ResolveEamAcr(...) always returns
possessionorinherence, which is the value
Entra accepts. This is computed per transaction; there is nothing to
capture from the portal.
Optional override: set Eam.{domain}.Acr
(or global Eam.Acr) to a non-blank value only if a
particular tenant's Conditional Access policy demands a different exact
acr string. When set it is emitted
verbatim and overrides the derived value. The
diagnostic trace records which path was used:
EamCallback.aspx: issuing id_token. ... acr=possessionorinherence acrSource=derived amr=otp ...
EamCallback.aspx: issuing id_token. ... acr=<your value> acrSource=EamConfig amr=otp ...
Returned value matrix
The second factor performed on SSOLogin.aspx maps to the
amr/acr pair below. acr is the
same derived value (possessionorinherence) for every method
because all are non-knowledge factors.
| SurePassID second factor | Device / channel | Factor type | amr (single, in array) |
Derived acr |
|---|---|---|---|---|
| SurePassID Authenticator OTP (software) | Mobile soft token | possession | otp |
possessionorinherence |
| Google Authenticator (software OTP) | Mobile soft token | possession | otp |
possessionorinherence |
| Desktop / other soft-token OTP | Software | possession | otp |
possessionorinherence |
| TapAuth push (Accept/Deny) | Mobile push | possession | hwk |
possessionorinherence |
| FIDO / passwordless push | Mobile push (user-verified) | possession + inherence | fido |
possessionorinherence |
| Push via voice call | Voice | possession | tel |
possessionorinherence |
| SMS one-time code | SMS | possession | sms |
possessionorinherence |
| Voice / IVR one-time code | Voice | possession | tel |
possessionorinherence |
| FIDO2 security key | Roaming hardware key | possession | hwk |
possessionorinherence |
| Hardware / OATH token (FOB, card, matrix) | Hardware | possession | hwk |
possessionorinherence |
AMR to SurePassID authentication-method mapping
Use this table when reading an Entra-decoded EAM
id_token and mapping the returned amr value
back to the SurePassID method the user actually performed.
EAM amr value |
SurePassID method(s) |
|---|---|
otp |
SurePassID Authenticator OTP, Google Authenticator, desktop soft-token OTP, and other software OTP factors |
sms |
SMS one-time code |
tel |
Voice / IVR one-time code, or push delivered by voice call |
hwk |
TapAuth push (Accept/Deny), FIDO2 security key, and hardware/OATH tokens (FOB, smart card, electronic card, matrix card, Treo) |
fido |
FIDO push / passwordless push performed on the enrolled mobile device |
The
amrvalue is the concrete method SurePassID recorded the instant the factor was validated (SsoUtil.RecordAuthMethod), then read back inEamCallback.pwdis never emitted for EAM because Entra already validated the password first factor.
SAML2 vs EAM: the SAML2 assertion still emits the full multi-value AMR list (and appends
mfafor two or more factors). Only the EAM path collapses to the single second-factor value plus the derivedpossessionorinherenceacr.
5. End-to-end test run (Entra-driven)
- In the Admin UI → EAM Configuration for the tenant,
enter the captured values and set Enabled = on, then
Save. (Fallback: set the equivalent
Eam.*web.configkeys andEam.Enabled=true, then recycle the IdP app pool.) - Pre-checks (browser):
GET /eam/<domain>/.well-known/openid-configuration→ 200 JSON;issuer==https://idp.surepassid.com/eam/<domain>.GET /eam/<domain>/jwks→ 200 JSON with a key whosekidis present.
- Sign in as the test user to an app that triggers
MFA (e.g.,
https://myapps.microsoft.comor any app with a Conditional Access policy requiring MFA), so Entra invokes the external method. - After the first factor, Entra redirects the browser to
https://idp.surepassid.com/eam/<domain>/authorize?request=<signed JWT>. - SurePassID validates the request object, then redirects to
SSOLogin.aspx. Complete SurePass MFA (OTP/push/FIDO). - SurePassID posts the
id_tokenback via auto-submit form to Entra'sredirect_uri. - Expected: Entra accepts the factor; sign-in completes. Check Entra → Sign-in logs → the user's entry → Authentication details shows the external method satisfied MFA.
6. Capture checklist (copy/paste)
[ ] EAM Client ID (string you chose) . _______________________ -> Eam.ClientId (= request client_id, token aud)
[ ] Application (client) ID (GUID) ... _______________________ -> Entra EAM "App ID" field only (not a SurePassID key)
[ ] Directory (tenant) ID ........... _______________________ -> used in Eam.EntraOpenIdConfigurationUrl
[ ] Entra OpenID config URL ......... _______________________ -> Eam.EntraOpenIdConfigurationUrl
[ ] EAM redirect_uri ................ default (no config) / override -> Eam.RedirectUris (exact)
[ ] acr override needed? ............ no (derived possessionorinherence) / yes -> Eam.Acr = __________
[ ] SurePass partner domain ......... _______________________ -> {domain} in the endpoint URLs
[ ] Partner signing cert present? ... yes / no
[ ] Discovery URL given to Entra .... https://____/eam/<domain>/.well-known/openid-configuration
[ ] Eam.Enabled ..................... true
[ ] Test user + group scoped ........ _______________________
7. Troubleshooting (Entra-side symptoms → SurePassID cause)
| Symptom in Entra | Likely cause | Fix |
|---|---|---|
| "External method failed" immediately, no SurePassID page | Discovery URL wrong/unreachable, or issuer
mismatch |
Verify discovery returns 200 and issuer exactly equals
https://idp.surepassid.com/eam/<domain>. |
| SurePassID authorize returns 400 | Request-object validation failed | Check Eam.ClientId and
Eam.EntraOpenIdConfigurationUrl; confirm Entra's
kid resolves via its JWKS. |
| SurePassID authorize returns 400 "The 'openid' scope is required" | The authorize request's scope did not contain
openid |
This is Entra-controlled and should always include
openid; if seen, capture the request object (Step 4) and
verify the scope= trace value. No SurePassID config change
fixes this. |
| SurePassID authorize returns 400 "redirect_uri not allow-listed" | The request's redirect_uri matches neither the built-in
default nor an Eam.RedirectUris override |
Verify the value (Step 4). If it is a legitimate non-default host,
set Eam.RedirectUris to it exactly; the error message lists
the expected allow-list values. |
| Token minted but Entra silently rejects the factor | Wrong aud or nonce |
aud must == Eam.ClientId;
nonce echoed verbatim. |
Entra rejects with AADSTS5001257 (amr
unexpected) or AADSTS5001258 (acr
unexpected) |
acr did not express the required type-separation from
the password first factor (e.g. bare possession was
sent) |
Ensure the derived acr is
possessionorinherence (default). Only set an
Eam.Acr override if the tenant policy needs a specific
string; check the acrSource= value in the trace. |
| Entra can't validate token signature | JWKS kid mismatch |
Ensure /eam/<domain>/jwks serves the same cert
used to sign (same kid); no cert rotation mid-flight. |
| 403 "authenticated user does not match subject" | login_hint ≠ SurePass user |
Align the Entra user's identifier with SurePassID
LoginName/Email. |
8. Notes / limits
- This EAM path is a stop-gap MFA integration, not a full OIDC IdP; there is no token endpoint, no code exchange, no refresh token (contract §5).
- Config is now database-backed per partner
(
EamConfigtable, Admin UI inOIDC_Admin_UI_Spec.md§4), so each tenant has distinctclient_id/redirect_uri(and optionalacroverride) without a shared file.web.configEam.*keys remain as a fallback for un-migrated deployments. - Remove any temporary request-object trace logging (Step 4) before production.
© 2013–2026 SurePassID. All rights reserved. Protected by patents pending. SurePassID, the SurePassID logo and design, and Secure SSO are registered trademarks or trademarks of SurePassID, Corp. in the United States and/or other jurisdictions. All other marks and names mentioned herein may be trademarks of their respective companies.
SurePassID 360 Central Avenue #800 St. Petersburg, FL 33701 USA +1 (888) 200-8144 surepassid.com