Backend SDK Configuration
Learn how to configure Wristband backend server auth SDKs, including auto-configuration.
Backend server auth SDKs are configured once when your application creates an instance of the SDK. That instance is then shared across your application and used by your auth endpoints and auth middleware.
For example, using the Express Auth SDK:
import { createWristbandAuth } from '@wristband/express-auth';
export const wristbandAuth = createWristbandAuth({
clientId: 'replace-me-with-your-client-id',
clientSecret: 'replace-me-with-your-client-secret',
wristbandApplicationVanityDomain: 'replace-me-with-your-vanity-domain',
});Required Configuration
Every SDK instance needs three values from your Wristband Application:
clientIdandclientSecret: The credentials of your application's Backend Server OAuth2 Client.wristbandApplicationVanityDomain: The vanity domain of your Wristband Application. See Domains and URLs for more on vanity domains.
All other values are either optional or can be fetched automatically through auto-configuration.
Auto-Configuration
Auto-configuration lets the SDK fetch some of its configuration values from Wristband's SDK Configuration Endpoint instead of requiring you to set them manually. It is enabled by default.
The following values are auto-configurable:
applicationAuthorizationRequestsEnabledcustomApplicationLoginPageUrlisApplicationCustomDomainActiveloginUrlredirectUri
Any value you set manually takes precedence over the auto-configured value. This lets you override individual values while still auto-configuring the rest.
When Configuration Is Fetched
By default, auto-configuration is lazy: the SDK fetches configuration values the first time an auth function (such as login or callback) is called, so your application can start without waiting on Wristband.
Some SDKs also support eager auto-configuration, which fetches and validates configuration values immediately when the SDK instance is created. Eager auto-configuration is useful when you want your application to fail fast at startup if auto-configuration is unavailable.
Disabling Auto-Configuration
Set autoConfigureEnabled to false to stop the SDK from calling the SDK Configuration Endpoint. When auto-configuration is disabled, you must set loginUrl and redirectUri manually, or the SDK throws an error. The other auto-configurable values fall back to their defaults if you don't set them.
Serverless and Edge RuntimesIn serverless and edge runtimes, the SDK cannot keep auto-configured values in memory between invocations, so it must fetch configuration on every cold start. Manual configuration is strongly recommended in these environments.
Login URL and Redirect URI
The loginUrl is the URL of your application's Login Endpoint, and the redirectUri is the URL of your Callback Endpoint where Wristband sends users after they authenticate.
These values correspond to settings in the Wristband Dashboard:
- Login URL: In most cases, set in "Application Settings". If your Application has multiple OAuth2 Clients, an individual client can override it with its own Login URL in that client's settings under "OAuth2 Clients".
- Redirect URIs: Set in your Backend Server OAuth2 Client's settings under "OAuth2 Clients".
When auto-configuration is enabled, the SDK Configuration Endpoint resolves which values apply and returns them to the SDK.
Tenant Subdomains
If your application uses tenant subdomains, both values must include the {tenant_name} placeholder. For example:
loginUrl: https://{tenant_name}.yourapp.io/auth/login
redirectUri: https://{tenant_name}.yourapp.io/auth/callback
The following rules apply to the placeholder:
-
It must appear exactly once, as the leftmost part of the hostname.
-
The
redirectUrimust contain the placeholder if theloginUrlcontains it, and must not contain it otherwise.
Since the {tenant_name} placeholder marks exactly where the tenant name sits in the hostname, the SDK can work out two additional values from your loginUrl by removing the placeholder, so you don't need to configure them separately:
-
Your application's root domain: Removing the
{tenant_name}subdomain gives the root domain (e.g.yourapp.io), which the SDK uses to parse tenant subdomains from incoming requests. -
A Login Endpoint URL without tenant information: Removing the
{tenant_name}subdomain also gives a Login Endpoint URL without tenant information (e.g.https://yourapp.io/auth/login), which the SDK can redirect to during logout when it can't determine the user's tenant.
Cookies, Tokens, and Scopes
Login State Cookie Encryption
During login, the SDK creates a Login State Cookie that stores the state of the login request, including the state value sent to Wristband and any return URL or custom state your application provided. When Wristband redirects the user back to your Callback Endpoint, the SDK uses this cookie to verify that the callback belongs to a login request your application actually started.
The SDK encrypts the Login State Cookie so that its contents can't be read or modified. It uses your clientSecret as the encryption key by default. For enhanced security, you can optionally set loginStateSecret to a separate value of at least 32 characters.
See the Login State Cookie section of Login for more on the Login State Cookie.
Secure Cookies in Local Development
By default, the SDK creates secure cookies, which browsers only send over HTTPS. Most browsers make an exception for localhost, but some, such as Safari, do not. If secure cookies are blocked in local development, set dangerouslyDisableSecureCookies to true, and re-enable secure cookies before deploying to production.
Token Expiration Buffer
The tokenExpirationBuffer value is subtracted from each access token's expiration time, so the SDK treats tokens as expired slightly before they actually expire. This helps avoid tokens expiring in the middle of an API call. The default is 60 seconds.
Scopes
The scopes value controls which scopes are requested during login. These scopes determine which user data Wristband returns in the Userinfo response, which the SDK retrieves during the callback. The default is openid, offline_access, and email. The offline_access scope is what allows the SDK to receive a refresh token.
See the Userinfo Endpoint documentation for supported scopes.
Requests Without Tenant Information
When a request reaches your Login or Logout Endpoint without any tenant information, the SDK can't determine which tenant the user belongs to. The settings in this section control what the SDK does in that case. The Login and Logout pages cover how the SDK resolves tenants in detail.
Application-Level Authorization Requests
The applicationAuthorizationRequestsEnabled value is configured in "Application Settings" in the Wristband Dashboard, where it's enabled by default, and the SDK picks up that setting through auto-configuration. It gives your application a single, fixed Authorize Endpoint URL, which some third-party platforms (e.g. Supabase) require because they can't handle per-tenant URLs.
- When
true: The SDK starts an authorization request through your Application's vanity domain, and Wristband handles tenant discovery as part of the same login flow. - When
false: The SDK sends the user to the Application-Level Login (Tenant Discovery) Page instead. After the user identifies their tenant, Wristband sends them back to your Login Endpoint to start a tenant-level login.
See Tenant Discovery for more on how tenant discovery works.
Self-Hosted Tenant Discovery Page
If you self-host your Application-Level Login (Tenant Discovery) Page, configure its URL in the Wristband Dashboard under "Application Settings" in the "Custom Page URLs" sub-navigation. The SDK picks up this value through auto-configuration as customApplicationLoginPageUrl, or you can set it manually.
How the SDK uses it depends on applicationAuthorizationRequestsEnabled:
- When
true: Wristband handles redirecting users to your self-hosted page as part of the authorization flow, so the SDK ignores this value. - When
false: The SDK sends users to this URL in place of the Wristband-hosted page, both during login and during logout when it can't determine the user's tenant.
Application-Level Custom Domain
The isApplicationCustomDomainActive value tells the SDK whether your Application has an active Application-Level custom domain. The SDK uses it to build tenant vanity domains for the Wristband Authorize Endpoint and Logout Endpoint URLs:
- When
true: The tenant name is joined to your Application's custom domain with a dot (e.g.customer01.auth.yourapp.io). - When
false: The tenant name is joined to your Application's vanity domain with a hyphen (e.g.customer01-yourapp-yourcompany.us.wristband.dev), which is the format Wristband uses for the vanity domains it provides out of the box.
It defaults to false, and it has no effect on tenant custom domains.
Reverse Proxies
The SDK reads the host of each incoming request to resolve tenant subdomains and validate return URLs. By default, it reads the host value from the Host HTTP header. Running behind a reverse proxy doesn't necessarily change this. Many proxies will pass the original Host header through to your application unchanged. In that case, no extra configuration is needed.
However, some proxies instead replace the Host header with your application's internal address and forward the original host in the X-Forwarded-Host header. Only in that case should you set trustProxyHeaders to true so that the SDK reads the host value from X-Forwarded-Host. Enable it only when your proxy sets or overwrites that header, since otherwise a client could supply its own value.
Framework Proxy SettingsSDKs for frameworks that have their own proxy trust configuration don't support the
trustProxyHeaderssetting. These SDKs read the host from the framework's request object, which already decides whether to useX-Forwarded-Hostbased on the framework's proxy trust configuration. Configure proxy trust through the framework instead.
Configuration Reference
| Field | Type | Required | Auto-Configurable | Default | Description |
|---|---|---|---|---|---|
applicationAuthorizationRequestsEnabled | boolean | No | Yes | true | Whether the SDK starts an authorization request through your application's vanity domain when it cannot resolve a tenant during login. |
autoConfigureEnabled | boolean | No | N/A | true | Whether the SDK fetches missing configuration values from Wristband's SDK Configuration Endpoint. |
clientId | string | Yes | No | N/A | The ID of your Wristband OAuth2 Client. |
clientSecret | string | Yes | No | N/A | The secret of your Wristband OAuth2 Client. |
customApplicationLoginPageUrl | string | No | Yes | N/A | The URL of your self-hosted Application-Level Login (Tenant Discovery) Page. Only used when applicationAuthorizationRequestsEnabled is false. |
dangerouslyDisableSecureCookies | boolean | No | No | false | Removes the Secure attribute from cookies the SDK creates. Only for local development without HTTPS. |
isApplicationCustomDomainActive | boolean | No | Yes | false | Whether your Wristband Application has an active Application-Level custom domain. |
loginStateSecret | string | No | No | Client secret | A secret of at least 32 characters used to encrypt the Login State Cookie. |
loginUrl | string | Yes | Yes | N/A | The URL of your application's Login Endpoint. |
redirectUri | string | Yes | Yes | N/A | The URL of your application's Callback Endpoint. |
scopes | string[] | No | No | openid, offline_access, email | The scopes requested during login. |
tokenExpirationBuffer | number | No | No | 60 | Seconds subtracted from each access token's expiration time. |
trustProxyHeaders | boolean | No | No | false | Whether the SDK reads the request host from the X-Forwarded-Host header. Only available in some SDKs (e.g. Next.js). |
wristbandApplicationVanityDomain | string | Yes | No | N/A | The vanity domain of your Wristband Application. |
Updated about 10 hours ago