使用.NET Core的Firebase身份验证(JWT)

Isr*_*uez 15 c# authentication asp.net-web-api firebase-authentication asp.net-core

我正在开发一个处理Firebase身份验证的简单API - 稍后将用于Android客户端.

所以在Firebase控制台中我启用了Facebook和Google登录方法,并创建了一个示例html页面,我可以使用它来测试登录方法 - 下一个函数由按钮调用:

function loginFacebook() {
        var provider = new firebase.auth.FacebookAuthProvider();
        var token = "";
        firebase.auth().signInWithPopup(provider).then(function (result) {
            var token = result.credential.accessToken;
            var user = result.user;
            alert("login OK");
            user.getToken().then(function (t) {
                token = t;
                loginAPI();
            });
        }).catch(function (error) {
            var errorCode = error.code;
            var errorMessage = error.message;
            alert(errorCode + " - " + errorMessage);
        });
    }
Run Code Online (Sandbox Code Playgroud)

接下来我使用令牌并通过jQuery中的简单ajax调用将其发送到我的API:

function loginAPI()
{
    $.ajax({
        url: "http://localhost:58041/v1/Users/",
        dataType: 'json',
        type: 'GET',
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Accept", "application/json");
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },
        error: function (ex) {
            console.log(ex.status + " - " + ex.statusText);
        },
        success: function (data) {
            console.log(data);
            return data;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

下一站:API后端 - 用.NET Core编写.

在Startup下我配置了JwtBearer Auth(包Microsoft.AspNetCore.Authentication.JwtBearer):

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    IncludeErrorDetails = true,
    Authority = "https://securetoken.google.com/PROJECT-ID",
    TokenValidationParameters = new TokenValidationParameters
    {  
        ValidateIssuer = true,
        ValidIssuer = "https://securetoken.google.com/PROJECT-ID",
        ValidateAudience = true,
        ValidAudience = "PROJECT-ID",
        ValidateLifetime = true,
    },
});
Run Code Online (Sandbox Code Playgroud)

这是控制器代码 - 具有以下[Authorize]属性:

[Authorize]
[Route("v1/[controller]")]
public class UsersController : Controller
{
    private readonly ILogger _logger;
    private readonly UserService _userService;

    public UsersController(ILogger<UsersController> logger, UserService userService)
    {
        _logger = logger;
        _userService = userService;
    }

    [HttpGet]
    public async Task<IList<User>> Get()
    {
        return await _userService.GetAll();
    }
}
Run Code Online (Sandbox Code Playgroud)

该API响应是200 OK(HttpContext.User.Identity.IsAuthenticatedtrue控制器内),但我认为它不应该.我的问题是我不完全确定这是安全的.

这是如何检查JWT令牌的签名部分的?我看到很多代码样本提到x509或RS256算法,它们在哪里适合?不应该检查对某种证书或私钥与IssuerSigningKeyTokenDecryptionKeyTokenValidationParameters类?我错过了什么?

有关该问题的相关知识来源:

Mar*_*cze 19

Firebase使用RSA256 非对称密钥密码系统,这意味着它具有公钥和私钥.使用私钥对令牌进行签名,同时使用公钥验证令牌.

下图说明了令牌签名的发生方式.

在此输入图像描述

在登录和访问安全端点期间,涉及以下步骤.

  1. 当我们的应用程序启动(再后来还定期)的JwtBearerMiddleware调用https://securetoken.google.com/my-firebase-project/.well-known/openid-configuration,它可以访问谷歌当前的公共密钥.重要的是,当我们使用公钥非对称密码系统时,公钥不会被保密,但它的发布很明显.
  2. 客户通过Firebase使用其凭据登录(这些是客户端自己的凭据,它们与用于签署令牌的密钥无关).
  3. 如果登录成功,则Firebase会为客户端构建JWT令牌.此令牌的一个关键部分是使用密钥对的私钥对其进行签名.与公钥相反,私钥永远不会公开暴露,它在Google的基础架构中保密.
  4. 客户端接收JWT令牌.
  5. 客户端在我们的Api上调用安全端点,并将令牌放入Authorization标头中.此时JwtBearerMiddleware,管道中的内容会检查此令牌,并验证它是否有效(如果它是使用Google的私钥签名的话).这里要认识到的重要一点是,为了进行验证,我们的Api 不需要访问私钥.这样做只需要公钥.验证后,中间件填充HttpContext.User,并HttpContext.User.Identity.IsAuthenticated相应地.

您可以在RSA维基百科页面上找到关于此概念的更简单的描述,并在我的博客文章中找到有关Firebase + ASP.NET的更多信息.


Rap*_*aël 6

对于后端,有一个Nuget软件包可以为您完成窍门:

安装包AspNetCore.Firebase.Authentication

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  ILoggerFactory loggerFactory)
{      
app.UseFirebaseAuthentication("https://securetoken.google.com/MYPROJECTNAME", "MYPROJECTNAME");
}
Run Code Online (Sandbox Code Playgroud)

它可以进行听众,发行人,签名和有效性验证