Overview
This article explains how the ‘phone_number_verified’ claim can be added to the ID Token.
Applies To
- ID Token
- OIDC
- Phone number verified
- Phone_number_verified claim
- Phone scope
- Phone_verified property
- Passwordless SMS connection
Solution
When a user is identified via the passwordless SMS connection, two properties are generated in the Auth0 profile: phone_number and phone_verified.
The OIDC spec defines the scope phone that should return the phone number and its verified status claims. However, the standard OIDC claim for the verified flag is phone_number_verified
, different from the phone_verified
property in the Auth0 user profile.
In order for the application to get the phone verified status when requesting the openid phone scopes, it is recommended to use Auth0 post-login Action for this purpose. An example action is located below:
exports.onExecutePostLogin = async (event, api) => {
// "phone_verified" is a non-standard property from the Auth0 user profile.
// "phone_number_verified" is the standard OIDC claim.
// This Action ensures the standard claim is present in the ID token.
if (event.user.hasOwnProperty('phone_verified')) {
api.idToken.setCustomClaim('phone_number_verified', event.user.phone_verified);
}
};
Once the Action is deployed and active in the login flow, when an application requests the 'openid phone’ scopes, the ID token issued by Auth0 will include both the phone_number and phone_number_verified claims in its payload, similar to this:
{
"phone_number": "+1<number>",
"phone_number_verified": true,
"iss": "https://<subdomain>.auth0.com/",
"sub": "auth0|abcdefgh038cae00688191e0",
"aud": "<aud>",
"iat": 1622747501,
"exp": 1622751101,
"nonce": "nonce"
}
If not using a Passwordless SMS Connection
The “phone_number” can also be set directly in the action, in case if the phone number needs to be retrieved from a different place (e.g. metadata), and it will work even if it’s not a Passwordless SMS connection. For this example, Auth0 post-login Action was used to achieve this result:
exports.onExecutePostLogin = async (event, api) => {
// This is an example of how to get phone data from a different source,
// like app_metadata.
// Remember that you need the "phone" scope in the request to get these two values.
if (event.transaction && event.transaction.requested_scopes.includes('phone')) {
if (event.user.app_metadata && event.user.app_metadata.phone_number) {
api.idToken.setCustomClaim('phone_number', event.user.app_metadata.phone_number);
// Assuming you have a way to determine verification status from app_metadata or another source.
// For this example, we'll set it to false if not explicitly verified.
api.idToken.setCustomClaim('phone_number_verified', event.user.app_metadata.phone_verified || false);
}
}
};