Rollout and approval
The expanded AuthOS implementation and external-application onboarding are undergoing production qualification. This guide documents the integration contract; publication does not mean your application is approved or that every provider and feature is activated. Confirm readiness with support@lssm.co before a production integration.
Anonymous dynamic client registration is disabled. An operator must approve your application configuration and access policy. Identity registration alone does not grant product membership.
Prepare your application registration
- Provide the application name, owner, exact HTTPS callback and post-logout URLs, required identity scopes and resource audiences. Use a callback such as https://YOUR_HOST/api/auth/callback/lssm; do not use a wildcard.
- Choose public verified-identity admission or an invitation/entitlement policy with the operator. Keep product memberships, roles and business authorization local to the consuming application.
- After approval, the owner rotates the client secret to obtain its one-time value. Store the assigned application ID, client ID and secret in the application server’s secret manager. Never expose the secret in a browser, mobile bundle or public configuration.
- The planned application-management surface is /auth/applications on id.lssm.co. Ask support for the available onboarding process during rollout; do not assume an unqualified route is live.
Protocol settings
Read authorization, token and JWKS endpoints from the canonical discovery document. Pin its issuer exactly to https://id.lssm.co/api/auth, including after discovery retries. Do not accept a different discovered issuer.
Application resource audiences are independently reviewed. Registration metadata cannot broaden the deployment’s valid-audience policy. The ID-token audience is the client ID, not the resource audience.
- Issuer
- https://id.lssm.co/api/auth
- Discovery
- https://id.lssm.co/.well-known/openid-configuration
- Client authentication
- Confidential server client; client_secret_basic
- Grant
- authorization_code with S256 PKCE; refresh_token only when approved
- Identity scopes
- openid; profile and email when needed; offline_access only when approved
- Application scope
- https://lssm.co/scopes/YOUR_APPROVED_APPLICATION_ID
- ID-token audience
- Your approved client ID
- Resource audience
- The exact operator-approved application resource audience
- Subject
- Pairwise sub, bound to the issuer; not the email address
Use the verified server configuration
Use Better Auth 1.7.14 and the complete reference configuration module linked below. It uses the official Generic OAuth plugin and verifies the canonical discovered issuer on startup and later retries. Supply a persistent supported database adapter, a dedicated session secret of at least 32 characters, and the approved server credentials. Database creation and migrations remain an explicit application deployment step.
Keep the complete reference wrapper: its confidential-client compatibility checks are part of this configuration. It requires a signed ID token bound to the exact server-generated nonce and the authorization response issuer. It rejects userinfo-only fallback and browser-submitted ID-token sign-in. Userinfo may supplement only the verified subject; a profile id is not an identity fallback.
The example configuration requests only openid, profile, email and the exact application scope. Add offline_access only after operator approval if the application needs refresh tokens. These snippets do not create product permissions or provision another product’s database.
APP_ORIGIN must be the exact HTTPS origin, such as https://YOUR_HOST, without a path or trailing slash. Use a separate server session secret; do not reuse the OAuth client secret as a session secret.
Application server configuration
import { betterAuth } from 'better-auth';
import { externalIdentityOptions } from './lssm-id-auth';
import { database } from './database'; // Your persistent supported adapter.
export const auth = betterAuth(externalIdentityOptions({
origin: process.env.APP_ORIGIN!,
database,
sessionSecret: process.env.APP_SESSION_SECRET!,
clientId: process.env.LSSM_CLIENT_ID!,
clientSecret: process.env.LSSM_CLIENT_SECRET!,
applicationId: process.env.LSSM_APPLICATION_ID!,
}));Next.js App Router handler
// app/api/auth/[...all]/route.ts
import { toNextJsHandler } from 'better-auth/next-js';
import { auth } from '@/lib/auth';
export const { GET, POST } = toNextJsHandler(auth);Generic server handler
// Mount on your HTTPS server; preserve the reviewed canonical origin.
import { auth } from './auth';
import { handleAuthorizedApplicationRequest } from './application';
export async function fetch(request: Request): Promise<Response> {
if (new URL(request.url).pathname.startsWith('/api/auth/')) {
return auth.handler(request);
}
const session = await auth.api.getSession({
headers: request.headers,
query: { disableCookieCache: true },
});
if (!session) return new Response('Sign in required', { status: 401 });
// This application handler must check its own live memberships and grants.
return handleAuthorizedApplicationRequest(request, session);
}Browser client on your application’s own origin
import { createAuthClient } from 'better-auth/client';
const authClient = createAuthClient();
await authClient.signIn.social({ provider: 'lssm', callbackURL: '/account' });
// Product-local sign-out; central LSSM ID logout is a separate choice.
await authClient.signOut();Validate the callback and local authority
- Bind each browser authorization to a single-use state, nonce, S256 challenge and verifier, and exact registered callback. Validate the authorization response issuer.
- Verify the ID-token signature using the trusted discovery/JWKS, exact issuer, client-ID audience, nonce and expiry. An access token is not an ID token. Fail closed on missing or invalid proof.
- Use the issuer and pairwise subject as identity, not email matching. Do not silently merge an existing local identity only because an email address matches.
- Create an application-local session only after successful central admission. Recompute live product memberships and grants after callback and account switching. A central administrator role does not grant product access.
- Use HTTPS and secure application-local cookies. Keep the application’s session and credentials separate from the central Passport cookie, API keys and agent grants. Do not trust arbitrary forwarded host headers to set the issuer or callback.
Consent, rotation and sign-out
Application metadata changes require a fresh operator review. Suspension, revocation and secret rotation stop the corresponding central credentials and grants; an already established local session still follows the application’s own revocation policy. Plan that policy explicitly.
The reference helper disables automatic provider logout. Signing out of your product ends that product’s local session; signing out of central LSSM ID is a separate user action. Test account selection, both logout choices and application-local authorization after switching.
Signing in does not authorize platform mail, repositories, reporting or other connected data. Platform connections require separate consent, scopes and resources. Browser sessions, API keys and agent grants remain distinct credentials.
Qualify before production use
- Record the operator-approved configuration version, exact application source and hosted deployment IDs.
- Run a real authorization → consent → callback → local-session journey on the actual HTTPS host. Also exercise denied consent and invalid state, nonce, issuer, audience, signature and expiry.
- Where approved, test refresh, credential rotation and revocation. Test account selection, local membership denial and logout without relying on cached authority.
- A source example, registered client or authorization-start URL is not a production receipt. The separately hosted reference application and each ecosystem consumer require their own real journey.
Contact support@lssm.co for integration coordination and security@lssm.co for a suspected security issue. The privacy and deletion pages describe personal-data requests.
Reference source
- Pinned Better Auth version
- 1.7.14
- Inspected source commit
- cd244e959faddc42ed30d6a6c5089618e37c1ab0