Deployment Topologies
Run a dedicated IdP, or embed the provider inside an existing app.
AuthKit is topology-agnostic: the same server config works whether the Authorization Server is its own deployment or lives inside one of your product apps.
Standalone
A dedicated identity provider app — nothing but AuthKit. Product apps are all relying
parties pointing at it. This is a dedicated auth app.
const authServerConfig = defineConfig({
issuer: env.get('AUTHKIT_ISSUER'), // https://auth.acme.com/oidc
adapter: adapters.database({ connection: 'auth' }),
jwks: { source: 'managed', algorithm: 'RS256' },
accountStore: lucidAccountStore(AuthUser),
mountPath: '/oidc',
render: inertiaRenderer({ prefix: 'authkit' }),
admin: { enabled: true },
adminApi: { enabled: true, apiKeys: [env.get('AUTHKIT_ADMIN_API_KEY')] },
})The IdP owns the user identities. After first boot, create each client (acme-web,
acme-admin, …) in the admin console at /admin/clients or via the Admin REST API:
curl -X POST https://auth.acme.com/api/authkit/v1/clients \
-H "Authorization: Bearer $AUTHKIT_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"clientId": "acme-web",
"redirectUris": ["https://web.acme.com/auth/callback"],
"postLogoutRedirectUris": ["https://web.acme.com/"],
"grantTypes": ["authorization_code", "refresh_token"],
"tokenEndpointAuthMethod": "client_secret_basic"
}'Each client gets its own clientId/clientSecret and registered redirect URIs. The
secret is shown once in the response — save it in the client app's .env.
Embedded
The provider runs inside an existing product app, and that app is also one of its own
clients (host-is-its-own-client). This is the acme-web example: the same process
serves the product and the OIDC endpoints.
const authServerConfig = defineConfig({
issuer: env.get('AUTHKIT_ISSUER'),
adapter: adapters.database({ connection: 'auth' }),
jwks: { source: 'managed', algorithm: 'RS256' },
accountStore: lucidAccountStore(AuthUser),
mountPath: '/oidc',
render: inertiaRenderer({ prefix: 'authkit' }),
admin: { enabled: true },
adminApi: { enabled: true, apiKeys: [env.get('AUTHKIT_ADMIN_API_KEY')] },
})After first boot, create the host app's own client (acme-web) in the admin console or
API, then copy the returned clientSecret to .env. Alongside the server config, add a
config/authkit_client.ts pointing at the same issuer — the host authenticates against
itself. See Client.
mountPath, issuer & cookies
mountPath(default/oidc) is where the provider's wildcard routes are mounted. It must match the tail ofissuer.issueris the public, externally-reachable URL —scheme://host[:port]/mountPath. Relying parties derive/auth,/token,/jwks, and/session/endfrom it.- Cookies — the provider sets its SSO session cookies on the issuer's host. In the
embedded topology the provider and the host app share an origin, so the IdP session and
the app session coexist on the same host (two separate cookies). Provide signing keys
via
cookieKeysif you want stable cookie signatures across restarts.
Switching topologies later is mostly an infrastructure change — split the app out, keep
the same issuer URL, and the relying parties don't need to change.