OIDC relying-party integration

The MVS OIDC Identity Provider is live at https://c-auth.mvscloud.com. Any standards-compliant OIDC client library works (e.g. openid-client, next-auth, Better Auth’s genericOAuth/social provider).

1. Register your client

Clients exist only as oauth_client database rows. There are two supported ways to create that row: the gated, authenticated self-service registration API (an admin session or a scoped Initial Access Token — the self-serve path for internal MVS apps / CI), or the operator CLI below (the manual fallback for external/un-tokened RPs, or when self-registration is disabled). To use the CLI, from the mvs-auth repo, with AUTH_DATABASE_URL pointing at the auth database:

$pnpm --filter @mvs/auth-server oidc:register -- \
> --name "My App" \
> --redirect https://myapp.mvscloud.com/api/auth/callback/mvs

The script prints the client_id and the one-time-visible client secret (only a SHA-256 hash is stored). First-party clients can be registered with skipConsent so users never see the consent page.

An oauth_client database row is what authenticates a client — written either via the gated, authenticated self-service registration API or via the oidc:register CLI. The OIDC_CLIENT_* environment triplets are vestigial. The only thing disabled is the better-auth plugin’s RFC 7591 /oauth2/register endpoint, so the discovery document carries no registration_endpoint — there is no dynamic (RFC 7591) client registration.

2. Configure your client

SettingValue
Issuerhttps://c-auth.mvscloud.com (exact)
Discoveryhttps://c-auth.mvscloud.com/.well-known/openid-configuration
Authorization endpointhttps://c-auth.mvscloud.com/api/auth/oauth2/authorize
Token endpointhttps://c-auth.mvscloud.com/api/auth/oauth2/token
UserInfohttps://c-auth.mvscloud.com/api/auth/oauth2/userinfo
JWKShttps://c-auth.mvscloud.com/api/auth/jwks
Scopesopenid profile email (+ offline_access for refresh tokens)
PKCERequired, S256 only (plain is rejected)
Client authclient_secret_basic or client_secret_post

3. Validate tokens

Access tokens are opaque (mvs_at_* prefix) — validate them server-side with RFC 7662 introspection at /api/auth/oauth2/introspect using your client credentials. ID tokens are JWTs signed with EdDSA (Ed25519); verify against the JWKS endpoint.

Namespaced custom claims are present in the ID token and userinfo response:

ClaimMeaning
https://mvscloud.com/org_idActive organization ID
https://mvscloud.com/org_slugActive organization slug
https://mvscloud.com/roleUser’s role in that organization
https://mvscloud.com/tenant_dbTenant database name

A JWT-access-token lane (RFC 8707 resource parameter + aud-bound JWTs) is available once your API origin is on the OIDC_VALID_AUDIENCES allowlist and you pass the RFC 8707 resource param on /authorize (see the downstream guide §5). Without it, access tokens are opaque and require introspection.

4. Logout

RP-initiated logout is available at /api/auth/oauth2/end-session. Refresh tokens rotate on use; reusing a rotated refresh token invalidates the whole token family.