我已经做了很多搜索,但却找不到理想的解决方案.我知道有一个所谓的解决方案(
WebApi ASP.NET Identity Facebook login)但是,解决方案的一些元素是(在我看来)严重hacky(例如用普通帐户注册用户然后添加外部登录,而不是在外部注册它们登录).
我希望能够在已经在iOS移动应用程序上使用Facebook SDK登录后注册和验证ASP.NET Web API 2应用程序,即我已经使用他们的SDK对Facebook进行了身份验证,现在想要无缝地使用ASP.NET Web API注册/验证.我不想使用我必须使用Web调用(/ api / Account / ExternalLogin)的过程,因为这对本机移动应用程序来说不是一个很好的用户体验.
我试过了解OWIN,但.NET框架很复杂,我在如何解决这个问题上苦苦挣扎.
解决方法
我今天需要为我的Ionic app做这个. Web API帐户控制器对如何做事有自己的看法,最好的理解方法是阅读Dominick Baier撰写的这篇非常棒的3部分博客文章.
https://leastprivilege.com/2013/11/26/dissecting-the-web-api-individual-accounts-templatepart-3-external-accounts/.
我解决这个问题的方法是忘记开箱即用的流程,而是使用本地Facebook登录中的accessToken,然后调用以下服务器代码1)调用Facebook API来验证访问令牌,2)从Facebook调用,获取电子邮件和ID,3)获取用户或创建它(和登录),这已经是其他地方的帐户控制器中的代码,4)为后续Web API创建本地权限JWT调用.
public class ProviderAndAccessToken { public string Token { get; set; } public string Provider { get; set; } } [AllowAnonymous] [HttpPost] [Route("JwtFromProviderAccessToken")] public async Task<IHttpActionResult> JwtFromProviderAccessToken(ProviderAndAccessToken model) { string id = null; string userName = null; if (model.Provider == "Facebook") { var fbclient = new Facebook.FacebookClient(model.Token); dynamic fb = fbclient.Get("/me?locale=en_US&fields=name,email"); id = fb.id; userName = fb.email; } //TODO: Google,LinkedIn ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(model.Provider,id)); bool hasRegistered = user != null; string accessToken = null; var identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType); var props = new AuthenticationProperties() { IssuedUtc = DateTime.UtcNow,ExpiresUtc = DateTime.UtcNow.Add(Startup.OAuthOptions.AccessTokenExpireTimeSpan),}; if (hasRegistered) { ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,OAuthDefaults.AuthenticationType); ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,CookieAuthenticationDefaults.AuthenticationType); AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName); Authentication.SignIn(properties,oAuthIdentity,cookieIdentity); identity.AddClaim(new Claim(ClaimTypes.Name,user.UserName)); identity.AddClaim(new Claim("role","user")); } else { user = new ApplicationUser() { UserName = userName,Email = userName }; IdentityResult result = await UserManager.CreateAsync(user); if (!result.Succeeded) { return GetErrorResult(result); } result = await UserManager.AddLoginAsync(user.Id,new UserLoginInfo(model.Provider,id)); if (!result.Succeeded) { return GetErrorResult(result); } identity.AddClaim(new Claim(ClaimTypes.Name,userName)); } identity.AddClaim(new Claim("role","user")); var ticket = new AuthenticationTicket(identity,props); accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket); return Ok(accessToken); }
我在Ionic中使用的代码基本上是为了从Facebook获取访问令牌,然后调用Web API以获取本地权限JWT用作Bearer令牌.
Facebook.login(['public_profile','email']).then((result) => { return this.http.post("<URL>/api/Account/JwtFromProviderAccessToken",{ provider: "Facebook",token: result.authResponse.accessToken }) .map((res: Response) => res.json()) .catch(this.handleError) .subscribe((res: Response) => { // use the result as the Bearer token }); })...