OAuth + OIDC security — the PKCE and state checks you cannot skip
Most OAuth bugs come from skipping PKCE, ignoring state, or accepting tokens issued for a different client. Here is the correct implementation in a Next.js + NextAuth app.
OAuth and OIDC are secure protocols with many unsafe implementations. The safe version requires PKCE for public clients, state for CSRF, nonce for OIDC, and token-audience verification.
What it is
OAuth 2.0 grants an app delegated access to a resource on behalf of a user. OIDC builds identity on top. Secure use requires the small set of checks below.
Vulnerable example
// Vulnerable: no state, no PKCE, no audience check on ID token
const auth_url = `https://provider.com/authorize?client_id=${id}&redirect_uri=${redir}&response_type=code`;
// redirect user; receive code; exchange for tokens; decode JWT without verifying audience.Fixed example
// Fixed: PKCE + state + nonce + audience check
import { randomBytes, createHash } from "crypto";
const state = randomBytes(16).toString("base64url");
const nonce = randomBytes(16).toString("base64url");
const code_verifier = randomBytes(32).toString("base64url");
const code_challenge = createHash("sha256").update(code_verifier).digest("base64url");
// store state, nonce, code_verifier in session
// include state, nonce, code_challenge_method=S256, code_challenge in authorize URL
// on callback: verify state matches, exchange code with code_verifier,
// verify id_token signature, audience, issuer, nonceHow Securie catches it
Securie audits every OAuth implementation in the repository — NextAuth, Clerk, custom, Lucia — requiring PKCE, state, and explicit audience verification.
Checklist
- PKCE enforced for all public clients (required for SPAs and mobile)
- State parameter included and validated on callback
- OIDC nonce included in id_token and verified
- ID token audience + issuer verified
- Access token never passed through a query parameter (use Authorization header)
- Refresh tokens rotated with reuse detection
FAQ
If I use NextAuth, do I need to do any of this?
NextAuth does most of it. Review that your provider config sets the right scopes and that any custom providers inherit the safe defaults.