Overview
Turn your project into an OAuth 2.1 and OpenID Connect provider, so other products can offer "Sign in with your app".
Your project already signs people in. The OAuth Server turns it around: it lets other applications sign people in with your product, the way you sign in to things with Google or GitHub.
Once it is on, a third-party developer registers an app against your project, sends their users to your authorization endpoint, and receives tokens that carry your users' identity. You decide who they are, what the app may see, and when access ends.
This is not how you sign in to your own app
For your own frontend, keep using auth.signIn and the session it returns. The
OAuth Server is for other people's applications. Reaching for it to log in to
your own product adds a redirect round trip and a consent screen you do not need.
The three parties
Every OAuth flow has three, and most confusion comes from mixing them up.
Authorization serveryour projectOptionalRuns on nulvless. Authenticates the user, shows consent, issues tokens. Its address is the issuer.
Clientthe third-party appOptionalRegistered against your project. Holds a client_id, and a client_secret if
it can keep one. Never sees the user's password.
Resource owneryour userOptionalThe person deciding whether that app may act on their behalf.
There is a fourth participant that is easy to miss: your own frontend. The consent screen is a page in your application, not one nulvless renders. That is deliberate — the moment a user grants access, they should be looking at your product, not at ours. Building it is a page of its own.
What OAuth 2.1 changes
OAuth 2.1 is a consolidation, not a new protocol. It folds a decade of practice into the baseline, and the parts that matter here are the parts it removes.
- PKCE is required, for every client, not just public ones. There is no way
to run the flow without
code_challenge. - The implicit grant is gone. No
response_type=token. Codes only. - The password grant is gone. An app never handles your users' credentials.
- Redirect URIs match exactly. No wildcards, no prefix matching.
If you have integrated an older OAuth provider, the flow will feel familiar and slightly stricter. Nothing you can do here is insecure by default, because the insecure options were removed rather than discouraged.
What you get
Quickstart
Enable the server, register a client, and run a full flow.
Authorization flow
Every redirect and request, in order, with the real parameters.
Consent screen
The page you build, in Next.js, Nuxt, SvelteKit and Remix.
Clients
Registering apps, secrets, redirect URIs, dynamic registration.
Tokens
What is inside them, and how a resource server checks one.
Reference
Endpoints, scopes, error codes.
Scopes
Four, and they mean what OpenID Connect says they mean.
| Scope | The client receives |
|---|---|
openid | An ID token. Without it, this is plain OAuth and no identity is asserted. |
email | The user's email address and whether it is verified. |
profile | Name and picture. |
phone | Phone number and whether it is verified. |
A request that omits scope falls back to email rather than failing. Ask for
the narrowest set that makes your integration work — every extra scope is
something the user has to read and accept.
Environments
Each environment of your project is a separate authorization server with its own issuer, its own clients and its own secrets. A client registered in staging does not exist in production, and a token minted in one will not validate against the other.
That separation is the point: you can hand a partner staging credentials without giving them anything that works against real users.