mirror of https://github.com/abpframework/abp.git
committed by
GitHub
1 changed files with 201 additions and 0 deletions
@ -0,0 +1,201 @@ |
|||
# How claim type works in ASP NET Core and ABP Framework |
|||
|
|||
## The Claim Type |
|||
|
|||
A web application may use one or more authentication schemes to obtain the current user's information, such as `Cookies`, `JwtBearer`, `OpenID Connect`, `Google` etc. |
|||
|
|||
After authentication, we get a set of claims that can be issued using a trusted identity provider. A claim is a type/name-value pair representing the subject. The type property provides the semantic content of the claim, that is, it states what the claim is about. |
|||
|
|||
The [`ICurrentUser`](https://docs.abp.io/en/abp/latest/CurrentUser) service of the ABP Framework provides a convenient way to access the current user's information from the claims. |
|||
|
|||
The claim type is the key to getting the correct value of the current user, and we have a static `AbpClaimTypes` class that defines the names of the standard claims in the ABP Framework: |
|||
|
|||
```cs |
|||
public static class AbpClaimTypes |
|||
{ |
|||
public static string UserId { get; set; } = ClaimTypes.NameIdentifier; |
|||
public static string UserName { get; set; } = ClaimTypes.Name; |
|||
public static string Role { get; set; } = ClaimTypes.Role; |
|||
public static string Email { get; set; } = ClaimTypes.Email; |
|||
//... |
|||
} |
|||
``` |
|||
|
|||
As you can see, the default claim type of `AbpClaimTypes` comes from the [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes) class, which is the recommended practice in NET. |
|||
|
|||
## Claim type in different authentication schemes |
|||
|
|||
We usually see two types of claim types in our daily development. One of them is the [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes) and the other one is the `OpenId Connect` [standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims). |
|||
|
|||
### ASP NET Core Identity |
|||
|
|||
There is a [`ClaimsIdentityOptions`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.claimsidentityoptions) property in the `IdentityOptions`, which can be used to configure the claim type: |
|||
|
|||
| Property | Description | |
|||
|----------------------|---------------------------------------------------------------------------------------------------------------| |
|||
| EmailClaimType | Gets or sets the ClaimType used for the user email claim. Defaults to Email. | |
|||
| RoleClaimType | Gets or sets the ClaimType used for a Role claim. Defaults to Role. | |
|||
| SecurityStampClaimType | Gets or sets the ClaimType used for the security stamp claim. Defaults to "AspNet.Identity.SecurityStamp". | |
|||
| UserIdClaimType | Gets or sets the ClaimType used for the user identifier claim. Defaults to NameIdentifier. | |
|||
| UserNameClaimType | Gets or sets the ClaimType used for the user name claim. Defaults to Name. | |
|||
|
|||
* The Identity creates a `ClaimsIdentity` object with the claim type that you have configured in the `ClaimsIdentityOptions` class. |
|||
* The ABP Framework configures it based on `AbpClaimTypes,` so usually you don't need to worry about it. |
|||
|
|||
### JwtBearer/OpenID Connect Client |
|||
|
|||
The `JwtBearer/OpenID Connect` gets claims from `id_token` or fetches user information from the `AuthServer`, and then maps/adds it to the current `ClaimsIdentity`. |
|||
|
|||
To map the [standard claim](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) type to the [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes) via [azure-activedirectory-identitymodel-extensions-for-dotnet](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) library by default, which is maintained by the Microsoft team: |
|||
|
|||
```cs |
|||
Dictionary<string, string> ClaimTypeMapping = new Dictionary<string, string> |
|||
{ |
|||
{ "actort", ClaimTypes.Actor }, |
|||
{ "birthdate", ClaimTypes.DateOfBirth }, |
|||
{ "email", ClaimTypes.Email }, |
|||
{ "family_name", ClaimTypes.Surname }, |
|||
{ "gender", ClaimTypes.Gender }, |
|||
{ "given_name", ClaimTypes.GivenName }, |
|||
{ "nameid", ClaimTypes.NameIdentifier }, |
|||
{ "sub", ClaimTypes.NameIdentifier }, |
|||
{ "website", ClaimTypes.Webpage }, |
|||
{ "unique_name", ClaimTypes.Name }, |
|||
{ "oid", "http://schemas.microsoft.com/identity/claims/objectidentifier" }, |
|||
{ "scp", "http://schemas.microsoft.com/identity/claims/scope" }, |
|||
{ "tid", "http://schemas.microsoft.com/identity/claims/tenantid" }, |
|||
{ "acr", "http://schemas.microsoft.com/claims/authnclassreference" }, |
|||
{ "adfs1email", "http://schemas.xmlsoap.org/claims/EmailAddress" }, |
|||
{ "adfs1upn", "http://schemas.xmlsoap.org/claims/UPN" }, |
|||
{ "amr", "http://schemas.microsoft.com/claims/authnmethodsreferences" }, |
|||
{ "authmethod", ClaimTypes.AuthenticationMethod }, |
|||
{ "certapppolicy", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/applicationpolicy" }, |
|||
{ "certauthoritykeyidentifier", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/authoritykeyidentifier" }, |
|||
{ "certbasicconstraints", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/basicconstraints" }, |
|||
{ "certeku", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/eku" }, |
|||
{ "certissuer", "http://schemas.microsoft.com/2012/12/certificatecontext/field/issuer" }, |
|||
{ "certissuername", "http://schemas.microsoft.com/2012/12/certificatecontext/field/issuername" }, |
|||
{ "certkeyusage", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/keyusage" }, |
|||
{ "certnotafter", "http://schemas.microsoft.com/2012/12/certificatecontext/field/notafter" }, |
|||
{ "certnotbefore", "http://schemas.microsoft.com/2012/12/certificatecontext/field/notbefore" }, |
|||
{ "certpolicy", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatepolicy" }, |
|||
{ "certpublickey", ClaimTypes.Rsa }, |
|||
{ "certrawdata", "http://schemas.microsoft.com/2012/12/certificatecontext/field/rawdata" }, |
|||
{ "certserialnumber", ClaimTypes.SerialNumber }, |
|||
{ "certsignaturealgorithm", "http://schemas.microsoft.com/2012/12/certificatecontext/field/signaturealgorithm" }, |
|||
{ "certsubject", "http://schemas.microsoft.com/2012/12/certificatecontext/field/subject" }, |
|||
{ "certsubjectaltname", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/san" }, |
|||
{ "certsubjectkeyidentifier", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/subjectkeyidentifier" }, |
|||
{ "certsubjectname", "http://schemas.microsoft.com/2012/12/certificatecontext/field/subjectname" }, |
|||
{ "certtemplateinformation", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatetemplateinformation" }, |
|||
{ "certtemplatename", "http://schemas.microsoft.com/2012/12/certificatecontext/extension/certificatetemplatename" }, |
|||
{ "certthumbprint", ClaimTypes.Thumbprint }, |
|||
{ "certx509version", "http://schemas.microsoft.com/2012/12/certificatecontext/field/x509version" }, |
|||
{ "clientapplication", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application" }, |
|||
{ "clientip", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-ip" }, |
|||
{ "clientuseragent", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent" }, |
|||
{ "commonname", "http://schemas.xmlsoap.org/claims/CommonName" }, |
|||
{ "denyonlyprimarygroupsid", ClaimTypes.DenyOnlyPrimaryGroupSid }, |
|||
{ "denyonlyprimarysid", ClaimTypes.DenyOnlyPrimarySid }, |
|||
{ "denyonlysid", ClaimTypes.DenyOnlySid }, |
|||
{ "devicedispname", "http://schemas.microsoft.com/2012/01/devicecontext/claims/displayname" }, |
|||
{ "deviceid", "http://schemas.microsoft.com/2012/01/devicecontext/claims/identifier" }, |
|||
{ "deviceismanaged", "http://schemas.microsoft.com/2012/01/devicecontext/claims/ismanaged" }, |
|||
{ "deviceostype", "http://schemas.microsoft.com/2012/01/devicecontext/claims/ostype" }, |
|||
{ "deviceosver", "http://schemas.microsoft.com/2012/01/devicecontext/claims/osversion" }, |
|||
{ "deviceowner", "http://schemas.microsoft.com/2012/01/devicecontext/claims/userowner" }, |
|||
{ "deviceregid", "http://schemas.microsoft.com/2012/01/devicecontext/claims/registrationid" }, |
|||
{ "endpointpath", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-endpoint-absolute-path" }, |
|||
{ "forwardedclientip", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip" }, |
|||
{ "group", "http://schemas.xmlsoap.org/claims/Group" }, |
|||
{ "groupsid", ClaimTypes.GroupSid }, |
|||
{ "idp", "http://schemas.microsoft.com/identity/claims/identityprovider" }, |
|||
{ "insidecorporatenetwork", "http://schemas.microsoft.com/ws/2012/01/insidecorporatenetwork" }, |
|||
{ "isregistereduser", "http://schemas.microsoft.com/2012/01/devicecontext/claims/isregistereduser" }, |
|||
{ "ppid", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier" }, |
|||
{ "primarygroupsid", ClaimTypes.PrimaryGroupSid }, |
|||
{ "primarysid", ClaimTypes.PrimarySid }, |
|||
{ "proxy", "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy" }, |
|||
{ "pwdchgurl", "http://schemas.microsoft.com/ws/2012/01/passwordchangeurl" }, |
|||
{ "pwdexpdays", "http://schemas.microsoft.com/ws/2012/01/passwordexpirationdays" }, |
|||
{ "pwdexptime", "http://schemas.microsoft.com/ws/2012/01/passwordexpirationtime" }, |
|||
{ "relyingpartytrustid", "http://schemas.microsoft.com/2012/01/requestcontext/claims/relyingpartytrustid" }, |
|||
{ "role", ClaimTypes.Role }, |
|||
{ "roles", ClaimTypes.Role }, |
|||
{ "upn", ClaimTypes.Upn }, |
|||
{ "winaccountname", ClaimTypes.WindowsAccountName }, |
|||
}; |
|||
``` |
|||
|
|||
#### Disable JwtBearer/OpenID Connect Client Claim Type Mapping |
|||
|
|||
To turn off the claim type mapping, you can set the `MapInboundClaims` property of `JwtBearerOptions` or `OpenIdConnectOptions` to `false`. Then, you can get the original claim types from the token(`access_token` or `id_token`): |
|||
|
|||
JWT Example: |
|||
|
|||
```json |
|||
{ |
|||
"iss": "https://localhost:44305/", |
|||
"exp": 1714466127, |
|||
"iat": 1714466127, |
|||
"aud": "MyProjectName", |
|||
"scope": "MyProjectName offline_access", |
|||
"sub": "ed7f5cfd-7311-0402-245c-3a123ff787f9", |
|||
"unique_name": "admin", |
|||
"preferred_username": "admin", |
|||
"given_name": "admin", |
|||
"role": "admin", |
|||
"email": "admin@abp.io", |
|||
"email_verified": "False", |
|||
"phone_number_verified": "False", |
|||
} |
|||
``` |
|||
|
|||
### OAuth2(Google, Facebook, Twitter, Microsoft) Extenal Login Client |
|||
|
|||
The `OAuth2 handler` fetchs a JSON containing user information from the `OAuth2` server. The third-party provider issues the claim type based on their standard server and then maps/adds it to the current `ClaimsIdentity`. The ASP NET Core provides some built-in claim-type mappings for different providers as can be seen below examples: |
|||
|
|||
**Example**: The `ClaimActions` property of the `GoogleOptions` maps the Google's claim types to [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes): |
|||
|
|||
```cs |
|||
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id"); // v2 |
|||
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); // v3 |
|||
ClaimActions.MapJsonKey(ClaimTypes.Name, "name"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name"); |
|||
ClaimActions.MapJsonKey("urn:google:profile", "link"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.Email, "email"); |
|||
``` |
|||
|
|||
**Example**: The `ClaimActions` property of the `FacebookOptions` maps the Facebook's claim types to [`System.Security.Claims.ClaimTypes`](https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimtypes): |
|||
|
|||
```cs |
|||
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id"); |
|||
ClaimActions.MapJsonSubKey("urn:facebook:age_range_min", "age_range", "min"); |
|||
ClaimActions.MapJsonSubKey("urn:facebook:age_range_max", "age_range", "max"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.DateOfBirth, "birthday"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.Email, "email"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.Name, "name"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.GivenName, "first_name"); |
|||
ClaimActions.MapJsonKey("urn:facebook:middle_name", "middle_name"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.Surname, "last_name"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender"); |
|||
ClaimActions.MapJsonKey("urn:facebook:link", "link"); |
|||
ClaimActions.MapJsonSubKey("urn:facebook:location", "location", "name"); |
|||
ClaimActions.MapJsonKey(ClaimTypes.Locality, "locale"); |
|||
ClaimActions.MapJsonKey("urn:facebook:timezone", "timezone"); |
|||
``` |
|||
|
|||
### OpenIddict AuthServer |
|||
|
|||
The `OpenIddict` uses the [standard claims](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) as the claim type of the `id_token` or `access_token` and `UserInfo` endpoint response, etc. |
|||
|
|||
* For JWT token, it also uses the [azure-activedirectory-identitymodel-extensions-for-dotnet](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) to get the claims from the `id_token` or `access_token`. |
|||
* For reference token, it gets the claims from the `database`. |
|||
|
|||
## Summary |
|||
|
|||
Once you find the claims you received do not meet your expectations, follow the instructions above to troubleshoot the problem. |
|||
|
|||
This article can help you understand the claim type in the ABP Framework and ASP NET Core. |
|||
|
|||
Loading…
Reference in new issue