2013-11-03 33 views
2

正如我found out here,我不能叫如何將信息從OnAuthenticated事件傳遞給控制器​​和SignIn?

HttpContext.GetOwinContext().Authentication.SignIn(...) 
在FacebookAuthenticationProvider OnAuthenticated事件

。這似乎是一個不同的背景。

我的用戶將來自Facebook,這意味着我將需要檢索如idemail數據......這些信息在OnAuthenticated事件訪問,我需要這些信息來登錄。

我需要訪問我的控制器上此信息...

我在事件試過這樣:

context.OwinContext.Set("FacebookUser", rawUserObjectFromFacebookAsJson); 

但是,如果我嘗試檢索此控制器上,它爲空。

var fbuser = HttpContext.GetOwinContext() 
       .Get<Newtonsoft.Json.Linq.JObject>("FacebookUser"); 

所以我的問題是,我如何將這些數據傳遞給控制器​​,以便我可以登錄?

回答

11

我找到了一種方法來做到這一點by looking at this answer並搞清楚我可以做什麼。

使用Claims我可以添加從Facebook檢索到的所有值並將其放入身份聲明中。

OnAuthenticated = (context) => 
{ 
    const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string"; 

    var rawUserObjectFromFacebookAsJson = context.User; 

    context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook")); 
    foreach (var x in context.User) 
    { 
     var claimType = string.Format("urn:facebook:{0}", x.Key); 
     string claimValue = x.Value.ToString(); 
     if (!context.Identity.HasClaim(claimType, claimValue)) 
      context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, XmlSchemaString, "Facebook")); 

    } 

    return Task.FromResult(0); 
} 

然後我控制器上我可以利用這個

ClaimsIdentity identity = await HttpContext.GetOwinContext().Authentication 
    .GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie); 

拿到身份之後我會對我的行爲

[AllowAnonymous] 
public async Task<ActionResult> ExternalLoginCallback(string returnUrl) 
{ 
    ClaimsIdentity identity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie); 

    var user = new IdentityUser() 
    { 
     Id = identity.GetUserId(), 
     UserName = identity.Name, 
    }; 

    await LoginAsync(user, identity); 

    if (!identity.IsAuthenticated) 
    { 
     return RedirectToAction("Login"); 
    } 

    return RedirectToAction("Index", "Home"); 
} 

而且我LoginAsync方法

private async Task LoginAsync(IdentityUser user, ClaimsIdentity identity) 
{ 
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie); 

    // I can't just use the identity I got on Facebook 
    // I need to create this one, or else it will not signin properly 
    // The authentication type has to be ApplicationCookie and the property 
    // is readonly, so... 
    var userIdentity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie); 

    // now we have to transfer the claims, adding a check to avoid duplicates 
    foreach (var claim in identity.Claims) 
    { 
     if (!userIdentity.HasClaim(c => c.Type == claim.Type)) 
      userIdentity.AddClaim(claim); 
    } 

    // then it will signin successfully 
    AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true }, userIdentity); 
} 

然後我可以訪問

HttpContext.GetOwinContext().Authentication.User.Claims 

在任何時間和檢索我需要的東西。

+0

我還沒有測試過這個,但是爲了徹底而+1。它看起來肯定會起作用,但我真的很想爲此找到「最佳實踐」。 。 。任何人都知道可能在哪裏? – Lopsided

相關問題