Authentication

All Alianza Experience API calls require an OAuth 2.0 access token sent as Authorization: Bearer <token>. There are two grant types and one optional discovery mechanism.

Authentication uses a dedicated auth base URL ({baseAuthUrl}), separate from the API base URL.

Base URLs

The authentication base URL is fixed per environment, regardless of the end user's phone number or account:

Environment Referenced as URL
Production API {baseUrl} https://api.alianza.com
Sandbox API {baseUrl} https://api.b2.alianza.com
Production Auth {baseAuthUrl} https://auth.alianza.com
Sandbox Auth {baseAuthUrl} https://auth.beta.alianza.com

Which grant to use

Grant When Pages
Client Credentials Server-to-server calls with no end-user context. Use this for the eligibility check before signup. Always act as an OAuth2 confidential client with this grant. Client Credentials
Authorization Code + PKCE Acting on behalf of an authenticated user (e.g. creating a connection on their account). Authorization Code + PKCE

Private key JWT authentication

Alianza strongly recommends private_key_jwt instead of client_secret when retrieving an access token. It authenticates your client with a short-lived JWT signed by your private key; Alianza validates the signature with the public key registered for your client.

private_key_jwt is the only supported client-authentication method that allows secret rotation with zero downtime. Alianza supports a maximum of two active public keys per client so you can register a new public key, deploy its private key, and then remove the old public key after the transition.

Keep the private key secure and never send it to Alianza. Register only the corresponding public key and provide it to Alianza. Each client assertion must include:

  • iss and sub set to your client_id.
  • aud set to {baseAuthUrl}/oauth/token.
  • iat set to the current time and exp set to no more than five minutes later.
  • jti set to a unique identifier to prevent replay.

Include the registered key's ID in the JWT header as kid.

For example, install jose with npm install jose, then generate the assertion from a PKCS#8 PEM private key:

import { randomUUID } from "node:crypto";
import { readFile } from "node:fs/promises";
import { importPKCS8, SignJWT } from "jose";

const clientId = process.env.CLIENT_ID;
const baseAuthUrl = process.env.BASE_AUTH_URL;
const privateKeyPem = await readFile("private-key.pem", "utf8");
const privateKey = await importPKCS8(privateKeyPem, "RS256");

const clientAssertion = await new SignJWT({})
  .setProtectedHeader({ alg: "RS256", kid: process.env.KEY_ID })
  .setIssuer(clientId)
  .setSubject(clientId)
  .setAudience(`${baseAuthUrl}/oauth/token`)
  .setIssuedAt()
  .setExpirationTime("1m")
  .setJti(randomUUID())
  .sign(privateKey);

Use private_key_jwt when retrieving an access token with Client Credentials and Authorization Code flows.

Token endpoints

Endpoint Used by
POST {baseAuthUrl}/oauth/token Client Credentials and Authorization Code grants
GET {baseAuthUrl}/authorize Authorization Code + PKCE only

Scopes

Scopes are declared in the OpenAPI spec's oauth2 security schemes. The scopes relevant to Experience integrations:

Scope Grants permission to
experience-assignability:check Invoke the Experience Assignability endpoint
experience-connections:manage List, retrieve, create, update, and delete Experience Connections for your Experience
experience-assignments:manage List, retrieve, create, and delete Experience Assignments for your Experience
experience-assignments:read Permission to list and retrieve Experience Assignments for your Experience
experience-connections:read Permission to list and retrieve Experience Connections for your Experience

Token caching and refresh tokens

Access tokens are valid for the duration in expires_in (seconds). Cache them until shortly before they expire rather than requesting a new token per call.

To obtain a refresh token, include the offline_access scope on the /authorize request. The subsequent /oauth/token request then returns a refresh token alongside the access token, letting your Experience get new access tokens without sending the user through sign-in again.

Retrieving a new access token

POST {baseAuthUrl}/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token={refresh_token}

See also