Skip to content

feat(token): add access_token grant for signing in with a Facebook access token#2609

Open
spydon wants to merge 1 commit into
masterfrom
feat/facebook-access-token-grant
Open

feat(token): add access_token grant for signing in with a Facebook access token#2609
spydon wants to merge 1 commit into
masterfrom
feat/facebook-access-token-grant

Conversation

@spydon

@spydon spydon commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

What

Adds a new access_token grant to POST /token that lets a client sign in with a provider-issued OAuth access token instead of an OIDC id token. Initially wired up for Facebook only.

POST /token?grant_type=access_token
{ "provider": "facebook", "access_token": "<facebook classic access token>" }

Why

Driven by native Facebook login on Android (supabase/supabase-flutter#1287). Investigation established that native Android cannot produce an OIDC id token for the common case, so the existing id_token grant is a dead end there. Exchanging the classic access token server-side is the mainstream solution.

Findings

  • Facebook's OIDC id token (Limited Login) is iOS-only. Facebook's docs state Limited Login is "tied to iOS applications" and "Android users are unaffected." The only non-iOS way to obtain an id_token is the web Code Flow with PKCE, i.e. the browser flow (signInWithOAuth).
  • Native Android reliably returns a classic access token, never a repeat id token. With a nonce + LoginConfiguration, Facebook mints an AuthenticationToken only on the first authorization; every subsequent login returns a classic access token with authenticationToken == null (confirmed on device across Android versions, and traced through facebook-android-sdk 18.x — the instant get-token handler wins and no native handler mints an id token on a cached grant). See Facebook Login - Obtain null Authentication token facebook/facebook-android-sdk#1132.
  • This matches how the major providers already do it. Firebase uses FacebookAuthProvider.getCredential(accessToken); Auth0 does a server-side token exchange of the Facebook access token. Neither relies on a native id token.

Net: iOS keeps using id_token (Limited Login); Android uses this new access_token grant.

How

  • New AccessTokenGrant handler (grant_type=access_token): resolves the provider, confirms it's enabled, verifies the token, fetches the profile via the existing GetUserData, then creates/links the account and issues a session, reusing the same path as IdTokenGrant.
  • facebookProvider.VerifyAccessToken calls Facebook's /debug_token with the app access token and rejects the request unless the token is_valid and its app_id matches this app's client id. This mitigates access-token substitution (a token minted for a different Facebook app being replayed against this one).
  • The grant is opt-in per provider via the new provider.AccessTokenVerifier interface, so today only facebook is accepted; other providers get a clear 400.

Tests

internal/api/token_access_token_test.go: success, token issued for another app (rejected), invalid token (rejected), missing token, and an unsupported provider. All pass against Postgres.

Follow-ups (separate PRs)

  • Client method in supabase-flutter (and other SDKs) to call this grant.
  • Optional: accept multiple configured Facebook client ids in VerifyAccessToken (currently checks the primary), and consider generalizing the grant to other providers that can verify token audience.

Comment thread internal/api/provider/facebook.go Outdated
Comment thread internal/api/token_access_token.go Outdated
Comment thread internal/api/provider/facebook.go
@spydon spydon force-pushed the feat/facebook-access-token-grant branch from 1d3f849 to 16f15c6 Compare July 3, 2026 08:39
Comment thread internal/api/provider/facebook.go
…cess token

Facebook's native Android login reliably returns a classic Graph access token on every login, but only mints an OIDC id token (AuthenticationToken) on the first authorization, which makes the id_token grant unusable for repeat native logins without falling back to the browser flow.

Add an access_token grant that accepts a provider-issued access token, verifies via Facebook's /debug_token that it was issued for this app, is valid, and is a user token (mitigating access token substitution), fetches the profile and issues a session. The grant is only available to providers that implement the new AccessTokenVerifier interface, which for now is Facebook only.
@spydon spydon force-pushed the feat/facebook-access-token-grant branch from 16f15c6 to 39ea58a Compare July 3, 2026 09:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant