Is it possible to get profile information in an id_token from Google?
Asked Answered
B

4

24

When using Google's OpenIDConnect authentication system, it's possible to specify email or profile or both in the scope parameter. If you request the email scope, the "email" and "email_verified" claims will be included in the id_token that gets returned as part of a successful OAuth2 authentication session.

Here's an example from Google's documentation:

An ID token's payload

An ID token is a JSON object containing a set of name/value pairs. Here’s an example, formatted for readability:

{"iss":"accounts.google.com", 
 "at_hash":"HK6E_P6Dh8Y93mRNtsDB1Q", 
 "email_verified":"true",
 "sub":"10769150350006150715113082367", 
 "azp":"1234987819200.apps.googleusercontent.com", 
 "email":"[email protected]", 
 "aud":"1234987819200.apps.googleusercontent.com", 
 "iat":1353601026, 
 "exp":1353604926,
 "hd":"example.com" 
}

However, requesting the profile scope seems to have no effect whatsoever on the contents of the id_token. In order to retrieve the profile information, you have to make a separate HTTP request to a distinct endpoint (authenticated with the access_token you just received) to get a document that looks very similar, but with more information:

{
  "kind": "plus#personOpenIdConnect",
  "gender": string,
  "sub": string,
  "name": string,
  "given_name": string,
  "family_name": string,
  "profile": string,
  "picture": string,
  "email": string,
  "email_verified": "true",
  "locale": string,
  "hd": string
}

Ideally, I would prefer to get the profile information (just name, actually) included in the id_token JWT rather than having to make a separate call. Is there any way to specify additional fields and have them included as claims in the id_token? If not, why is email treated specially and returned in the id_token?

Baily answered 24/8, 2015 at 5:47 Comment(0)
S
17

Starting today you will get profile information when exchanging the code at the token endpoint (i.e. using the "code flow").

How to use: add the profile scope to your request, and make sure you are using the OpenID Connect compliant endpoints (the ones listed in https://accounts.google.com/.well-known/openid-configuration).

Look for claims such as name and picture in these ID Token responses. As before, if the email scope is in your request, the ID Token will contain email related claims.

When you refresh your access token, every so often the ID Token that is returned with the fresh access token will also contain these additional claims. You can check these fields, and if present (and different to what you have stored), update your user's profile. This can be useful to detect name or email address changes.

Sighted answered 4/9, 2015 at 21:5 Comment(9)
In theory this should work, however, the id tokens I receive don't contain any profile info. authorization_uri: accounts.google.com/o/oauth2/… id token keys: ["azp", "aud", "sub", "email", "email_verified", "at_hash", "iss", "iat", "exp"]Condillac
@Willam Denniss: for some reason during refreshing access token id_token doesn't contain any profile info.Stock
With the URL googleapis.com/oauth2/v4/token it works, Thanks.Hyperextension
This functionality appears to be broken. ID tokens do not contain picture nor name claims when requested using the endpoints linked in the answer. Nor does it work with the token URL @Hyperextension suggested using.Redshank
i just got this to work: 1. accounts.google.com/o/oauth2/v2/auth with my client_id, redirect_uri, and state and response_type=code and scope=openid+email+profile. 2. oauth2.googleapis.com/token with code returned by the first call, my client_id and client_secret and redirect_uri, and grant_type=authorization_code. Got an id_token with sub, name, given_name, profile, picture, email, email_verified, locale, and hd -- didn't need to hit openidconnect.googleapis.com/v1/userinfoNereen
I still can't get it work, checked everything. What can I do more? Can anybody help?Biak
Did you ever figure this out, Maria? Struggling with it myself.Preclinical
payload for google ID token that I am recieving from the google auth token has name, given_name, etc, but the payload of the google ID token I am recieving from the google refresh token doesn't have the profile information it only contains ["azp", "aud", "sub", "email", "email_verified", "at_hash", "iss", "iat", "exp"] why am I encountering this issue?Satin
According to this answer, the profile information is only included "every so often" when using a refresh token -- not on every new token. I'm guessing this is a performance optimization by Google.Baily
W
7

When a request is made with response_type=id_token and profile in the scope like scope=openid+profile+email, the resulting id token should contain the profile claims directly in it.

This is per section 5.4 of the OpenID Connect spec, which says "... when no Access Token is issued (which is the case for the response_type value id_token), the resulting Claims are returned in the ID Token."

However, in a little testing I did with their OAuth 2 Playground, Google doesn't seem to put profile claims in the id token even when response_type=id_token and no access token is issued. I'd argue that this is an implementation defect on Google's part and, short of them fixing that (or adding support for the "claims" Request Parameter), there doesn't seem to be a way to accomplish what you're looking for.

Wergild answered 24/8, 2015 at 14:7 Comment(5)
I appreciate the confirmation, at least. I don't suppose you know if there's any place to request OpenIDConnect bugfixes/enhancements from Google?Baily
I don't know. But will make a polite inquiry to some folks that might know better than I.Wergild
I'm told that there is not an open bug tracker or anything like that for OpenID Connect but that they are evaluating placing more claims in the id token and will look at the specific response_type=id_token case (where there is no access token) in the course of that. Though they can't commit to if or when that would actually be done. They are at least aware. That's the best I can do on this one.Wergild
Thank you, much appreciated!Baily
For people still looking for a fix/workaround, adding openid in scope as suggested in this answer does the trick. The scopes profile and email are actually userinfo scopes and not tokeninfo scopes, a bit different from what the docs sayHg
S
1

Well, this is the right place to request. We are working to support this feature and should be rolling this out soon (in the next few weeks). I'll make an update to this response then.

Saleem answered 25/8, 2015 at 5:20 Comment(2)
Any update? Trying to get this working and I'm seeing the email when I don't ask for the email, but no "profile object" as indicated in the developer docs.Innutrition
See William's answer. We did roll this out. What scopes are you requesting and does the account you use to approve have a public visible name?Saleem
P
1

Yes, it's possible, I've implemented the Google login functionality!

    const { code } = req.body;

    const clientId = process.env.GOOGLE_CLIENT_ID;
    const clientSecret = process.env.GOOGLE_CLIENT_SECRET;
    const redirectUri = process.env.CLIENT_URL + '/googleLogin'; // You can add your own url here

    const tokenEndpoint = 'https://oauth2.googleapis.com/token';

    // Exchange authorization code for access token and ID token
    const response = await axios.post(
        tokenEndpoint,
        qs.stringify({
            code: code,
            client_id: clientId,
            client_secret: clientSecret,
            redirect_uri: redirectUri,
            grant_type: 'authorization_code',
        }),
        { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
    );

    const idToken = response.data.id_token;
    const decoded = jwt.decode(idToken);
    const email = decoded?.email;

Here's a breakdown of the key steps involved:

  1. Retrieving the Authorization Code: We first obtain the authorization code from the user's browser after they've completed the Google login flow.

  2. Exchanging the Code for Tokens: We make a POST request to the Google OAuth 2.0 token endpoint, providing the authorization code along with our client ID, client secret, and redirect URI. Google responds with both an access token (for API calls) and an ID token (containing user information).

  3. Extracting User Information from the ID Token: We decode the ID token using a JWT library, revealing the user's email address and other relevant details.

  4. No Additional API Calls Required: Crucially, we don't need to make any further API calls to Google to retrieve user information—it's all contained within the ID token!

This cost me a lot of time, and I hope this might be helpful. The Google documentation is way poor in this regard.

Pomace answered 25/1 at 11:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.