From c073d9c7bab820f34154c9cd8595e0cb37c57039 Mon Sep 17 00:00:00 2001 From: Dudi Levy <4785835+dudil@users.noreply.github.com> Date: Thu, 4 Apr 2024 13:40:14 +0300 Subject: [PATCH] * Updated order to fit the curent documentation by MS * added the email and the oid claims --- fastapi_msal/models/id_token_claims.py | 88 ++++++++++++++------------ fastapi_msal/models/user_info.py | 48 +++++++++----- 2 files changed, 80 insertions(+), 56 deletions(-) diff --git a/fastapi_msal/models/id_token_claims.py b/fastapi_msal/models/id_token_claims.py index 7ad6cfe..5eeb23a 100644 --- a/fastapi_msal/models/id_token_claims.py +++ b/fastapi_msal/models/id_token_claims.py @@ -85,22 +85,11 @@ class IDTokenClaims(UserInfo, AADInternalClaims, BaseAuthModel): For more information: https://learn.microsoft.com/en-us/entra/identity-platform/id-token-claims-reference """ - exp: Optional[float] = None - """ - The expiration time claim is the time at which the token becomes invalid, represented in epoch time. - Your app should use this claim to verify the validity of the token lifetime. - """ - - not_before: Optional[float] = Field(time.time() - 1, alias="nbf") - """ - This claim is the time at which the token becomes valid, represented in epoch time. - This is usually the same as the time the token was issued. - Your app should use this claim to verify the validity of the token lifetime. - """ - - ver: OptStr = None + audience: Union[OptStr, list[str]] = Field(None, alias="aud") """ - Indicates the version of the token. + An audience claim identifies the intended recipient of the token. + For Azure AD B2C, the audience is your app's Application ID, as assigned to your app in the app registration portal. + Your app should validate this value and reject the token if it does not match. """ issuer: OptStr = Field(None, alias="iss") @@ -111,6 +100,11 @@ class IDTokenClaims(UserInfo, AADInternalClaims, BaseAuthModel): It also should use the GUID portion of the claim to restrict the set of tenants that can sign in to the app. """ + issue_time: Optional[float] = Field(None, alias="iat") + """ + The time at which the token was issued, represented in epoch time. + """ + identity_provider: OptStr = Field(None, alias="idp") """ Records the identity provider that authenticated the subject of the token. @@ -122,6 +116,19 @@ class IDTokenClaims(UserInfo, AADInternalClaims, BaseAuthModel): 9188040d-6c67-4c5b-b112-36a304b66dad. """ + not_before: Optional[float] = Field(time.time() - 1, alias="nbf") + """ + This claim is the time at which the token becomes valid, represented in epoch time. + This is usually the same as the time the token was issued. + Your app should use this claim to verify the validity of the token lifetime. + """ + + exp: Optional[float] = None + """ + The expiration time claim is the time at which the token becomes invalid, represented in epoch time. + Your app should use this claim to verify the validity of the token lifetime. + """ + code_hash: OptStr = Field(None, alias="c_hash") """ The code hash is included in ID tokens only when the ID token is issued with an OAuth 2.0 authorization code. @@ -142,6 +149,28 @@ class IDTokenClaims(UserInfo, AADInternalClaims, BaseAuthModel): This claim isn't returned on ID tokens from the /token endpoint. """ + nonce: OptStr = None + """ + A nonce is a strategy used to mitigate token replay attacks. + Your app can specify a nonce in an authorization request by using the nonce query parameter. + The value you provide in the request will be emitted unmodified in the nonce claim of an ID token only. + This allows your app to verify the value against the value it specified on the request, + which associates the app's session with a given ID token. + Your app should perform this validation during the ID token validation process. + """ + + object_id: OptStr = Field(None, alias="oid") + """ + The immutable identifier for an object, in this case, a user account. + This ID uniquely identifies the user across applications - + two different applications signing in the same user receives the same value in the oid claim. + Microsoft Graph returns this ID as the id property for a user account. + Because the oid allows multiple apps to correlate users, + the profile scope is required to receive this claim. If a single user exists in multiple tenants, + the user contains a different object ID in each tenant - they're considered different accounts, + even though the user logs into each account with the same credentials. The oid claim is a GUID and can't be reused. + """ + subject: OptStr = Field(None, alias="sub") """ This is the principal about which the token asserts information, such as the user of an app. @@ -159,27 +188,12 @@ class IDTokenClaims(UserInfo, AADInternalClaims, BaseAuthModel): the value is 9188040d-6c67-4c5b-b112-36a304b66dad. """ - audience: Union[OptStr, list[str]] = Field(None, alias="aud") - """ - An audience claim identifies the intended recipient of the token. - For Azure AD B2C, the audience is your app's Application ID, as assigned to your app in the app registration portal. - Your app should validate this value and reject the token if it does not match. - """ - - nonce: OptStr = None + ver: OptStr = None """ - A nonce is a strategy used to mitigate token replay attacks. - Your app can specify a nonce in an authorization request by using the nonce query parameter. - The value you provide in the request will be emitted unmodified in the nonce claim of an ID token only. - This allows your app to verify the value against the value it specified on the request, - which associates the app's session with a given ID token. - Your app should perform this validation during the ID token validation process. + Indicates the version of the token. """ - issue_time: Optional[float] = Field(None, alias="iat") - """ - The time at which the token was issued, represented in epoch time. - """ + #### Review the below claims if still needed auth_time: Optional[float] = None """ @@ -191,18 +205,14 @@ class IDTokenClaims(UserInfo, AADInternalClaims, BaseAuthModel): This is the name of the policy that was used to acquire the token. """ + ### Private attributes + _id_token: Optional[str] = PrivateAttr(None) """ The raw id_token that was used to create this object - private attribute for internal use only Will be set only via the `decode_id_token` method """ - _decoded_token: OptStrsDict = PrivateAttr(None) - """ - The decoded token that was used to create this object - private attribute for internal use only - Will be set only via the `decode_id_token` method - """ - @staticmethod def decode_id_token(id_token: str) -> Optional["IDTokenClaims"]: decoded: OptStrsDict = json.loads(oidc.decode_part(id_token.split(".")[1])) diff --git a/fastapi_msal/models/user_info.py b/fastapi_msal/models/user_info.py index df455c2..cf97926 100644 --- a/fastapi_msal/models/user_info.py +++ b/fastapi_msal/models/user_info.py @@ -1,24 +1,48 @@ from typing import Optional, Union -from pydantic import BaseModel, Field +from pydantic import Field from fastapi_msal.core import OptStr, OptStrList, StrList +from .base_auth_model import BaseAuthModel -class UserInfo(BaseModel): - first_name: OptStr = Field(None, alias="given_name") + +class UserInfo(BaseAuthModel): + preferred_username: OptStr = None """ - The user's given name (also known as first name). + The primary username that represents the user. + It could be an email address, phone number, or a generic username without a specified format. + Its value is mutable and might change over time. + Since it is mutable, this value must not be used to make authorization decisions. + It can be used for username hints, however, and in human-readable UI as a username. + The profile scope is required in order to receive this claim. Present only in v2.0 tokens. """ - last_name: OptStr = Field(None, alias="family_name") + email: OptStr = None """ - The user's surname (also known as last name). + Present by default for guest accounts that have an email address. + Your app can request the email claim for managed users (from the same tenant) using the email optional claim. + This value isn't guaranteed to be correct and is mutable over time. + Never use it for authorization or to save data for a user. + On the v2.0 endpoint, your app can also request the email OpenID Connect scope - + you don't need to request both the optional claim and the scope to get the claim. """ display_name: OptStr = Field(None, alias="name") """ - The user's full name in displayable form including all name parts, possibly including titles and suffixes. + The name claim provides a human-readable value that identifies the subject of the token. + The value isn't guaranteed to be unique, it can be changed, and should be used only for display purposes. + The profile scope is required to receive this claim. + """ + + first_name: OptStr = Field(None, alias="given_name") + """ + The user's given name (also known as first name). + """ + + last_name: OptStr = Field(None, alias="family_name") + """ + The user's surname (also known as last name). """ city: OptStr = None @@ -58,16 +82,6 @@ class UserInfo(BaseModel): The Microsoft Graph will return this ID as the id property for a given user account. """ - preferred_username: OptStr = None - """ - The primary username that represents the user. - It could be an email address, phone number, or a generic username without a specified format. - Its value is mutable and might change over time. - Since it is mutable, this value must not be used to make authorization decisions. - It can be used for username hints, however, and in human-readable UI as a username. - The profile scope is required in order to receive this claim. Present only in v2.0 tokens. - """ - unique_name: OptStr = None """ Only present in v1.0 tokens. Provides a human readable value that identifies the subject of the token.