A mobile app sends your Laravel API a Google token for Socialite's userFromToken(); what does Socialite check about that token, and what does it leave to you?
answer
- no callback, no state, no code
- a JWT versus an opaque access token
- signature, issuer and audience
- userinfo accepts any valid token
- then issue your own API token
basics
~20 suserFromToken() fetches the profile for a token the client already holds. For a Google ID token, Socialite verifies signature, issuer and audience; an opaque access token just goes to userinfo, with no check of which app it was issued to.
solid answer
~50 s`userFromToken($token)` maps a provider user from a token the client already obtained, with no redirect, state or code exchange; it returns the same `Two\User` with `token` set. What it verifies depends on the driver. The Google driver treats a three-part token longer than 100 characters as an **ID token**: it checks the signature against Google's published keys, requires `iss` to be `https://accounts.google.com` and `aud` to equal your `client_id`, and uses the claims as the profile. Any other token is sent to Google's userinfo endpoint, which answers for **any** valid access token, including one issued to a different app; Socialite does not check its audience. The GitHub driver likewise just calls the user API. So for mobile Google sign-in, have the app send the ID token, then map the member by provider id and return your own API token, for example a Sanctum token.
go deeper
Know that userFromToken() turns a token the client already has into a Socialite user, without the redirect and callback.
Explain how the Google driver treats ID tokens versus access tokens and what each path verifies.
Spot token substitution through opaque access tokens, insist on ID tokens for Google, and exchange the identity for your own API token.
Decide whether mobile sign-in should run through your backend's OAuth flow or accept device tokens, and what audit trail the exchange endpoint needs.
## Why `userFromToken()` exists In a browser, Socialite runs the whole redirect-and-callback dance. A **mobile app** usually signs the member in with the provider's native SDK and ends up holding a token itself. It then needs your Laravel API to answer one question: *which member is this?* `userFromToken($token)` is the Socialite entry point for that: ```php use Laravel\Socialite\Socialite; $social = Socialite::driver('google')->userFromToken($request->input('token')); ``` There is no `state`, no `code` and no session involved; Socialite goes straight to "get the profile for this token" and returns a `Laravel\Socialite\Two\User` with `token` set to what you passed. ## What the Google driver checks The Google driver branches on the token's shape: | Token given | How Socialite recognises it | What it verifies | |---|---|---| | **ID token** (a JWT) | exactly two dots and longer than 100 characters | signature against Google's published key set, `iss` equals `https://accounts.google.com`, `aud` equals your configured `client_id` | | **Access token** (opaque) | anything else | nothing about the token itself; it calls Google's userinfo endpoint with it | A failed ID-token check surfaces as a plain `Exception` whose message starts "Failed to verify Google JWT token". The access-token path is the gap. Userinfo returns the profile for **any** valid Google access token, including one that another app obtained for the same person. If a malicious app your member once used replays that token against your API, Socialite happily returns the member's profile and your API signs the attacker in. This is the classic token-substitution problem; the defence is to accept a token that names your app as its audience. ## Other drivers - **GitHub** has no ID token; `userFromToken()` calls the user API, which again accepts any valid token for that member. - **Facebook** accepts an optional nonce, `userFromToken($token, $nonce)`, for tokens from its limited-login flow on iOS. So on a developer-community site whose mobile app offers GitHub and Google: 1. For **Google**, require the app to send the **ID token** and let Socialite's checks run. 2. For **GitHub**, prefer running the OAuth flow through your own backend so the token is minted for your client, rather than accepting arbitrary tokens from the device. 3. Rate-limit and log the exchange endpoint like any login endpoint. ## What stays your job - **Mapping** the result to a local account by provider and `getId()`, with the same email-linking rules as the web callback. - **Issuing your own credential.** The provider's token proves identity to *you* once; the mobile app should then call your API with *your* token, for example a Sanctum personal access token, not keep sending Google's. - **Not storing** the provider token unless a feature needs to call the provider's API. ```php Route::post('/auth/google/token', function (Request $request) { $social = Socialite::driver('google')->userFromToken($request->input('id_token')); $member = app(ResolveSocialMember::class)->handle('google', $social); // your own action class return ['token' => $member->createToken('mobile')->plainTextToken]; }); ``` ## Errors to expect - A forged, expired or foreign ID token makes the Google driver throw; map that to a 401 response rather than a 500. - An invalid or revoked access token makes the provider's API answer with an error status, which the HTTP client turns into an exception. - A missing or empty token should be rejected by validation before Socialite is called at all. ## Summary - `userFromToken()` replaces the browser flow for clients that already hold a token. - Only Google ID tokens get signature, issuer and audience checks. - Opaque access tokens are accepted for whoever they belong to, whichever app they were issued to. - Always exchange the provider identity for your own API token.
- Does userFromToken() need stateless() in a sessionless API?No. `userFromToken()` never touches the session: it skips the state check and the code exchange and goes straight to fetching the profile. `stateless()` only changes `redirect()` and `user()`, which a token-exchange endpoint does not call.
- What does Socialite's refreshToken() return, and when would the mobile flow need it?`refreshToken($refreshToken)` posts a refresh grant to the provider and returns a `Laravel\Socialite\Two\Token` with `token`, `refreshToken`, `expiresIn` and `approvedScopes`. The sign-in exchange does not need it; it matters only when your backend keeps calling the provider's API for the member after the access token expires.
saying these in an interview costs you the question
- userFromToken() validates that every token was issued to your client_id
- userFromToken() requires the state parameter from the original redirect
- Any token the Google userinfo endpoint accepts is safe to sign in with
- The API should keep accepting the provider token on every later request
- Socialite checks a GitHub token's audience before calling the user API