How to check if a Google user have MFA enabled

Hello, I would like to implement google login on a web portal developed by us. I would like to allow anyone with a google account, even users outside our workspace, to access as long as they have two-factor authentication enabled.
Is there a way to check if a google user has MFA enabled or not?

0 1 1,639
1 REPLY 1

This is a forum dedicated to Apigee. I'm an Apigee expert, not an expert on Sign-in-with -Google.  There might be a better forum for asking your question, but I don't have any suggestions for you.  Even so, I like the question, I think it's interesting. Since I'm not an expert, take my response below with a grain of salt.

There is a standard claim for the JWT ID Token, amr, which is intended to convey the "Authentication Method Reference". This is described in the OpenID.Core spec. It is a claim like any other claim (iss = issuer, azp = authorized presenter, exp = expiry, iat = issued-at time, etc). While the amr claim name is standardized, values held within the amr claim are not. You can read about it in IETF RFC 8176 . Though there are no standards, there are some conventions. In section 2, it offers some values like pwd = password based authentication, pin = Personal Identification Number (PIN) auth, and otp = one-time password (the things served up by the Authenticator apps on your phone). One of the options is mfa = multi-factor auth.

That seems perfect! Just examine the ID token, check the amr claim, and see if it has the value "mfa".  Easy . Solved.

Alas, I think it is not so easy. As far as I know (and again I am not the expert on this), Sign-in with Google does not issue ID tokens with the amr claim. And I don't know of a way for you to "ask" Google to issue an ID token with that claim. The documentation I'm looking at , shows https://accounts.google.com/.well-known/openid-configuration as the Discovery document for signin-with-Google, and the response from that URL gives this list of supported claims in the ID token:

 "claims_supported": [
"aud",
"email",
"email_verified",
"exp",
"family_name",
"given_name",
"iat",
"iss",
"locale",
"name",
"picture",
"sub"
],

None of those indicate the authentication mechanism.

Even if you were able to get Google to issue an amr, the RFC 8716 advises that it is "brittle" and systems should be wary of depending on it. specifically in section 3 it advises that you should consider using the acr claim:

The "acr" (Authentication Context Class Reference) claim and "acr_values" request parameter are related to the "amr" (Authentication Methods References) claim, but with important differences. An Authentication Context Class specifies a set of business rules that authentications are being requested to satisfy. These rules can often be satisfied by using a number of different specific authentication methods, either singly or in combination. Interactions using "acr_values" request that the specified Authentication Context Classes be used and that the result should contain an "acr" claim saying which Authentication Context Class was satisfied. The "acr" claim in the reply states that the business rules for the class were satisfied -- not how they were satisfied.

In contrast, interactions using the "amr" claim make statements about the particular authentication methods that were used. This tends to be more brittle than using "acr", since the authentication methods that may be appropriate for a given authentication will vary over time, both because of the evolution of attacks on existing methods and the deployment of new authentication methods.

So, rather than depending on the answer to the question "was multi factor auth used?" , the RFC suggests that you should depend on the "class" of authentication. OpenID.CORE says:

[the acr claim] identifies the Authentication Context Class that the authentication performed satisfied. The value "0" indicates the End-User authentication did not meet the requirements of ISO/IEC 29115 [ISO29115] level 1. Authentication using a long-lived browser cookie, for instance, is one example where the use of "level 0" is appropriate. Authentications with level 0 SHOULD NOT be used to authorize access to any resource of any monetary value. (This corresponds to the OpenID 2.0 PAPE [OpenID.PAPE] nist_auth_level 0.) An absolute URI or an RFC 6711 [RFC6711] registered name SHOULD be used as the acr value; .... Parties using this claim will need to agree upon the meanings of the values used, which may be context-specific.

And again, sign-in-with-Google doesn't offer acr as a supported claim. So it gets complicated.

Maybe what you need to do is step back and re-examine your goals. What do you really want to do here? If you want to avoid bot traffic, you could use something like reCAPTCHA in concert with the google ID token, to verify that (a) Google has authenticated the user recently, and (b) Google does not believe the request is coming from a bot. Unlike the older "click the pictures that have images of a schoolbus" challenges, the v3 recaptcha uses device fingerprinting, so there is no interruption in the user experience.

Another option is to augment the sign-in-with-Google experience, and add your own "second factor" to that signin. For example you could issue a TOTP to the user (onboarding this is the experience where the user scans a barcode with their phone, and it opens in the Authenticator app). And your site could require that the user keys in the TOTP AFTER google has authenticated them. You could do that with an Apigee API proxy pretty simply. I built an example a long while ago showing how to do this. But you could build this in other systems too.  (Cloud run?  Firebase?).  You would need to be able to store a TOTP code for each unique signing-in user. And the user experience would be kinda wonky, especially for first sign in. Maybe not optimal.