Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Identity: Update external claims after authorization

I am using ASP.NET Identity with several external login providers and I need to handle the following scenario:

1) A user logs in using an external service (let's say it is Facebook), application grabs some info from Facebook (first and last name, email, date of birth, etc...) Claims containing this info are added to the identity.

2) I need to store this info in the application Db, for the following scenarios:

  • Admin browses the list of registered users

  • Email subscription service will use first and last names

  • ...

The question is what about if user will update his/her Facebook profile (e.g., change email address) - in this case I need to update information in my Db too (I store external claims in AspNetUserClaims table). Actually I need to update it every time an external user is authenticated.

Here's the code of how it is saved for the first time:

Extended Claim class:

public class ApplicationUserClaim : IdentityUserClaim<Guid>
{
    public string Issuer { get; set; }
    public string ClaimValueType { get; set; }
}

Startup:

var facebookOptions = new FacebookAuthenticationOptions {
    AppId = "...",
    AppSecret = "...",
    Provider = new FacebookAuthenticationProvider {
        OnAuthenticated = (context) => {
            context.Identity.AddClaims(new[] {
                new Claim("LastName", context.User["last_name"].ToString(), ClaimValueTypes.String, "Facebook"),
                new Claim("FirstName", context.User["first_name"].ToString(), ClaimValueTypes.String, "Facebook"),
                //...Other claims
            });
        }
    }
};

facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("user_birthday");

app.UseFacebookAuthentication(facebookOptions);

AuthController

External Login callback:

public ActionResult ExternalLogin(string returnUrl)
{
    var loginInfo = authenticationManager.GetExternalLoginInfo();

    //No user found - this is the first login with an external service
    //Asking to confirm an external account
    if(signInStatus == SignInStatus.Failure)
        return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { ... });    
}

Creating an user after external login confirmation (omitting other code):

public ActionResult ExternalLoginConfirmation(ExternalLoginConfirmationViewModel loginConfirmationViewModel)
{
    var loginInfo = authenticationManager.GetExternalLoginInfo();

    var user = new ApplicationUser();

    user.Logins.Add(new RegisteredUserLogin {
        LoginProvider = loginInfo.Login.LoginProvider,
        ProviderKey = loginInfo.Login.ProviderKey
    });

    //Converting Claims added in OnAuthenticated callback to ApplicationClaim objects to store them in Db
    foreach(var userInfoClaim in loginInfo.GetUserInfoClaims())                        
        user.Claims.Add(ClaimsHelper.ToUserClaimObject(userInfoClaim));

    userManager.Create(user);
}

This works fine, but I'm stuck with updating incoming claim values after a Facebook user comes back. What is the true way to handle such a situation? Thx.

like image 944
nativehr Avatar asked Feb 25 '15 13:02

nativehr


People also ask

What does HttpContext SignInAsync do?

SignInAsync(HttpContext, String, ClaimsPrincipal, AuthenticationProperties) Sign in a principal for the specified scheme.

What is Aspnetuserclaims?

A claims-based identity is the set of claims. A claim is a statement that an entity (a user or another application) makes about itself, it's just a claim. For example a claim list can have the user's name, user's e-mail, user's age, user's authorization for an action.


1 Answers

This is a bit costy but the easiest answer:

You can just check the same information whenever the user logs in and update them if changed. Since you have no direct connection to Facebook, you can never know when the users change their information.

This should result be an OK approach unless you have thousands of logins to your system in a minute.

like image 144
Mithgroth Avatar answered Sep 19 '22 06:09

Mithgroth