asp.net core identity extract and save external login tokens and add claims to local identity asp.net core identity extract and save external login tokens and add claims to local identity asp.net asp.net

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.