allow, step_up, review or block.
Your auth provider already knows facts that make the score more accurate. Examples are whether the user verified the email and whether the user passed a second factor. auth_context is the part of the assessment request that carries these facts. An adapter in each NoResponse SDK builds it from the claims that you verified.
Any provider that issues OpenID Connect ID tokens works with the generic adapter, fromOIDC. Examples are Okta, Ping Identity, OneLogin, Zitadel, Authentik and Google. Supabase, Firebase, Amazon Cognito, Microsoft Entra ID, Keycloak and Ory each have a dedicated adapter that reads their own claims. They are listed below. Clerk, WorkOS and Auth0 have their own pages.
Your backend does four things:
- Verifies the ID token: its signature, issuer and audience.
- Calls the API of your provider: gets the account age.
fromOIDC: turns the claims and the overrides intoauth_context.assessments.create: NoResponse returns the assessment.
What fromOIDC reads
fromOIDC reads only the standard claims. Their meaning is the same at every provider:
It never reads
email_verified, amr, act or any organization or role claim from the token, because providers fill those claims differently. Pass each fact that you can prove as an override. The adapter sends it as given.
Where each fact comes from
When your provider cannot supply a fact, leave it out of
auth_context. An absent fact is not false, and it does not move the score.
Install
TypeScript
OIDC_ISSUER: the issuer URL of your provider, exactly as its discovery document gives it, such ashttps://example.okta.com/oauth2/default.OIDC_CLIENT_ID: the client ID of your application. It is the audience of the ID token.NORESPONSE_API_KEY: your NoResponse key, with theassessscope. The TypeScript and Python clients read it themselves. The Go client takes it as an argument. The quickstart tells you how to get one.
Assess the new account
Assess each new account once. Do it on the first authenticated request for asub that your database does not know yet. Do it before you create your own records for the account or give it access. The API answers within 3 seconds.
The ID token is the id_token in the token response. Your callback route receives it after the login redirect.
Your login library can return the verified claims, as openid-client, Authlib and go-oidc do. Then pass those claims to the adapter and skip step 1.
Each sample reads the discovery document on first use, not at startup. So a provider outage fails the assessment of that new account, and your error path handles it. The outage does not stop your server from starting.
The first argument to fromOIDC names your provider in auth_context.provider. It is a lowercase slug of 2 to 32 letters, digits, dots, underscores or hyphens, such as okta. accountCreatedAt is the creation time of the user from the user API of your provider, as an RFC 3339 string. Leave it empty when you do not have it.
TypeScript
ip is the public address of the client. Behind a load balancer, read it from the header that the load balancer sets, such as the last address that it appended to X-Forwarded-For. Never read it from a value that the client controls.
The sub of the token is the account_id. It is stable, and the API of your provider takes it when you act on the result later.
The flow is account creation, so NoResponse waits up to 3000 ms for its full set of sources. To wait only for the sources that answer within 500 ms, send depth: "quick". The other sources still finish later, and their results reach you through the webhook.
Override names
Overrides use theauth_context field names:
- In TypeScript, camelCase:
emailVerified,accountCreatedAt,mfa.ageSeconds. - In Python and Go, snake_case keys:
email_verified,account_created_at,mfa.age_seconds.
Act on the answer
The answer starts withassessment.account, the one current risk of the account. Your code acts on assessment.account.risk.decision, the decision for the flow that you sent:
allow: let the account in.step_up: ask for more proof first, such as a second factor.review: hold the account until your team looks at it.block: refuse the account. NoResponse answersblockafter you set a block threshold and the score reaches it.- Any other value: treat it as
review.
assessment.account.risk.score and assessment.account.risk.reasons tell you why. assessment.detail holds the facts of this assessment, such as its status, the sources that did not answer and the summary facts.
assessment.accountis absent while the first assessment of the account is still pending. Apply your fallback. Then take the final assessment from the webhook when it arrives.- If the call fails or times out, apply the same fallback.
What the adapter sends
This is theauth_context for a new Okta user with a verified email who passed a second factor at login a minute ago:
auth_context for a new Okta user
account.risk.reasons lists each one with its weight:
auth_new_accountraises the score for any new account.auth_email_verifiedandauth_mfa_recentlower it. They make this account different from one with nothing verified.
Dedicated adapters
These adapters read the claims of each provider as well as the standard ones. Every SDK has them. Each adapter takes the verified claims and an optional overrides object, in the same way asfromOIDC, but without the slug.
- Each Go function takes the claims and the overrides as
map[string]any. Passnilfor no overrides. - Times in overrides are RFC 3339 strings, so convert the milliseconds of a provider first.
Supabase Auth
Supabase Auth
TypeScript
fromSupabase, Python from_supabase, Go FromSupabaseClaims.- Reads from the claims: the access token, verified with the JWKS or JWT secret of your project. It reads
session_idandrole, a second factor fromaalandamr, and an anonymous user asassurance_level: low. - Pass as overrides:
email_verifiedandphone_verified,truewhen the user hasemail_confirmed_atorphone_confirmed_at.account_created_atfrom thecreated_atof the user. - Walkthrough.
Firebase Authentication
Firebase Authentication
TypeScript
fromFirebase, Python from_firebase, Go FromFirebaseClaims.- Reads from the claims: the ID token claims from
verifyIdTokenin the Admin SDK. It readsfirebase.tenantastenant_id,firebase.sign_in_second_factorasmfa, and an anonymous login asassurance_level: low. Custom claims never change the mapping. - Pass as overrides:
email_verifiedfromemailVerifiedon the user record fromgetUser, because custom claims can overwrite theemail_verifiedof the token.phone_verified: truewhen the user has aphoneNumber.account_created_atfrommetadata.creationTime. - Walkthrough.
Amazon Cognito
Amazon Cognito
TypeScript
fromCognito, Python from_cognito, Go FromCognitoClaims.- Reads from the claims: a user pool ID token or access token. It reads
client_idas the audience of an access token,origin_jtiassession_id,cognito:groupsasroles,scope, andamr. Claims that a pre token generation Lambda adds never change the mapping. - Pass as overrides:
email_verifiedandphone_verifiedfrom theemail_verifiedandphone_number_verifiedof the ID token. UseAdminGetUserinstead if a pre token generation Lambda can change them.account_created_atfromUserCreateDateinAdminGetUser.
Microsoft Entra ID
Microsoft Entra ID
TypeScript
fromEntra, Python from_entra, Go FromEntraClaims.- Reads from the claims: a v1.0 or v2.0 ID or access token. It reads
tidastenant_id,utiastoken_id,roles,scp, andamrwhen the token carries it.mfainamrsetsmfa.present. - Pass as overrides:
account_created_atfromcreatedDateTimeon the Microsoft Graph user.
Keycloak
Keycloak
TypeScript
fromKeycloak, Python from_keycloak, Go FromKeycloakClaims.- Reads from the claims: an ID or access token. It reads
sidorsession_state,organization,realm_access.rolesandscope. It reads theimpersonatorclaim from the impersonator mappers of Keycloak. It readsamrfrom the AMR mapper, wheremfaor factors of two kinds setmfa.present. - Pass as overrides:
email_verifiedfrom theemail_verifiedof the token.account_created_atfromcreatedTimestampon the admin API user.session_created_atfromstarton the admin API session. Both are in milliseconds.
Ory (Kratos session)
Ory (Kratos session)
TypeScript
fromOry, Python from_ory, Go FromOrySession.- Reads from the session: the session object from
toSession, not a JWT. It reads the identity id, the session id andauthenticated_at. It readsissued_atassession_created_atand thecreated_atof the identity asaccount_created_at. It reads the second factor from the assurance level and the authentication methods. - Pass as overrides:
issuer, required. This is the URL of your Ory project, which the session does not carry.email_verifiedfromverifiedon the verifiable address of the identity.
Ory OAuth2 (Hydra)
Ory OAuth2 (Hydra)
TypeScript
fromOryOAuth2, Python from_ory_oauth2, Go FromOryOAuth2Claims.- Reads from the claims: the ID token. It reads the standard claims, and
amr, where factors of two kinds setmfa.present. - Pass as overrides: the facts in the table above.
Any other OIDC provider
Any other OIDC provider
TypeScript
fromOIDC, Python from_oidc, Go FromOIDCClaims.- Reads from the claims: the standard claims of the ID token. It takes the provider slug first.
- Pass as overrides: every fact, as this page shows.
Next steps
Turn an assessment into a decision
Rules for
allow, step_up, review and block.Pending, retries and idempotency
What a
pending answer carries and how retries work.Pass your auth session
Every
auth_context field and the six auth reason codes.