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.