ASP.net core web api:使用Facebook/Google OAuth访问令牌进行身份验证

22

最近几天,我一直在尝试让我的ASP.net核心Web Api项目能够使用Google和Facebook的OAuth身份验证。

目前的状态是:

  • 我有一个ASP.net核心Web Api项目,需要对用户进行身份验证
  • 我有一个Angular 2 Web应用程序,它应该使用我的Web Api(带有身份验证)
  • 我有一个Android应用程序,它应该使用我的Web Api(带有身份验证)

我的目标是:

  • 使用Google / Facebook作为OAuth提供商进行登录
  • 以后:添加自己的用户账户(可能使用IdentityServer4)
  • 无需重定向到特殊的登录网站(如IdentityServer4解决方案)。只需点击应用程序中的facebook / google按钮,允许访问即可完成!

在我的Android和Angular应用程序中,我能够从Google/Facebook检索访问令牌。现在,我想使用OAuth隐式流程,使用给定的访问令牌(将令牌放入标头作为Bearer令牌)在我的Web API上对用户进行身份验证。

这就是我的问题:是否有任何通用的方法可以轻松地实现此操作?我不想使用Facebook/Google的SDK来完成此操作。

我尝试过以下方法:

  • 使用IdentityServer4: 通过这个我可以在我的WebAPI上使用Facebook/Google登录,但需要重定向到IdentityServer4的登录页面。是否有可能仅点击应用程序中的Google/FB按钮并登录,而无需重定向到identityServer登录页面?
  • 使用google/facebook身份验证中间件 (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/): 但它们不验证我发送的令牌(尝试了无数种方法来实现正确的验证)。在Web API中使用这个是否可行?
  • 尝试使用Microsoft.AspNetCore.Authentication.JwtBearer-Middleware并自己放入必要的选项以供Google/Facebook使用,但也没有验证(同样尝试了无数次)。
在过去的几天里,我尝试了很多可能的解决方案,但现在已经完全陷入困境,不知道如何才能实现我的目标。到这个地步,我几乎阅读了每一个asp.net web api oauth教程/stackoverflow条目,但无法弄清楚如何在我的情况下使用它。大多数教程只适用于mvc网站或使用IdentityServer4并重定向到其登录页面。
有什么建议或解决方案吗?我错过了什么吗?

1
对于第三方身份验证,我认为当页面重定向回您的应用程序(用户已通过身份验证),HTTP请求应包含身份验证数据。您可以编写全局过滤器来拦截它。在此处查看一些详细信息:https://andrewlock.net/an-introduction-to-oauth-2-using-facebook-in-asp-net-core/ - wannadream
你解决了这个问题吗? - Marcus
1
我在几周前找到了一个解决方案(忘记在这里更新): 在IdentityServer4的auth端点上,可以使用特殊参数,立即重定向到所选身份提供者的网站,而无需通过identityserver的登录页面。如此处所述http://docs.identityserver.io/en/release/endpoints/authorize.html acr_values中的idp:name_of_idp参数直接重定向到身份提供者,这正是我想要的。 - Rul3r
你找到最终解决方案了吗? - Martin Bodocky
1
@nicV 感谢您推荐这篇文章,它完全符合问题所要求的,并且可以与 .net core 无缝配合使用。 - Jay Dubal
显示剩余4条评论
2个回答

18

如果我理解得正确,您已经通过应用程序从Facebook SDK获得了您的Facebook用户令牌。
像您一样,我无法找到如何使用ASP.NET Core库/包完成此操作。因此,我回到了基础知识。
我只需调用我的api的一个端点,并使用Facebook令牌检查它是否符合Facebook Graph API的要求。如果没问题,我将注册用户(如果需要),并返回我的JWT令牌,就好像用户通过传统的用户名/密码路径登录。

[HttpPost]
[AllowAnonymous]
[Route("api/authentication/FacebookLogin")]
public async Task<IActionResult> FacebookLogin([FromBody] FacebookToken facebookToken)
{
    //check token
    var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.facebook.com/v2.9/") };
    var response = await httpClient.GetAsync($"me?access_token={facebookToken.Token}&fields=id,name,email,first_name,last_name,age_range,birthday,gender,locale,picture");
    if (!response.IsSuccessStatusCode) return BadRequest();
    var result = await response.Content.ReadAsStringAsync();
    var facebookAccount = JsonConvert.DeserializeObject<FacebookAccount>(result);

    //register if required
    var facebookUser = _context.FacebookUsers.SingleOrDefault(x => x.Id == facebookAccount.Id);
    if (facebookUser == null)
    {
        var user = new ApplicationUser {UserName = facebookAccount.Name, Email = facebookAccount.Email};
        var result2 = await _userManager.CreateAsync(user);
        if (!result2.Succeeded) return BadRequest();
        facebookUser = new FacebookUser {Id = facebookAccount.Id, UserId = user.Id};
        _context.FacebookUsers.Add(facebookUser);
        _context.SaveChanges();
    }

    //send bearer token
    return Ok(GetToken(facebookUser.UserId));
}

1
你难道不应该先对比Facebook的应用程序密钥验证所得到的访问令牌与授权提供者(联合到Facebook)吗? - user1912383

-2

你需要复制Medium文章中提供的自定义代码。

在AccountController.cs中创建一个函数。

 private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()

将文章中提供的代码粘贴


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接