asp.net core identity extract and save external login tokens and add claims to local identity
When you use await _userManager.AddClaimAsync(user, new Claim("your-claim", "your-value"));
that actually updates the Identity's aspnetuserclaims table.
Whenever you sign in (by using _signInManager.PasswordSignIn or _signInManager.ExternalLoginSignInAsync) the claims from that table are read and added to the cookie that on every request becomes the Principal.
So you probably don't want to be calling the AddClaimAsync method from UserManager on every login.
Regarding external login providers, you have access to the claims when you call (in ExternalCallback and ExternalCallbackConfirmation if you are using the default templates) here:
var info = await _signInManager.GetExternalLoginInfoAsync();
The claims are in info.Principal.Claims
.
The access token is not included by default. When it is, it will be here (along with the type and expiry date):
var accessToken = info.AuthenticationTokens.Single(f => f.Name == "access_token").Value;var tokenType = info.AuthenticationTokens.Single(f => f.Name == "token_type").Value;var expiryDate = info.AuthenticationTokens.Single(f => f.Name == "expires_at").Value;
To have the access token be included in the AuthenticationTokens
collection, when you are configuring the GoogleAuthentication middleware set the SaveTokens flag to true:
app.UseGoogleAuthentication(new GoogleOptions{ ClientId = "...", ClientSecret = "...", SaveTokens = true
Now, if you want to have control over which claims go in the cookie you have to "take over" the process of creating the claims principal.
This is done for you when you use _signInManager.PasswordSignIn/ExternalLoginSignInAsync
.
So, for example, for ExternalLoginSignInAsync
replace:
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
With:
var user = await this._userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); var claimsPrincipal = await this._signInManager.CreateUserPrincipalAsync(user); ((ClaimsIdentity)claimsPrincipal.Identity).AddClaim(new Claim("accessToken", info.AuthenticationTokens.Single(t => t.Name == "access_token").Value)); await HttpContext.Authentication.SignInAsync("Identity.Application", claimsPrincipal);
"Identity.Application" is the default cookie name. You can change it in Startup's ConfigureServices
method, for example to MainCookie:
services.Configure<IdentityOptions>(options => { options.Cookies.ApplicationCookie.AuthenticationScheme = "MainCookie"; });
You still need to handle the ExternalCallbackConfirmation
action in the AccountController. It will be similar to the example above.