140 lines
8.6 KiB
Markdown
140 lines
8.6 KiB
Markdown
|
---
|
||
|
title: Persist additional claims and tokens from external providers in ASP.NET Core
|
||
|
author: guardrex
|
||
|
description: Learn how to establish additional claims and tokens from external providers.
|
||
|
monikerRange: '>= aspnetcore-2.0'
|
||
|
ms.author: riande
|
||
|
ms.custom: mvc
|
||
|
ms.date: 08/28/2018
|
||
|
uid: security/authentication/social/additional-claims
|
||
|
---
|
||
|
# Persist additional claims and tokens from external providers in ASP.NET Core
|
||
|
|
||
|
By [Luke Latham](https://github.com/guardrex)
|
||
|
|
||
|
An ASP.NET Core app can establish additional claims and tokens from external authentication providers, such as Facebook, Google, Microsoft, and Twitter. Each provider reveals different information about users on its platform, but the pattern for receiving and transforming user data into additional claims is the same.
|
||
|
|
||
|
[View or download sample code](https://github.com/aspnet/Docs/tree/master/aspnetcore/security/authentication/social/additional-claims/samples) ([how to download](xref:tutorials/index#how-to-download-a-sample))
|
||
|
|
||
|
## Prerequisite
|
||
|
|
||
|
Decide which external authentication providers to support in the app. For each provider, register the app and obtain a client ID and client secret. For more information, see <xref:security/authentication/social/index>. The [sample app](#sample-app-instructions) uses the [Google authentication provider](xref:security/authentication/google-logins).
|
||
|
|
||
|
## Authentication provider configuration
|
||
|
|
||
|
### Set the client ID and client secret
|
||
|
|
||
|
The OAuth authentication provider establishes a trust relationship with an app using a client ID and client secret. Client ID and client secret values are created for the app by the external authentication provider when the app is registered with the provider. Each external provider that the app uses must be configured independently with the provider's client ID and client secret. For more information, see the external authentication provider topics that apply to your scenario:
|
||
|
|
||
|
* [Facebook authentication](xref:security/authentication/facebook-logins)
|
||
|
* [Google authentication](xref:security/authentication/google-logins)
|
||
|
* [Microsoft authentication](xref:security/authentication/microsoft-logins)
|
||
|
* [Twitter authentication](xref:security/authentication/twitter-logins)
|
||
|
* [Other authentication providers](xref:security/authentication/otherlogins)
|
||
|
* [OpenIdConnect](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2)
|
||
|
|
||
|
The sample app configures the Google authentication provider with a client ID and client secret provided by Google:
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Startup.cs?name=snippet_AddGoogle&highlight=4,6)]
|
||
|
|
||
|
### Establish the authentication scope
|
||
|
|
||
|
Specify the list of permissions to retrieve from the provider by specifying the <xref:Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions.Scope*>. Authentication scopes for common external providers appear in the following table.
|
||
|
|
||
|
| Provider | Scope |
|
||
|
| --------- | ---------------------------------------------------------------- |
|
||
|
| Facebook | `https://www.facebook.com/dialog/oauth` |
|
||
|
| Google | `https://www.googleapis.com/auth/plus.login` |
|
||
|
| Microsoft | `https://login.microsoftonline.com/common/oauth2/v2.0/authorize` |
|
||
|
| Twitter | `https://api.twitter.com/oauth/authenticate` |
|
||
|
|
||
|
The sample app adds the Google `plus.login` scope to request Google+ sign in permissions:
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Startup.cs?name=snippet_AddGoogle&highlight=7)]
|
||
|
|
||
|
### Map user data keys and create claims
|
||
|
|
||
|
In the provider's options, specify a <xref:Microsoft.AspNetCore.Authentication.ClaimActionCollectionMapExtensions.MapJsonKey*> for each key in the external provider's JSON user data for the app identity to read on sign in. For more information on claim types, see <xref:System.Security.Claims.ClaimTypes>.
|
||
|
|
||
|
The sample app creates a <xref:System.Security.Claims.ClaimTypes.Gender> claim from the `gender` key in Google user data:
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Startup.cs?name=snippet_AddGoogle&highlight=8)]
|
||
|
|
||
|
In <xref:Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal.ExternalLoginModel.OnPostConfirmationAsync*>, an <xref:Microsoft.AspNetCore.Identity.IdentityUser> (`ApplicationUser`) is signed into the app with <xref:Microsoft.AspNetCore.Identity.SignInManager`1.SignInAsync*>. During the sign in process, the <xref:Microsoft.AspNetCore.Identity.UserManager`1> can store an `ApplicationUser` claim for user data available from the <xref:Microsoft.AspNetCore.Identity.ExternalLoginInfo.Principal*>.
|
||
|
|
||
|
In the sample app, `OnPostConfirmationAsync` (*Account/ExternalLogin.cshtml.cs*) establishes a <xref:System.Security.Claims.ClaimTypes.Gender> claim for the signed in `ApplicationUser`:
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Pages/Account/ExternalLogin.cshtml.cs?name=snippet_OnPostConfirmationAsync&highlight=30-31)]
|
||
|
|
||
|
### Save the access token
|
||
|
|
||
|
<xref:Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions.SaveTokens*> defines whether access and refresh tokens should be stored in the <xref:Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties> after a successful authorization. `SaveTokens` is set to `false` by default to reduce the size of the final authentication cookie.
|
||
|
|
||
|
The sample app sets the value of `SaveTokens` to `true` in <xref:Microsoft.AspNetCore.Authentication.Google.GoogleOptions>:
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Startup.cs?name=snippet_AddGoogle&highlight=9)]
|
||
|
|
||
|
When `OnPostConfirmationAsync` executes, store the access token ([ExternalLoginInfo.AuthenticationTokens](xref:Microsoft.AspNetCore.Identity.ExternalLoginInfo.AuthenticationTokens*)) from the external provider in the `ApplicationUser`'s `AuthenticationProperties`.
|
||
|
|
||
|
The sample app saves the access token in:
|
||
|
|
||
|
* `OnPostConfirmationAsync` – Executes for new user registration.
|
||
|
* `OnGetCallbackAsync` – Executes when a previously registered user signs into the app.
|
||
|
|
||
|
*Account/ExternalLogin.cshtml.cs*:
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Pages/Account/ExternalLogin.cshtml.cs?name=snippet_OnPostConfirmationAsync&highlight=34-35)]
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Pages/Account/ExternalLogin.cshtml.cs?name=snippet_OnGetCallbackAsync&highlight=31-32)]
|
||
|
|
||
|
### How to add additional custom tokens
|
||
|
|
||
|
To demonstrate how to add a custom token, which is stored as part of `SaveTokens`, the sample app adds an <xref:Microsoft.AspNetCore.Authentication.AuthenticationToken> with the current <xref:System.DateTime> for an [AuthenticationToken.Name](xref:Microsoft.AspNetCore.Authentication.AuthenticationToken.Name*) of `TicketCreated`:
|
||
|
|
||
|
[!code-csharp[](additional-claims/samples/2.x/AdditionalClaimsSample/Startup.cs?name=snippet_AddGoogle&highlight=10-21)]
|
||
|
|
||
|
## Sample app instructions
|
||
|
|
||
|
The sample app demonstrates how to:
|
||
|
|
||
|
* Obtain the user's gender from Google and store a gender claim with the value.
|
||
|
* Store the Google access token in the user's `AuthenticationProperties`.
|
||
|
|
||
|
To use the sample app:
|
||
|
|
||
|
1. Register the app and obtain a valid client ID and client secret for Google authentication. For more information, see <xref:security/authentication/google-logins>.
|
||
|
1. Provide the client ID and client secret to the app in the <xref:Microsoft.AspNetCore.Authentication.Google.GoogleOptions> of `Startup.ConfigureServices`.
|
||
|
1. Run the app and request the My Claims page. When the user isn't signed in, the app redirects to Google. Sign in with Google. Google redirects the user back to the app (`/Home/MyClaims`). The user is authenticated, and the My Claims page is loaded. The gender claim is present under **User Claims** with the value obtained from Google. The access token appears in the **Authentication Properties**.
|
||
|
|
||
|
```
|
||
|
User Claims
|
||
|
|
||
|
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
|
||
|
b36a7b09-9135-4810-b7a5-78697ff23e99
|
||
|
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
|
||
|
username@gmail.com
|
||
|
AspNet.Identity.SecurityStamp
|
||
|
29G2TB881ATCUQFJSRFG1S0QJ0OOAWVT
|
||
|
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender
|
||
|
female
|
||
|
http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod
|
||
|
Google
|
||
|
|
||
|
Authentication Properties
|
||
|
|
||
|
.Token.access_token
|
||
|
bv42.Dgw...GQMv9ArLPs
|
||
|
.Token.token_type
|
||
|
Bearer
|
||
|
.Token.expires_at
|
||
|
2018-08-27T19:08:00.0000000+00:00
|
||
|
.Token.TicketCreated
|
||
|
8/27/2018 6:08:00 PM
|
||
|
.TokenNames
|
||
|
access_token;token_type;expires_at;TicketCreated
|
||
|
.issued
|
||
|
Mon, 27 Aug 2018 18:08:05 GMT
|
||
|
.expires
|
||
|
Mon, 10 Sep 2018 18:08:05 GMT
|
||
|
```
|