Four roles and three different tokens
For example, a document app needs to display approved files from an API. The user is the resource owner. The app is the client. The authorisation server processes consent and issues tokens. The document API is the resource server, checking access against its contract. These roles may belong to the same organisation but remain technically distinct recipients. RFC 6749, section 1, describes the foundations.
On narrow screens, scroll the table sideways.
| Item | Purpose and recipient | Common misconception |
|---|---|---|
| Access token | Credential for the intended API | Any valid token may call any API |
| ID token | The OpenID Provider's statement about the login for the client | It automatically serves as an access token for a business API |
| Refresh token | Obtain a new access token from the authorisation server | It must accompany every resource request |
Among other requirements, OpenID Connect requires the correct issuer and audience for an ID token. Its aud refers to the client. The business API instead needs an access token issued for it and validated according to its profile. See OpenID Connect Core, sections 2 and 3.1.3.7.
Client type determines how secrets are handled
A confidential client can protect credentials in a controlled server-side environment. A public client, such as delivered browser JavaScript, cannot keep an embedded shared secret confidential. A client_id is an identifier rather than a secret in any case.
PKCE does not replace this distinction. It binds redemption of an authorisation code to a value generated by that client for this flow. It is neither a user password nor, on its own, client authentication. A service without interactive user consent may use a different flow such as Client Credentials. Base this choice on the authentication task.
Understand Authorization Code with PKCE
The following flow is a synthetic illustration. In a real integration, endpoints and details come from trusted configuration and the SDK used.
- The app starts a new login or consent transaction and generates a random
code_verifierused only for this transaction. It calculates the PKCE challenge from it usingS256. - It redirects the browser to the known authorisation endpoint. Parameters include the client identifier, registered redirect URI, requested permissions and challenge. OIDC also uses its login context.
- The authorisation server processes login and the required consent. It sends a short-lived code through the browser to the specified redirect URI.
- The client associates this response with the transaction it started and redeems the code at the token endpoint. It supplies the
code_verifierand, where required, its client authentication. - After successful verification, the authorisation server returns the tokens intended for this transaction. The client validates responses intended for it and uses the access token exclusively for the appropriate API.
RFC 7636, section 4, describes the PKCE binding. The current security baseline, RFC 9700, section 2.1.1, requires PKCE for public clients and recommends it for confidential clients. S256 prevents the verifier from being exposed in the authorisation request.
Synthetic client example · no login performed
From sign-in to API authorisation
Example: a server-side document app is the confidential client. The user is the resource owner and operates it in a browser. The app backend uses OIDC and Authorization Code with PKCE, redeems the code itself and calls the document API. The authorisation server is also the OpenID Provider; the document API is the resource server.
- App backend: begin a new transaction
The client generates a random
code_verifierfor this transaction only and derives the PKCE challenge usingS256. - App backend → browser → authorisation server
The browser is directed to the known authorisation endpoint with the client ID, registered redirect URI, requested permissions, challenge and OIDC sign-in context.
- User ↔ authorisation server
The server handles the user’s sign-in and the required consent.
- Authorisation server → browser → app backend
A short-lived code arrives at the designated redirect URI. The client checks its association with the transaction it began.
- App backend ↔ token endpoint
The client redeems the code with the
code_verifierand its intended client authentication. Only after successful validation does the authorisation server return the intended tokens.- ID token → client
- Describes the sign-in. The client validates it, including issuer and audience; it is not an access token for the document API.
- Access token → intended API
- Is intended for the agreed API access. The client uses it only with the designated API.
- App backend → document API
The API checks the access token for its audience context, validity and permissions. It also decides which objects, fields and functions this access may use. The
documents:readscope alone does not permit every document.
Transaction binding and permissions remain separate checks: PKCE binds code redemption to the verifier; it does not authenticate the client by itself. state and, in OIDC, nonce have their own roles and conditions. The complete integration must provide transaction binding, CSRF protection and correct issuer association. A successful sign-in does not replace API authorisation.
Redirect URI and transaction belong together
Register specific redirect URIs and use the provider's validation according to the current protocol profile. Broad patterns and open redirects increase the risk of a response reaching the wrong recipient. The narrow exception for native app loopback ports does not permit arbitrary web redirects.
The client must also recognise whether a response belongs to the transaction actually started. PKCE, state and, in OIDC, nonce have different purposes and conditions. Do not remove these safeguards yourself because a guide abbreviates the situation to ‘PKCE prevents CSRF’. The complete library and provider integration must provide transaction binding, CSRF protection and, with multiple issuers, correct issuer association. RFC 9700, section 2.1, sets out these requirements together.
For new integrations, a flow in which the client receives the user's main password is not a suitable shortcut. RFC 9700 prohibits use of the Resource Owner Password Credentials Grant. Access tokens directly in authorisation responses are likewise outside the code flow recommended here.
What the API must still check after login
The API checks the access token for its own audience context, its validity and permitted rights. Depending on the contract, this may require local JWT validation or a server-side token query. ‘Login succeeded’ does not replace this check.
A scope such as documents:read names an agreed permission range. It does not yet determine which document belongs to a user or tenant. The API must additionally enforce object, field and function permissions. For structured access tokens, continue with JWT validation; for the business rule, see object permissions.
Do not store tokens in URLs or complete logs. Transmit them only to their intended recipients. A signature does not automatically make claims confidential, and a valid bearer token can be misused after theft until effectively restricted.
Plan refresh, logout and revocation separately
A refresh token may enable access beyond the lifetime of a single access token. For public clients, RFC 9700 requires sender constraining or refresh token rotation. Rotation must account for reuse, concurrent refreshes and interrupted responses in the actual provider and client behaviour. Adding your own infinite refresh loop is not error handling.
Logout, session blocking and token revocation are separate operations. The revocation standard RFC 7009 describes a dedicated endpoint and possible effects on related tokens. Whether an issued access token immediately becomes ineffective everywhere depends on token type, validation and propagation of revocation state. Define and test this promise explicitly.
Verify your own flow within a defined scope
Use test users and your own test registration. Check normal access, a different redirect URI, a missing or incorrect verifier, an unrelated callback and an access token for another API. Expectations follow your profile; do not use other people's accounts or real production values in diagnostic tools.
Then check expiry, session blocking and revocation from the user's perspective. Demonstrate which access stops working when. Keep a previously working client configuration ready for rollout. If a secret is compromised, roll back with new trustworthy credentials rather than reactivating the old value.
The API Security Check performs no login, token validation or role checks. Appropriate evidence here comes from a correctly configured protocol implementation and your own integration tests. Sources checked: 27 September 2026; OIDC Core 1.0 including Errata Set 2 and OAuth Security BCP RFC 9700.
Sources and date
Sources checked: 27 September 2026. Links also appear alongside the statements they support.