Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.authsignal.com/llms.txt

Use this file to discover all available pages before exploring further.

Authsignal SDKs can be used to implement OIDC provider authentication in the following scenarios.
  1. Sign in or sign up. Authenticate users without a known user ID. Covers both new and returning users.
  2. Step-up authentication. Re-verify a known user with a linked provider before a sensitive action.
  3. Enrol an OIDC provider. Link a provider to an existing user as an additional authentication factor.
OIDC providers are configured per-tenant with allowed redirect URLs and per-action restrictions.

How it works

To bind the client that starts a challenge to the client that completes it, the client SDK generates a codeVerifier and a hashed codeChallenge. The codeChallenge is sent to Authsignal when the client challenge starts and the codeVerifier is persisted locally. After the user is redirected back, the SDK returns the codeVerifier alongside the authorizationToken so the server can prove the challenge is being completed by the original client.

SDK setup

Server SDK

Initialize the Server SDK using your secret key from the API keys page and the API URL for your region.
import { Authsignal } from "@authsignal/node";

const authsignal = new Authsignal({
  apiSecretKey: "YOUR_SECRET_KEY",
  apiUrl: "YOUR_API_URL",
});

Client SDK

Initialize the Client SDK with your tenant ID and the API URL for your region.
import { Authsignal } from "@authsignal/browser";

const authsignal = new Authsignal({
  tenantId: "YOUR_TENANT_ID",
  baseUrl: "YOUR_API_URL",
});

Sign in or sign up

Scenario - Authenticate a user when you don’t have a user ID upfront, e.g. adding a “Sign in with Google” button to your app.
Your server initiates the challenge without a userId. After the user authenticates with the provider, your server calls verify to get the provider’s identity attributes, then calls identify to associate the user with an ID in your system.

1. Initiate challenge

Call oidc.challenge on your server to start the OIDC provider flow. This returns an authorizationToken that your server passes back to the client.
const { authorizationToken } = await authsignal.oidc.challenge({
  action: "signIn",
  provider: "google",
  redirectUrls: ["https://myapp.com/auth/callback"],
  clientId: "YOUR_APP_CLIENT_ID",
});
Return the authorizationToken from the response to your client.

2. Start the client challenge

On your client, call oidc.challenge with the authorizationToken. The SDK redirects the user to the provider’s login page.
await authsignal.oidc.challenge({ authorizationToken });

3. Handle callback

After the user authenticates with the provider, they are redirected back to one of your redirectUrls. Call oidc.handleCallback on your client to retrieve a short-lived authorizationToken representing the completed challenge along with the codeVerifier.
const { authorizationToken, codeVerifier } = await authsignal.oidc.handleCallback();
Send the authorizationToken and codeVerifier to your server for verification.

4. Verify

On your server, call verify with the authorizationToken and codeVerifier.
const { challengeId, user, attributes } = await authsignal.verify({
  authorizationToken,
  codeVerifier,
});

Returning user

If the user has previously signed in and their provider identity is already linked, the verify response will return isIdentified: true with session tokens. In this case, the user is already associated — skip the identify step and proceed with the session.

New user

If the user is new, the response includes isIdentified: false on the user, indicating no user ID has been associated yet. The attributes object contains the verified provider data such as email, sub, emailVerified, and iss. Call identify in the next step to complete the process.

5. Identify

Associate the user with a user ID. You can either use the Authsignal-generated user ID from the verify response, or provide your own. Option A: Use the Authsignal-generated user ID Use the userId returned in the verify response to confirm the Authsignal-generated ID.
const { user: identifiedUser } = await authsignal.identify({
  challengeId,
  userId: user.userId,
});
Option B: Bring your own user ID Look up or create the user in your system using the verified attributes, then pass your user ID to identify.
const myUserId = await mySystem.findOrCreateUser(attributes.email);

const { user: identifiedUser } = await authsignal.identify({
  challengeId,
  userId: myUserId,
});

Step-up authentication

Scenario - Require a user to re-authenticate with a linked OIDC provider as an additional verification step. The user must already have the provider enrolled.
Use this flow when a user is already signed in and you want to verify their identity again before a sensitive action. The provider must already be enrolled for the user — if no provider is enrolled, the challenge will return an error. If the user authenticates with a different provider account than the one linked, the verification will fail.

1. Initiate challenge

const { authorizationToken } = await authsignal.oidc.challenge({
  action: "transferFunds",
  userId: "my-user-id",
  provider: "google",
  redirectUrls: ["https://myapp.com/auth/callback"],
  clientId: "YOUR_APP_CLIENT_ID",
});
Return the authorizationToken from the response to your client.

2. Start the client challenge

await authsignal.oidc.challenge({ authorizationToken });

3. Handle callback

const { authorizationToken, codeVerifier } = await authsignal.oidc.handleCallback();

4. Verify

const { session, user, attributes } = await authsignal.verify({
  authorizationToken,
  codeVerifier,
});
The response includes isIdentified: true and a session object containing accessToken and refreshToken.

Example response

{
  "verificationMethod": "OIDC_PROVIDER",
  "attributes": {
    "atHash": "abc123def456",
    "aud": "your-google-client-id.apps.googleusercontent.com",
    "sub": "109876543210987654321",
    "emailVerified": true,
    "azp": "your-google-client-id.apps.googleusercontent.com",
    "iss": "https://accounts.google.com",
    "hd": "example.com",
    "exp": 1776316088,
    "iat": 1776312488,
    "email": "user@example.com"
  },
  "action": {
    "state": "CHALLENGE_SUCCEEDED",
    "completedVerificationMethods": ["OIDC_PROVIDER"]
  },
  "user": {
    "userId": "my-user-id",
    "emailVerified": false,
    "phoneNumberVerified": false,
    "isIdentified": true
  },
  "session": {
    "accessToken": "eyJhbGciOiJSUzI1NiIs...",
    "refreshToken": "9e1e8769e887fb0a029d..."
  }
}

Enrol an OIDC provider

Scenario - Link an OIDC provider to an existing user as an additional authentication factor. The user must be in an authenticated state.
Use this flow to let users add an OIDC provider to their account. This requires the add:authenticators scope to be provided in the challenge call.

1. Initiate challenge

The add:authenticators scope is required to enrol a new OIDC provider for an existing user. This scope should only be used when the user is in an already authenticated state. For more information on using scopes safely refer to our documentation on authenticator binding.
const { authorizationToken } = await authsignal.oidc.challenge({
  action: "enrolProvider",
  userId: "my-user-id",
  provider: "google",
  redirectUrls: ["https://myapp.com/auth/callback"],
  clientId: "YOUR_APP_CLIENT_ID",
  scope: "add:authenticators",
});
Return the authorizationToken from the response to your client.

2. Start the client challenge

await authsignal.oidc.challenge({ authorizationToken });

3. Handle callback

const { authorizationToken, codeVerifier } = await authsignal.oidc.handleCallback();

4. Verify

const { user, attributes } = await authsignal.verify({
  authorizationToken,
  codeVerifier,
});
The OIDC provider is now linked to the user.
If the OIDC provider is already linked to a different user, the challenge will fail with an error. Each provider identity (identified by the provider’s sub or equivalent identifier) can only be linked to one user at a time.