Firebase 身份验证 (JWT) 与 .NET Core [英] Firebase Authentication (JWT) with .NET Core

查看:26
本文介绍了Firebase 身份验证 (JWT) 与 .NET Core的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个简单的 API,用于处理 Firebase 进行的身份验证 - 稍后用于 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("登录成功");user.getToken().then(function (t) {令牌 = t;登录API();});}).catch(函数(错误){var errorCode = error.code;var errorMessage = error.message;警报(错误代码 + "- " + 错误消息);});}

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

函数 loginAPI(){$.ajax({url: "http://localhost:58041/v1/Users/",数据类型:'json',类型:'获取',beforeSend: 函数 (xhr) {xhr.setRequestHeader("Accept", "application/json");xhr.setRequestHeader("Content-Type", "application/json");xhr.setRequestHeader("Authorization", "Bearer" + token);},错误:函数(前){console.log(ex.status + " - " + ex.statusText);},成功:功能(数据){控制台日志(数据);返回数据;}});}

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

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

app.UseJwtBearerAuthentication(new JwtBearerOptions{自动身份验证 = 真,IncludeErrorDetails = true,权限 = "https://securetoken.google.com/PROJECT-ID",TokenValidationParameters = 新的 TokenValidationParameters{ValidateIssuer = 真,ValidIssuer = "https://securetoken.google.com/PROJECT-ID",ValidateAudience = 真,ValidAudience = "项目 ID",ValidateLifetime = 真,},});

这是控制器代码 - 带有 [Authorize] 属性:

[授权][路由(v1/[控制器]")]公共类 UsersController :控制器{私有只读 ILogger _logger;私有只读 UserService _userService;公共用户控制器(ILogger logger, UserService userService){_logger = 记录器;_userService = 用户服务;}[HttpGet]公共异步任务>得到(){返回等待 _userService.GetAll();}}

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

这是如何检查 JWT 令牌的签名部分的?我看到很多代码示例都提到了 x509 或 RS256 算法,它们在哪里适合?不应该使用 TokenValidationParameters 类中的 IssuerSigningKeyTokenDecryptionKey 来检查某种证书或私钥吗?我错过了什么?

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

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

    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 维基百科页面上找到对此概念的更简单的描述.a>,以及 我的博文.

    I'm developing a simple API that handles Authentication made by Firebase - to be used later with Android clients.

    So in Firebase console I enabled Facebook and Google sign-in methods and created a sample html page that I can use it to test the login method - this next function is called by a button:

    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);
            });
        }
    

    next I use the token and send it to my API with a simple ajax call from jQuery here:

    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;
            }
        });
    }
    

    Next stop: the API backend - written with .NET Core.

    Under the Startup I've configured the JwtBearer Auth (package 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,
        },
    });
    

    And here is the Controller code - with the [Authorize] attribute:

    [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();
        }
    }
    

    The API response is 200 OK (HttpContext.User.Identity.IsAuthenticated is true inside the Controller), but I think it shouldn't. My problem is that I'm not entirely sure that this is secure.

    How this is checking the signature part of the JWT token? I saw a lot of code samples mentioning x509 or RS256 algorithm, where do they fit with this? Shouldn't be checking against some kind of certificate or private key with the IssuerSigningKey or TokenDecryptionKey from the TokenValidationParameters class? What I'm missing?

    Relevant sources of knowledge about the issue:

    解决方案

    Firebase uses the RSA256 asymmetric key cryptosystem, which means it has a public and a private key. Signing a token happens with the private key, while verifying a token happens with the public key.

    The following diagram illustrates how the token signing happens.

    During signing in and accessing a secure endpoint, the following steps are involved.

    1. When our application starts up (and then later also periodically) the JwtBearerMiddleware calls https://securetoken.google.com/my-firebase-project/.well-known/openid-configuration, where it can access the current public keys of Google. It's important that when we're using a public key asymmetric cryptosystem, the public key is not kept as a secret, but it is published in plain sight.
    2. A client signs in using their credential through Firebase (these are the client's own credentials, they have nothing to do with the key used to sign the token).
    3. If the signin was successful, then Firebase constructs a JWT token for the client. A crucial part of this token is that it's signed using the private key of the key pair. In contrast to the public key, the private key is never exposed publicly, it is kept as a secret inside Google's infrastructure.
    4. The client receives the JWT token.
    5. The client calls a secure endpoint on our Api, and puts the token in the Authorization header. At this point the JwtBearerMiddleware in the pipeline checks this token, and verifies if it's valid (if it was signed with Google's private key). The important thing to realize here is that in order to do the verification, our Api does not need to have access to the private key. Only the public key is necessary to do that. After verification, the middleware populates HttpContext.User, and HttpContext.User.Identity.IsAuthenticated accordingly.

    You can find an even simpler description of this concept on the RSA Wikipedia page, and some more information about Firebase + ASP.NET in my blog post.

    这篇关于Firebase 身份验证 (JWT) 与 .NET Core的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆