Skip to main content
NoResponse assesses each new account for abuse. It returns the current risk score of the account, from 0 to 100, where a higher score means more risk. It also returns a decision: allow, step_up, review or block. Auth0 already knows facts that make the score more accurate. Examples are whether the user verified the email and when the user last passed a second factor. auth_context is the part of the assessment request that carries these facts. fromAuth0 is the Auth0 adapter in each NoResponse SDK. It builds auth_context from the ID token claims that you verified, and you add the facts from the Auth0 user and session records. Your backend does five things:
  1. Verifies the ID token: its signature, issuer and audience.
  2. users.get: gets the account age and the verified phone.
  3. sessions.get: gets the session age.
  4. fromAuth0: turns the claims and the records into auth_context.
  5. assessments.create: NoResponse returns the assessment.

What Auth0 can supply

The session record comes from the sessions endpoint of the Management API. Auth0 offers this endpoint on its Enterprise plans. On another plan, delete the session lines from the samples. The assessment then has no session age.

What Auth0 cannot supply

  • Impersonation. Auth0 no longer offers impersonation. So the adapter sends impersonated: false, unless an Action of yours adds an act claim.
  • Roles. Auth0 puts roles in a namespaced custom claim that you choose, so the adapter does not read them. To keep them with the assessment, pass them as an override, such as roles: ["admin"].
  • An assurance level. Auth0 has no equivalent of assurance_level.

Install

TypeScript
The samples use auth0 7 for Node.js, auth0-python 6 and go-auth0 1. Version 4 of the Node.js package has a different Management API client. Do these three things in Auth0:
  1. Request the openid email phone scopes at login, so that the ID token carries email_verified and phone_number_verified.
  2. Create a machine-to-machine application with access to the Management API and the read:users and read:sessions scopes.
  3. Keep the ID token signing algorithm at RS256, the Auth0 default.
Set these variables in the environment of your backend:
  • AUTH0_DOMAIN: your Auth0 tenant domain, such as example.us.auth0.com. The Management API calls use it.
  • AUTH0_ISSUER: optional. Set it when users log in through a custom domain. The value is https://, then that domain, then a trailing /. This value is the iss of the ID token. The default is https://, then AUTH0_DOMAIN, then /.
  • AUTH0_CLIENT_ID: the client ID of the application that users log in to. It is the audience of the ID token.
  • AUTH0_M2M_CLIENT_ID and AUTH0_M2M_CLIENT_SECRET: the credentials of the machine-to-machine application.
  • NORESPONSE_API_KEY: your NoResponse key, with the assess scope. 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 an Auth0 user 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 Auth0 token response. Your callback route receives it after the login redirect. Pass an ID token, not an access token for your API, because an access token carries no verified email. Your Auth0 SDK can verify the ID token first. Then pass its claims to the adapter and skip step 1. In express-openid-connect the claims are req.oidc.idTokenClaims.
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 Auth0 user id is the account_id, unchanged. auth0|64abc0de1234567890abcdef is a valid account id, and the Management API 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.
Verified claims, never the tokenThe adapter takes the claims that verification gave you. It never takes the token string. It sets verified: true and transport: "backend" to say that your backend did the verification. The API refuses an auth_context that holds a token.

Act on the answer

The answer starts with assessment.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 answers block after 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.account is 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.
Turn an assessment into a decision gives a full rule set to copy.

What the adapter sends

This is the auth_context for a new user with a verified email who passed a one-time code a minute ago:
auth_context for a new user
audience is the audience of the ID token, which is the client ID of your application. audiences lists every value when aud holds more than one. That context fires four reasons. account.risk.reasons lists each one with its weight:
  • auth_new_session and auth_new_account raise the score for any new account.
  • auth_email_verified and auth_mfa_recent lower it. They make this account different from one with nothing verified.

Late results

A slow source can raise an assessment after you allowed the new account. NoResponse then sends assessment.updated. The Auth0 late-result provider in each SDK then acts on the Auth0 user through the Management API. It is auth0Actions in TypeScript, auth0_actions in Python and Auth0Actions in Go. Act on late results has the full webhook handlers for Auth0. This section tells you what the Auth0 actions do on each plan. The handler needs its own machine-to-machine application, with access to the Management API and these scopes: Auth0 offers the session and refresh-token endpoints only on Enterprise plans. On every other plan, Free included, they answer 403 with the error code feature_not_enabled. The handler then falls back: Without the sessions API, your code cannot end a login session. An application can use a login session to get new tokens through silent authentication. Blocking the user stops that, because Auth0 refuses the logins and refresh token grants of a blocked user. So on those plans revoke_sessions does what ban does, and the result reports ban. Log result.action to see which one ran. To let a blocked user back in, unblock the user in the Auth0 dashboard. You can also send PATCH /api/v2/users/{id} with {"blocked": false}. Both actions are safe to repeat. A second delivery sets blocked: true again and finds no refresh tokens left to delete. A 404 for a user or credential that is already gone counts as done.
Any other refusal is not a plan limit. The handler raises ProviderActionError with the Auth0 error code in code (errorCode in PHP), such as insufficient_scope when the token does not have a scope. Answer the webhook with a 5xx so that NoResponse delivers it again.
The Management API has rate limits, and the limits of the Free plan are low. Without the sessions API, a revoke makes one call per refresh token. When Auth0 answers 429, the handler waits and sends the same call again. A 429 means that Auth0 did nothing, so a repeat is safe for a delete too. The handler waits for the first of these that applies:
  • The time that Retry-After gives.
  • Else, until X-RateLimit-Reset.
  • Else, 250 ms, 500 ms, 1 s and 2 s, in that order.
The handler retries each call at most 4 times. One revoke or ban waits at most 3 seconds in total, so the handler still answers within the 5 seconds that a delivery has. If the next wait goes past that limit, the handler raises ProviderActionError with status 429. Answer with a 5xx, and NoResponse delivers the event again. Revoke and ban are safe to repeat.

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.

Act on late results

Revoke sessions or ban when an assessment rises after account creation.