AutoX ID
Agents & tools: fetch the Markdown at /integration.md

AutoX SSO — integration & migration guide

_For engineers and coding agents wiring an application onto AutoX SSO, or migrating one off its own custom authentication._

This page is served live by the identity provider itself:

Every value below reflects the running provider's configuration. When a fact here and the discovery document disagree, the discovery document wins.

TL;DR

AutoX SSO is an OpenID Connect (OIDC) identity provider. Migrating an app means: stop handling credentials yourself, and instead redirect users here to authenticate, then receive them back with tokens.

Before you start — what you need

There is no self-service or dynamic client registration. Ask an AutoX SSO admin to register your app in the console (https://sso.autogrc.cloud/admin → Applications) and hand you:

The protocol contract

Configure your client from the discovery document — do not hardcode endpoint paths:

https://sso.autogrc.cloud/.well-known/openid-configuration

Current values (authoritative source is the discovery document above):

Scopes

A typical web app requests: openid profile email orgs roles. Add offline_access only if you need to refresh sessions without redirecting the user again.

Claims

Identity, org, and role claims are placed in the ID token, so you usually do not need a /userinfo round-trip:

Tokens

Logout

RP-initiated logout is enabled. Redirect the user to the end_session_endpoint with an id_token_hint and, optionally, a registered post_logout_redirect_uri.

Migration recipe (framework-agnostic)

  1. Have an admin register the client and collect the values above.
  2. Add an OIDC client library for your stack (examples below). Configure it from the issuer / discovery document — never hand-roll the protocol.
  3. Implement three routes: login (redirect to the authorization endpoint with PKCE + state + nonce), callback (exchange the code for tokens, verify the ID token), and logout (redirect to the end-session endpoint).
  4. On a successful callback, load or create your local user by sub. Store only the claims you need in a server-side session (or an httpOnly, Secure cookie).
  5. Replace your authorization checks with autox:roles / autox:orgs.
  6. Delete the old auth: password hashing/storage, login & signup pages, password reset, MFA/TOTP enrollment & verification, and any local JWT/session minting tied to passwords.
  7. Keep your users table, but drop the password/MFA columns and key it on sub.
  8. If a separate API/resource server must authorize requests, validate a JWT access token obtained via resource=https://sso.autogrc.cloud/api.

Example — Next.js (Auth.js v5 / NextAuth)

// auth.ts
import NextAuth from "next-auth";

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [
    {
      id: "autox",
      name: "AutoX ID",
      type: "oidc",
      issuer: "https://sso.autogrc.cloud",              // discovery is automatic
      clientId: process.env.AUTOX_CLIENT_ID!,
      clientSecret: process.env.AUTOX_CLIENT_SECRET!, // omit for a public client
      authorization: { params: { scope: "openid profile email orgs roles offline_access" } },
      // Auth.js performs PKCE + state + nonce for oidc providers by default.
    },
  ],
  callbacks: {
    async jwt({ token, profile }) {
      if (profile) {
        token.sub = profile.sub;
        token.roles = profile["autox:roles"] ?? [];
        token.orgs = profile["autox:orgs"] ?? [];
      }
      return token;
    },
    async session({ session, token }) {
      session.user.id = token.sub;
      session.roles = token.roles;
      session.orgs = token.orgs;
      return session;
    },
  },
});

Register the redirect URI https://your-app.example.com/api/auth/callback/autox in the console.

Example — Node (openid-client v5), any framework

import { Issuer, generators } from "openid-client";

const issuer = await Issuer.discover("https://sso.autogrc.cloud");
const client = new issuer.Client({
  client_id: process.env.AUTOX_CLIENT_ID,
  client_secret: process.env.AUTOX_CLIENT_SECRET, // omit + token_endpoint_auth_method:'none' for a public client
  redirect_uris: ["https://your-app.example.com/callback"],
  response_types: ["code"],
});

// login: stash these in the session, then redirect the user to `url`
const code_verifier = generators.codeVerifier();
const code_challenge = generators.codeChallenge(code_verifier);
const state = generators.state();
const nonce = generators.nonce();
const url = client.authorizationUrl({
  scope: "openid profile email orgs roles",
  code_challenge,
  code_challenge_method: "S256",
  state,
  nonce,
});

// callback:
const params = client.callbackParams(req);
const tokenSet = await client.callback(
  "https://your-app.example.com/callback",
  params,
  { code_verifier, state, nonce },
);
const claims = tokenSet.claims(); // sub, email, name, autox:roles, autox:orgs, ...

Example — FastAPI resource server (validate JWT access tokens)

Have the front end request resource=https://sso.autogrc.cloud/api so your API receives a JWT it can verify offline:

import jwt
from jwt import PyJWKClient

ISSUER = "https://sso.autogrc.cloud"
AUDIENCE = "https://sso.autogrc.cloud/api"
_jwks = PyJWKClient(ISSUER + "/jwks")

def verify_access_token(token: str) -> dict:
    key = _jwks.get_signing_key_from_jwt(token).key
    return jwt.decode(token, key, algorithms=["ES256"], audience=AUDIENCE, issuer=ISSUER)

def require_role(claims: dict, role: str) -> bool:
    return role in claims.get("autox:roles", [])

Handling cold starts (scale-to-zero / free-tier hosting)

The identity provider may be cold — on a free or scale-to-zero host it spins down when idle, and the first request after that wakes it, which can take tens of seconds. If you redirect a user straight to the authorization endpoint while the IdP is asleep, they hit a hang or a connection error *mid-redirect*, with nothing to look at. Warm it first, then redirect.

When a user lands on your app's entry page (or clicks "Sign in"):

  1. Preconnect early. Put <link rel="preconnect" href="https://sso.autogrc.cloud"> (and a

dns-prefetch) in that page's <head> so the connection is being established while the user reads the page.

  1. Probe before you redirect. Do a cheap GET https://sso.autogrc.cloud/health (it returns

{"status":"ok"}) with a short timeout and a few retries/backoff, showing a brief "Connecting to sign-in…" state. Only navigate to the authorization endpoint once the probe returns 2xx.

  1. Optionally prefetch discovery (https://sso.autogrc.cloud/.well-known/openid-configuration)

during the warm-up so the redirect resolves instantly.

// Warm the IdP (it may be cold), confirm it's reachable, THEN redirect.
async function goToSignIn(authorizeUrl) {
  const issuer = "https://sso.autogrc.cloud";
  const deadline = Date.now() + 60_000; // give a cold start up to ~60s
  while (Date.now() < deadline) {
    try {
      const r = await fetch(issuer + "/health", { cache: "no-store" });
      if (r.ok) { window.location.href = authorizeUrl; return; }
    } catch { /* still waking */ }
    await new Promise((res) => setTimeout(res, 2000));
  }
  // Never came up — show a friendly "sign-in is temporarily unavailable" message.
}

This is a deployment characteristic, not a protocol requirement: once the IdP runs always-on (a paid/warm plan), the probe is essentially instant and you can keep it as a cheap health gate or drop it.

Security requirements your app MUST honor

What NOT to do

Migration checklist


Can't find a value? It is in the discovery document (https://sso.autogrc.cloud/.well-known/openid-configuration), or ask the admin who registered your client.

Protected by AutoX SSO