Identidade do ASP.NET: atualizar declarações externas após autorização

Estou usando a identidade do ASP.NET com vários provedores de logon externos e preciso lidar com o seguinte cenário:

1) Um usuário faz login usando um serviço externo (digamos que seja o Facebook), o aplicativo pega algumas informações do Facebook (nome e sobrenome, email, data de nascimento, etc ...) As reivindicações que contêm essas informações são adicionadas à identidade .

2) Preciso armazenar essas informações no aplicativo Db, para os seguintes cenários:

Admin navega na lista de usuários registrados

O serviço de assinatura de email usará o nome e o sobrenome

...

A questão é se o usuário atualizará seu perfil no Facebook (por exemplo, alterar o endereço de e-mail) - nesse caso, também preciso atualizar as informações no meu banco de dados (guardo reivindicações externas na tabela AspNetUserClaims). Na verdade, preciso atualizá-lo sempre que um usuário externo for autenticado.

Aqui está o código de como ele é salvo pela primeira vez:

Classe de reivindicação estendida:

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

Comece:

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

Retorno de chamada de logon externo:

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 { ... });    
}

Criando um usuário após a confirmação de login externo (omitindo outro código):

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);
}

Isso funciona bem, mas não consigo atualizar os valores de reivindicação de entrada depois que um usuário do Facebook volta. Qual é a verdadeira maneira de lidar com essa situação? Valeu.

questionAnswers(1)

yourAnswerToTheQuestion