Skip to content

Apple OAuth flow should include nonce to prevent ID token replay #385

Description

@bpowers

Description

The Apple OAuth sign-in flow does not include a nonce parameter. While the server performs JWKS-based verification of the Apple ID token (validating signature, issuer, audience, and expiry), it does not bind the token to a specific authentication request via a nonce.

Apple recommends including a nonce -- generated per authentication request and bound to the session/state -- to prevent ID token replay attacks. Without a nonce, a valid ID token intercepted from one authentication flow could theoretically be replayed in another session.

Why it matters

  • Security: Prevents ID token replay attacks, following Apple's recommended best practices for Sign in with Apple
  • Defense in depth: The existing JWKS verification and short token expiry provide strong baseline security, but nonce binding adds another layer

Components affected

  • src/server/ -- OAuth route handlers and token verification logic

Possible approach

  1. Generate a cryptographically random nonce during the authorization request
  2. Bind the nonce to the OAuth state parameter (which is already session-bound)
  3. Pass the nonce to Apple's authorization endpoint
  4. After receiving the ID token, verify that the nonce claim in the decoded JWT matches the expected value

Context

Identified during review of the server-side-auth branch (commits implementing server-side OAuth state binding and Apple provider handling).

Activity

  1. added
    backendInvolves the Google App Engine node app
    securitySecurity, auth hardening
    on Jun 8, 2026
  2. bpowers commented on Jun 9, 2026

    @bpowers
    OwnerAuthor

    This describes the server-side-auth branch (commit fec5fc61), which was never merged.

    On main there is no server-side Apple OAuth or JWKS token verification at all -- Sign in with Apple is handled entirely by the Firebase client SDK (signInWithRedirect in src/app/Login.tsx). The server-side ID-token verification this nonce would harden exists only on the unmerged branch.

    Closing as not applicable to main. The nonce hardening should be part of the server-side-auth work if it is revived.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendInvolves the Google App Engine node appsecuritySecurity, auth hardening

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions