OpenID Connect · OAuth 2.0
The flows in diagrams
Who talks to whom, in what order. Solid lines are requests, dotted lines are responses. To choose, start with Which flow should I choose?
Authorization Code + PKCE · Hybrid (code id_token, code token…) · Implicit (id_token, id_token token) · Refresh Token · Client Credentials · Password (ROPC) · Device Code (RFC 8628) · Token exchange (RFC 8693) · Logout (RP-initiated and back-channel) · Introspection and revocation · private_key_jwt and JWT Bearer (RFC 7523) · PAR and JAR (RFC 9126 and 9101) · JARM (signed authorization response) · DPoP (RFC 9449) · CIBA (Client-Initiated Backchannel)
Authorization Code + PKCE Recommended
The standard flow: the browser only sees a single-use code, tokens go from server to server.
Text version of the diagram
- Application: Generates code_verifier, state, nonce
- Application → Browser : 302 to /authorize (challenge, state, nonce)
- Browser → Provider (OP) : GET /authorize
- Provider (OP) → Browser: Sign-in and consent page
- Browser → Provider (OP): Credentials and consent of the person
- Provider (OP) → Browser : 302 redirect_uri?code=…&state=…
- Browser → Application : GET /callback?code=…&state=…
- Application → Provider (OP) : POST /token (code, code_verifier, secret)
- Provider (OP) → Application : ID token + access token (+ refresh token)
- Application: Verifies signature, iss, aud, nonce
- Application → API : Authorization: Bearer access_token
- API → Application: Requested data
Use when: Any website, mobile app, SPA or desktop application where a person signs in.
What sets it apart: This is the foundation. All the other flows are a variant or special case of it.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Hybrid (code id_token, code token…) Specific cases
The identity is received immediately in the browser, and the code to obtain the tokens safely.
Text version of the diagram
- Application → Browser : 302 to /authorize (response_type=code id_token)
- Browser → Provider (OP) : GET /authorize then sign-in
- Provider (OP) → Browser : 302 redirect_uri#code=…&id_token=…&state=…
- Browser: A script reads the fragment and sends it back
- Browser → Application : POST /callback (code, id_token, state)
- Application: Verifies id_token and c_hash
- Application → Provider (OP) : POST /token (code, code_verifier)
- Provider (OP) → Application : access token (+ refresh token)
Use when: An application that must know the person before exchanging the code (server-side session validation, old libraries).
What sets it apart: Like the code flow, but the ID token arrives right in the redirect (with c_hash binding it to the code).
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Implicit (id_token, id_token token) Discouraged
Tokens arrive directly in the address: simpler, but exposed.
Text version of the diagram
- Browser (SPA): Generates state and nonce
- Browser (SPA) → Provider (OP) : GET /authorize (response_type=id_token token)
- Provider (OP) → Browser (SPA) : 302 redirect_uri#id_token=…&access_token=…
- Browser (SPA): Reads the fragment, verifies the token
- Browser (SPA) → API : Authorization: Bearer access_token
Use when: Almost never. Only for old SPAs or to check that an application properly forbids it.
What sets it apart: No code exchange: no back channel, no refresh token, tokens visible in the browser history.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Refresh Token Complement
Renew a short-lived access token without asking the person again.
Text version of the diagram
- Application → API : Authorization: Bearer access_token
- API → Application: 401 invalid_token (expired)
- Application → Provider (OP) : POST /token (grant_type=refresh_token)
- Provider (OP): Revokes the old refresh token (rotation)
- Provider (OP) → Application : New access token + new refresh token
- Application → API : Authorization: Bearer new access_token
Use when: As soon as you want short access tokens while keeping the person signed in for a long time (offline_access scope).
What sets it apart: This is not a sign-in flow: it extends a session obtained with another flow.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Client Credentials Machine to machine
No person: the service authenticates with its secret.
Text version of the diagram
- Service → Provider (OP) : POST /token (grant_type=client_credentials, scope)
- Provider (OP): Verifies the client secret
- Provider (OP) → Service : access token
- Service → API : Authorization: Bearer access_token
- API → Service: Data
Use when: A service, a scheduled task or a daemon calling an API in its own name.
What sets it apart: No browser, no ID token, no refresh token: only an access token limited to the client's scopes.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Password (ROPC) Avoid
The application collects the password itself and sends it to the provider.
Text version of the diagram
- Person → Application: Enters username and password
- Application → Provider (OP) : POST /token (grant_type=password, username, password)
- Provider (OP) → Application: access token (+ refresh token) or error
Use when: Avoid. Only for migrating from an old system or for automated tests.
What sets it apart: Bypasses the provider's page: no MFA, no SSO, easier phishing.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Device Code (RFC 8628) Devices without a browser
The device displays a short code; the person validates it on their phone.
Text version of the diagram
- Device → Provider (OP) : POST /device_authorization
- Provider (OP) → Device : device_code, user_code, URL
- Device: Shows "go to … and enter ABCD-EFGH"
- Phone / computer → Provider (OP): Opens the address, enters the code, signs in
- Device → Provider (OP) : POST /token (device_code) in a loop
- Provider (OP) → Device: authorization_pending, then the tokens
Use when: Television, console, connected object, command-line tool.
What sets it apart: Sign-in happens on another device. The device polls the provider until validation.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Token exchange (RFC 8693) Specific cases
Exchange one token for another, for a different recipient.
Text version of the diagram
- API A → Provider (OP) : POST /token (grant_type=token-exchange, subject_token, audience=B)
- Provider (OP): Checks rights and audience
- Provider (OP) → API A: access token for API B
- API A → API B : Authorization: Bearer new token
Use when: An API that must call another one on behalf of the person, or microservices that propagate identity.
What sets it apart: Starts from a token already obtained, without a new sign-in. Can reduce the rights or change the audience.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Logout (RP-initiated and back-channel) Session
Close the session at the provider and notify the other applications.
Text version of the diagram
- Browser → Application A: Clicks "Sign out"
- Application A → Browser : 302 to /logout (id_token_hint, post_logout_redirect_uri)
- Browser → Provider (OP) : GET /logout
- Provider (OP): Closes the provider session
- Provider (OP) → Application B : POST logout_token (back-channel)
- Provider (OP) → Browser : 302 to post_logout_redirect_uri
Use when: Any application with single sign-on (SSO): the logout must propagate.
What sets it apart: The back channel notifies server to server, without going through the browser (so it is reliable).
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
Introspection and revocation Check
Ask the provider whether a token is still valid, or invalidate it.
Text version of the diagram
- API → Provider (OP) : POST /introspect (token)
- Provider (OP) → API : { "active": true, scope, exp, sub }
- API → Provider (OP) : POST /revoke (token)
- Provider (OP) → API: 200 : the token is invalid
Use when: An API that receives an opaque token, or that wants immediate revocation.
What sets it apart: A JWT can be verified alone by its signature; an opaque token requires this call.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
private_key_jwt and JWT Bearer (RFC 7523) In ID-Kit: test provider
The client proves its identity with a JWT signed by its private key, rather than with a shared secret.
Text version of the diagram
- Service: Signs a JWT (iss, sub, aud, exp, jti)
- Service → Provider (OP) : POST /token (client_assertion, client_assertion_type)
- Provider (OP): Verifies the signature with the client's public key
- Provider (OP) → Service : access token
Use when: Banking, healthcare, sensitive APIs, enterprise integrations: no secret to store or rotate.
What sets it apart: Same exchange as client credentials, but authentication is a signed assertion (client_assertion).
ID-Kit can play it on the test provider side (declare your client's public key, type "Confidential by key"). Not yet on the test application side.
PAR and JAR (RFC 9126 and 9101) In ID-Kit
The authorization request is pushed server to server, instead of passing in clear in the address.
Text version of the diagram
- Application → Provider (OP): POST /par (all parameters, signed)
- Provider (OP) → Application : request_uri (valid for a few seconds)
- Application → Browser : 302 to /authorize?request_uri=…
- Browser → Provider (OP) : GET /authorize?request_uri=…
- Provider (OP) → Browser: Sign-in then redirect with the code
Use when: FAPI requirements: prevent a parameter from being modified or read in the browser.
What sets it apart: The browser only carries an opaque request_uri.
ID-Kit can play it: test provider (your application against ID-Kit) and test application (your provider against ID-Kit).
JARM (signed authorization response) In ID-Kit (test provider)
The provider also signs its response: the code arrives in a JWT, not in clear in the address.
Text version of the diagram
- Application → Browser : 302 to /authorize?response_mode=jwt
- Browser → Provider (OP) : GET /authorize then sign-in
- Provider (OP): Signs a JWT { iss, aud, code, state }
- Provider (OP) → Browser : Redirection to l’application ?response=JWT
- Browser → Application : Forwards response
- Application: Verifies the signature, iss, aud, then reads the code
Use when: FAPI 2.0, regulated sectors, protection against mix-up attacks between providers.
What sets it apart: A single "response" parameter (JWT signed with iss, aud, exp, code, state) replaces the plain parameters.
ID-Kit can play it on the test provider side (declare your client's public key, type "Confidential by key"). Not yet on the test application side.
DPoP (RFC 9449) In ID-Kit (test provider)
The token is bound to a key that only the client holds: a stolen token is unusable.
Text version of the diagram
- Application: Creates a key pair
- Application → Provider (OP): POST /token + DPoP header (signed proof)
- Provider (OP) → Application: key-bound access token (cnf.jkt)
- Application → API : Authorization: DPoP token + new DPoP proof
- API: Verifies the proof and the link with the key
Use when: High security, exposed SPAs, sensitive APIs.
What sets it apart: Each call comes with a signed proof (DPoP header) proving possession of the key.
ID-Kit can play it on the test provider side (declare your client's public key, type "Confidential by key"). Not yet on the test application side.
CIBA (Client-Initiated Backchannel) In ID-Kit (test provider)
Authentication happens on the person's device, initiated by the server.
Text version of the diagram
- Application → Provider (OP) : POST /bc-authorize (login_hint, binding_message)
- Provider (OP) → Application : auth_req_id
- Provider (OP) → Phone: Notification: "Authorize this payment?"
- Phone → Provider (OP): The person accepts
- Application → Provider (OP): POST /token (auth_req_id) in a loop, or callback
- Provider (OP) → Application : Tokens
Use when: Call centers, banks, payment confirmation by notification.
What sets it apart: No browser redirect: the provider contacts the person directly.
ID-Kit can play it on the test provider side (declare your client's public key, type "Confidential by key"). Not yet on the test application side.