Google Cloud What does the email_verified claim indicate in Google ID Tokens?

When you authenticate a user by using OpenID Connect and request the email scope, most identity providers add two additional claims to the ID Token, email and email_verified. The email claim does not need much explanation – but what about email_verified, what does this claim indicate and how does Google populate it?

The email_verified claim is defined as part of the OpenID Connect standard claims set as:

True if the End-User's e-mail address has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed.

The Google docs are not much more specific:

True if the user's e-mail address has been verified; otherwise false.

So let’s take a closer look at how Google populates the email and email_verified claims by examining a few example ID Tokens.

Gmail user

First, let’s look at the ID Token of a Gmail user. Its claims look like this:

iss            https://accounts.google.com
azp            ...19nh.apps.googleusercontent.com
aud            ...19nh.apps.googleusercontent.com
sub            106368166...
email          [email protected]
email_verified True
at_hash        n879grk0yDwMjWx92oPjRQ
iat            1609589400
exp            1609593000

The email address of a Gmail address is by definition a proper email address, so there are few surprises here: email contains the primary email address and email_verified is true.

Consumer account

Next, let’s check a user that has been created using the use my existing email address option in the sign-up form:

iss            https://accounts.google.com
azp            ...19nh.apps.googleusercontent.com
aud            ...19nh.apps.googleusercontent.com
sub            1159645970...
email          [email protected]
email_verified True
at_hash        C3Fsz4MTMsLk7yVeuTXdzw
iat            1609590284
exp            1609593884

When you sign up with an existing email address, Google sends you an email with a confirmation link that you have to click. As a result, email_verified is set to true.

Notice that it might have been a long time ago that the email was confirmed and it is well possible that by now, the email address does not exist anymore. But the specification does not care about that.

Workspace user

Next up, let’s look at a Google Workspace (née G Suite) user:

iss            https://accounts.google.com
azp            ...19nh.apps.googleusercontent.com
aud            ...19nh.apps.googleusercontent.com
sub            113269283...
hd             workspace.example.com
email          [email protected]
email_verified True
at_hash        tqbVRCaYo2QaEXHvDa7Hqg
iat            1609588745
exp            1609592345

The first thing to notice here is the additional hd claim which indicates:

The hosted G Suite domain of the user. Provided only if the user belongs to a hosted domain.

In other words, if the ID Token has a hd claim, we know that the user is a managed user account.

By default, every Workspace user gets Gmail – so it is tempting to assume that [email protected] must be a valid, routable email address. But it does not have to be: As the administrator of a Google Workspace account, you can disable Gmail for one or more users. If the administrator of example.com did that, [email protected] would still be the username that Charlie uses to sign in – but any emails to [email protected] would go nowhere.

Regardless of whether Gmail is enabled or disabled for a user, the ID Token reports email_verified as true. That might seem surprising, but to quote the OpenID specification once again:

The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating.

Google Workspace is a paid service and signing up for a Google Workspace account requires that you prove ownership of a DNS domain. Although [email protected] might not be a routable email address, these properties of a Google Workspace account arguably seem enough to indeed consider the email address verified in the OpenID Connect sense.

Cloud Identity user

Let’s move on to Cloud Identity:

iss            https://accounts.google.com
azp            ...19nh.apps.googleusercontent.com
aud            ...19nh.apps.googleusercontent.com
sub            107547574...
hd             cloudidentity.example.org
email          [email protected]
email_verified True
at_hash        muegjYZiZZmXmM82NR9cgA
iat            1609656591
exp            1609660191

Unsurprisingly, the situation with Cloud Identity is similar to Google Workspace: We see the hd claim indicating that we’re dealing with a managed user account and email_verified is set to true. As with Google Workspace, we cannot be sure whether [email protected] is indeed a routable email address – but the fact that it’s Cloud Identity and that Cloud Identity also requires DNS domain verification again seem sufficient to consider the email address verified in the OpenID Connect sense.

Chrome Device Management

Google Workspace and Cloud Identity both require domain verification. Does that mean that whenever we see an hd claim in a token, we know that the domain must have been verified?

As it turns out, the answer is no.

If you sign up for Chrome Browser Cloud Management, you are provisioned with an account that is similar to a Google Workspace or Cloud Identity account. That is, you can sign in to admin.google.com to manage users and, of course, Chrome browsers.

Unlike Google Workspace and Cloud Identity, signing up for Chrome Browser Cloud Management does not require you to bring your own domain. Instead, Google auto-provisions a .deviceadmin.goog subdomain for you.

The ID Token of a Chrome Browser looks just like this:

iss            https://accounts.google.com
azp            ...19nh.apps.googleusercontent.com
aud            ...19nh.apps.googleusercontent.com
sub            110487664...
hd             example.deviceadmin.goog
email          [email protected]
email_verified True
at_hash        b_EDFAXj8f5BoSf_Bfhffw
iat            1609589338
exp            1609592938

Again, email_verified is set to true, which might seem a little dubious given that [email protected] is definitely not a routable email address and DNS verification has not taken place either. However, one thing I did not mention is that signing up for Chrome Browser Cloud Management requires you to verify your email. So [email protected] might not be a routable or verified email address – but the owner of the Chrome Browser Cloud Management did indeed verify their email address.

Conflicting user

Finally, let’s look at an oddball scenario – a conflicting user account:

iss            https://accounts.google.com
azp            ...19nh.apps.googleusercontent.com
aud            ...19nh.apps.googleusercontent.com
sub            115964597...
email          frank%[email protected]
email_verified True
at_hash        0-dyDJse2j_lJFSuGUe7Wg
iat            1609590419
exp            1609594019

A consumer account becomes a conflicting user account if a Cloud Identity or Google Workspace administrator (deliberately or inadvertently) creates a managed user with the same email address.

A conflicting user account is still a consumer account, so the ID Token does not contain an hd claim. What is special about a conflicting user’s claims is their email address: Instead of reporting the user’s original email address ([email protected] in this case), the ID Token contains frank%[email protected].

Because there cannot be two users with the exact same email address, a consumer account is temporarily renamed once the conflict ensues. Frank is still able to sign in using his old email address, but sooner or later he has to change his email address to something else. In the meantime, Google considers the frank%[email protected] to be his primary email address and hence reports this email address in the token.

Once again, email_verified is true – which does seem to be a bit of a stretch since frank%[email protected] is obviously not a routable email address and we cannot rely on any of the other assurances that Cloud Identity, Workspace, or Chrome Browser Management accounts provided either. But a consumer account does not come out of thin air – the user account must have been named [email protected] before and as we saw earlier, consumer accounts with an external email address always require an email confirmation.

Takeaway

The email_verified claim is easy to misinterpret. Its name suggests that if it is true, the email claim must contain a proper, routable email address. But this is evidently not the case.

First, the OpenID specification is much laxer than the name of the two claims suggest. The specification neither requires email to be a routable email address nor does it require email_verified to only be true if some kind of email double opt-in has taken place.

Second, it is rather unlikely that you will ever see a Google-issued ID Token with an email_verified claim set to false. I suppose there are some edge case scenarios where this might happen, but I don’t even know how to reproduce one.

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.
« Back to home