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

Posted

技术标签:

【中文标题】使用 .NET Core 的 Firebase 身份验证 (JWT)【英文标题】:Firebase Authentication (JWT) with .NET Core 【发布时间】:2017-07-09 06:47:33 【问题描述】:

我正在开发一个简单的 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("login OK");
            user.getToken().then(function (t) 
                token = t;
                loginAPI();
            );
        ).catch(function (error) 
            var errorCode = error.code;
            var errorMessage = error.message;
            alert(errorCode + " - " + errorMessage);
        );
    

接下来,我使用令牌并通过 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;
        
    );

下一站: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,
    ,
);

这是控制器代码 - 带有[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();
    

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

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

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

https://blog.markvincze.com/secure-an-asp-net-core-api-with-firebase/ SPA - Firebase and .Net WebApi 2 authentication https://stormpath.com/blog/token-authentication-asp-net-core https://jwt.io/ https://firebase.google.com/docs/auth/admin/verify-id-tokens

【问题讨论】:

即使不传递Authorization 标头,响应也是200 OK?那肯定是错的。在app.UseJwtBearerAuthentication() 之前或之后有app.UseMvc() 电话吗? 如果我没有传递Authorization 标头,则响应为401app.UseMvc()app.UseJwtBearerAuthentication() 之后。我只是不确定安全性。我试图破解我的应用程序但无法破解。也许我只是偏执。 嗯,但你说响应“不应该是 200”。为什么?您是否故意在标头中传递了不正确的标记?或者你为什么期望响应不是 200? 由于我没有在我的代码中的任何地方提供私钥,所以我认为这应该行不通,但是在无法破解它之后,我认为我只是偏执。 恐怕您误解了令牌签名在此流程中的工作原理。您的应用程序不应提供(或拥有)私钥(或任何类型的密钥)。我在我的博文中添加了对流程的描述:blog.markvincze.com/secure-an-asp-net-core-api-with-firebase/… 【参考方案1】:

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

下图说明了令牌签名是如何发生的。

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

    当我们的应用程序启动时(然后也定期启动)JwtBearerMiddleware 调用https://securetoken.google.com/my-firebase-project/.well-known/openid-configuration,它可以访问 Google 当前的公钥。 重要的是,当我们使用公钥非对称密码系统时,公钥不会保密,而是公开发布。 客户端通过 Firebase 使用其凭据登录(这些是客户端自己的凭据,它们与用于签署令牌的密钥无关)。 如果登录成功,Firebase 会为客户端构造一个 JWT 令牌。该令牌的一个关键部分是使用密钥对的私钥进行签名。与公钥不同的是,私钥永远不会公开,它在 Google 的基础架构中作为秘密保存。 客户端收到 JWT 令牌。 客户端调用我们 Api 上的安全端点,并将令牌放入 Authorization 标头中。 此时,管道中的JwtBearerMiddleware 会检查此令牌,并验证它是否有效(是否使用 Google 的私钥签名)。这里要意识到的重要一点是,为了进行验证,我们的 Api 不需要访问私钥。只有公钥是必要的。验证后,中间件会相应地填充HttpContext.UserHttpContext.User.Identity.IsAuthenticated

您可以在 RSA Wikipedia page 上找到对此概念的更简单描述,在 my blog post 上找到有关 Firebase + ASP.NET 的更多信息。

【讨论】:

我创建了一个涵盖这个gist.github.com/deeja/c67e6027ca37a8d6a367b8b8bf86d5c6的要点【参考方案2】:

对于后端,有一个 Nuget 包可以为您解决问题:

安装包 AspNetCore.Firebase.Authentication

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  ILoggerFactory loggerFactory)
      
app.UseFirebaseAuthentication("https://securetoken.google.com/MYPROJECTNAME", "MYPROJECTNAME");

它负责受众、发行者、签名和有效性验证

【讨论】:

不确定这是否适用于 ASP .NET Core 2.0。我收到以下错误:无法从程序集“Microsoft.AspNetCore.Authentication.JwtBearer, Version=2.0.0.0 加载类型“Microsoft.AspNetCore.Builder.JwtBearerOptions” @Raphaël ApiKey 有什么用? @TzviGregoryKaidanov 实际上它在 appsettings 中,但未使用,因为中间件仅验证令牌和签名,不需要 ApiKey @Primico 我发布了一个 .netcore2.0 兼容包 嗨@Raphaël,我在.Net Core 2.1 上使用你的nuget 包非常好。但它不适用于 .Net Core 3.1。你能帮我检查一下这个问题吗?【参考方案3】:

NuGet 数据包使用旧的 ASP NET Core 1.x 身份验证机制

认证已更改:https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

【讨论】:

发布了支持.aspnetcore2.0的包AspNetCore.Firebase.Authentication 2.0

以上是关于使用 .NET Core 的 Firebase 身份验证 (JWT)的主要内容,如果未能解决你的问题,请参考以下文章

Dora.Interception,为.NET Core度身打造的AOP框架 [2]:以约定的方式定义拦截器

Dora.Interception, 为.NET Core度身打造的AOP框架[4]:演示几个典型应用

Dora.Interception,为.NET Core度身打造的AOP框架 [3]:多样化拦截器应用方式

Dora.Interception,为.NET Core度身打造的AOP框架 [5]:轻松地实现与其他AOP框架的整合

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

Asp net core 和 Firebase 身份验证