0

我想簽署我的用戶使用他們在Facebook上的電子郵件地址。我已經配置了我的Facebook的身份驗證:帶有電子郵件地址的WebApi Facebook身份驗證

var facebookAuthenticationOptions = new FacebookAuthenticationOptions 
{ 
    AppId = facebookId, 
    AppSecret = facebookSecret, 
    Provider = new FacebookProvider() 
}; 
app.UseFacebookAuthentication(facebookAuthenticationOptions); 

我已經覆蓋了Facebook的供應商也返回的電子郵件地址:

public class FacebookProvider : FacebookAuthenticationProvider 
{ 
    public override Task Authenticated(FacebookAuthenticatedContext context) 
    { 
     var accessTokenClaim = new Claim("ExternalAccessToken", context.AccessToken, "urn:facebook:access_token"); 
     context.Identity.AddClaim(accessTokenClaim); 
     var extraClaims = GetAdditionalFacebookClaims(accessTokenClaim); 
     context.Identity.AddClaim(new Claim(ClaimTypes.Email, extraClaims.First(k => k.Key == "email").Value.ToString())); 
     context.Identity.AddClaim(new Claim("Provider", context.Identity.AuthenticationType)); 
     context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirstValue(ClaimTypes.Name))); 

     var userDetail = context.User; 
     var link = userDetail.Value<string>("link") ?? string.Empty; 
     context.Identity.AddClaim(new Claim("link", link)); 
     context.Identity.AddClaim(new Claim("FacebookId", userDetail.Value<string>("id"))); 
     return Task.FromResult(0); 
    } 

    private static JsonObject GetAdditionalFacebookClaims(Claim accessToken) 
    { 
     var fb = new FacebookClient(accessToken.Value); 
     return fb.Get("me", new { fields = new[] { "email" } }) as JsonObject; 
    } 

一切正常,在MVC - 在LoginOwinCallback功能,我能夠檢索從Facebook返回的用戶的電子郵件地址。我試圖在WebApi中使用令牌認證而不是外部cookie來實現同樣的功能。但是,儘管我可以看到我的提供者將電子郵件聲明添加到響應中,但當我在以下例程中調用AuthenticateAsync方法時,並未包含電子郵件聲明。

private async Task<ExternalLoginInfo> GetExternalLoginInfoAsync() 
{ 
    var result = await Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalBearer); 

    if (result == null || result.Identity == null) return null; 

    var idClaim = result.Identity.FindFirst(ClaimTypes.NameIdentifier); 
    if (idClaim != null) 
    { 
     return new ExternalLoginInfo() 
     { 
      DefaultUserName = result.Identity.Name == null ? "" : result.Identity.Name.Replace(" ", ""), 
      ExternalIdentity = result.Identity, 
      Login = new UserLoginInfo(idClaim.Issuer, idClaim.Value) 
     }; 
    } 

    return null; 
} 

任何想法我做錯了什麼?

回答

0

對於其他面臨同樣問題的人,電子郵件聲明可用 - 只是有點隱藏。

首先,正確地獲取來自Facebook用戶的電子郵件地址,認證建立在Startup.Auth.cs的ConfigureAuth方法應該是:

app.UseFacebookAuthentication(new FacebookAuthenticationOptions 
{ 
    AppId = facebookId, 
    AppSecret = facebookSecret, 
    Scope= {"email"}, 
    UserInformationEndpoint = "https://graph.facebook.com/v2.4/me?fields=email" 
}); 

在MVC AccountController類的LoginOwinCallback方法,該電子郵件地址位於由var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();返回的ExternalLoginInfo對象的Email屬性中。

要檢索WebAPI AccountController類中的電子郵件地址,您需要將User.Identity對象轉換爲ClaimsIdentity類型。

[OverrideAuthentication] 
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)] 
[AllowAnonymous] 
[Route("ExternalLogin", Name = "ExternalLogin")] 
public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null) 
{ 
    if (error != null) 
    { 
     return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error)); 
    } 

    if (!User.Identity.IsAuthenticated) 
    { 
     return new ChallengeResult(provider, this); 
    } 

    // get all of the claims 
    var claimsIdentity = User.Identity as ClaimsIdentity; // this cast exposes all of the claims returned by Facebook 

    // get the external login details 
    var externalLogin = ExternalLoginData.FromIdentity(claimsIdentity); 

    if (externalLogin == null) 
    { 
     return InternalServerError(); 
    } 

    if (externalLogin.LoginProvider != provider) 
    { 
      AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); 
     return new ChallengeResult(provider, this); 
    } 

    var user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider, 
      externalLogin.ProviderKey)); 

    var hasRegistered = user != null; 

    if (hasRegistered) 
    { 
     AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); 

     var oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager, 
      OAuthDefaults.AuthenticationType); 
     var cookieIdentity = await user.GenerateUserIdentityAsync(UserManager, 
      CookieAuthenticationDefaults.AuthenticationType); 

     var properties = ApplicationOAuthProvider.CreateProperties(user.UserName); 
     AuthenticationManager.SignIn(properties, oAuthIdentity, cookieIdentity); 
    } 
    else 
    { 
     var claims = claimsIdentity?.Claims ?? externalLogin.GetClaims(); 
     var identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType); 
     AuthenticationManager.SignIn(identity); 
    } 

    return Ok(); 
} 

這意味着,你可以使用的身份FindFirst方法找到被Facebook返回的電子郵件要求。