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.