Separate the three participants
The browser application starts the sign-in flow, the identity provider authenticates the user, and the API validates access tokens. A successful login does not prove the API will accept the resulting token.
Capture the intended issuer, client ID, redirect URI, response type and scopes. Check the exact redirect URI rather than assuming that two similar URLs are equivalent.
Follow the code exchange
With PKCE, the client creates a verifier and sends a derived challenge in the authorization request. The token request must present the matching verifier. Losing it during a redirect or attempting to reuse a code can make the exchange fail.
Do not log tokens or verifiers. Check request structure, the timing of storage changes and the identity provider’s sanitized error response instead.
Then check API authorization
An access token must be intended for the API and issued by the trusted authority. Validate issuer, audience, signature and lifetime before inspecting application permissions. An ID token is not a substitute for an API access token.
Once authentication succeeds, scope and authorization policy can still deny the operation. Keeping these steps separate makes a 401 or 403 much easier to investigate.
Further reading
Primary documentation & specification