当需要 RSA 安全密钥时,如何在 .NET 7 中处理 Bearer 令牌?

问题描述 投票:0回答:1

现有 .NET Framework 应用程序可创建 Bearer 令牌。另一个现有的 .NET Framework 代码应用程序能够识别令牌以进行身份验证和授权。使用 RSA 安全密钥,因此它不像我之前在该主题上的工作那么简单。

我的任务是创建一个也能够识别相同令牌的 .NET 7 应用程序。我没有成功。这就是我在一个 .NET 7 应用程序中隔离该问题的原因。希望有人可以修复我的扩展方法,使其能够正常工作。

让我向您展示我的扩展方法:

    public static IServiceCollection AddCustomJwtAuthentication(this IServiceCollection services, AuthConfiguration authConfiguration)
    {
        // Initialize RSA parameters for public key
        var rsa = new RSACryptoServiceProvider(2048);
        rsa.FromXmlString(authConfiguration.OAuthAccessTokenSigningKeyPublic);
        var rsaPublicKey = new RsaSecurityKey(rsa.ExportParameters(false));

        var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(authConfiguration.OAuthTokenEncryptionKey));

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    AuthenticationType = "Bearer",
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = authConfiguration.OAuthIssuer,
                    ValidAudience = authConfiguration.OAuthAudience,
                    IssuerSigningKey = rsaPublicKey, // Used for verifying the token's signature
                    TokenDecryptionKey = symmetricSecurityKey, // Used for decrypting the token's payload
                    ValidAlgorithms = new[]
                    {
                        SecurityAlgorithms.RsaSha512Signature, // For signature verification
                        SecurityAlgorithms.Aes256KW, // For key wrapping during decryption
                        SecurityAlgorithms.Aes128CbcHmacSha256 // For content encryption/decryption
                    }
                };

                options.Events = new JwtBearerEvents
                {
                    OnAuthenticationFailed = context =>
                    {
                        Console.WriteLine($"OnAuthenticationFailed {context.Exception}");
                        if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        {
                            context.Response.Headers.Append("Token-Expired", $"{true}");
                        }
                        return Task.CompletedTask;
                    },
                    OnTokenValidated = context =>
                    {
                        Console.WriteLine($"OnTokenValidated: with SecurityToken valid to {context.SecurityToken.ValidTo}");
                        return Task.CompletedTask;
                    },
                    OnChallenge = context =>
                    {
                        Console.WriteLine($"OnChallenge: {context.Error} - {context.ErrorDescription}");
                        return Task.CompletedTask;
                    }
                };
            });

        return services;
    }

我也会展示我的代币创建者:

public class TokenCreator
{
    private const int KeySize = 2048;
    private readonly string _issuer;
    private readonly string _audience;
    private readonly SymmetricSecurityKey _encryptionKey;
    private readonly EncryptingCredentials _encryptingCredentials;
    private SigningCredentials _signingCredentials;

    private TokenCreator(string encryptionKey, string issuer, string audience)
    {
        if (string.IsNullOrWhiteSpace(encryptionKey)) throw new ArgumentNullException(nameof(encryptionKey));
        _issuer = issuer;
        _audience = audience;
        _encryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(encryptionKey));
        _encryptingCredentials = new EncryptingCredentials(
            _encryptionKey,
            SecurityAlgorithms.Aes256KW,
            SecurityAlgorithms.Aes128CbcHmacSha256);
    }

    public TokenCreator(AuthConfiguration authConfiguration) : this (authConfiguration.OAuthTokenEncryptionKey,
        authConfiguration.OAuthIssuer, authConfiguration.OAuthAudience)
    {
        SetSigningCredentials(authConfiguration.OAuthAccessTokenSigningKeyPrivate);
    }


    private void SetSigningCredentials(string privateSigningKeyXml)
    {
        if (string.IsNullOrWhiteSpace(privateSigningKeyXml)) throw new ArgumentNullException(nameof(privateSigningKeyXml));
        using (var rsa = new RSACryptoServiceProvider(KeySize))
        {
            rsa.FromXmlString(privateSigningKeyXml);
            _signingCredentials = new SigningCredentials(new RsaSecurityKey(rsa.ExportParameters(true)), SecurityAlgorithms.RsaSha512Signature);
        }
    }

    public virtual string CreateToken(DateTime expires, DateTime issued)
    {
        // Define claims
        var claims = new List<Claim>
        {
            new(ClaimTypes.Name, "John Doe"),
            new(ClaimTypes.Email, "[email protected]"),
            new(ClaimTypes.Role, "Administrator"),
            new("CustomClaimType", "CustomClaimValue")
        };
        var identity = new ClaimsIdentity(claims, "Bearer");
        var handler = new JwtSecurityTokenHandler();
        var token = handler.CreateJwtSecurityToken(_issuer, _audience, identity, null, expires, issued, _signingCredentials, _encryptingCredentials);
        var jwt = handler.WriteToken(token);
        return jwt;
    }
}

我也会分享我的节目课:

    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            // Add services to the container.

            builder.Services.AddControllers();
            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();
            
            var authConfiguration = builder.Configuration.GetSection(nameof(AuthConfiguration)).Get<AuthConfiguration>()!;
            builder.Services.AddCustomJwtAuthentication(authConfiguration);

            var tokenCreator = new TokenCreator(authConfiguration);
            var token = tokenCreator.CreateToken(DateTime.UtcNow.AddHours(1), DateTime.UtcNow);
            Console.WriteLine("Token is coming");
            Console.WriteLine(token);
            Console.WriteLine("End of token");

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseHttpsRedirection();
            app.UseAuthentication(); 
            app.UseAuthorization();


            app.MapControllers();

            app.Run();
        }
    }

由于这个 Web api 为我生成了一个令牌,我可以直接使用 VSCode REST Client 进行测试:

GET https://localhost:7134/api/Authentication/verifyAuthentication
Authorization: Bearer SUPERLONGTOKEN

这是调用我的控制器方法:

    [Route("api/[controller]")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    {
        [HttpGet("verifyAuthentication")]
        [Authorize]
        public IActionResult VerifyAuthentication()
        {
            return Ok("Auth succeeded");
        }
    }

这给出了以下输出:

HTTP/1.1 401 Unauthorized
Content-Length: 0
Connection: close
Date: Tue, 11 Jun 2024 12:26:12 GMT
Server: Kestrel
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature key was not found"

代币生成成功,所以这不是我关心的问题。为了能够使用它,我需要使用与 .NET Framework 代码相同的键来编写扩展方法。显然,我没有正确执行此操作,因为我没有收到 200 的退款。那么,当需要 RsaSecurityKey 时,需要更改哪些内容来处理 .NET 7 中的 Bearer 令牌?

oauth jwt rsa .net-7.0 bearer-token
1个回答
0
投票

要使用 RSA 安全密钥处理 .NET 7 中的承载令牌,您需要配置 JWT 承载身份验证以使用 RSA 密钥进行令牌验证。这是分步指南:

  1. 安装所需的软件包: 确保您已安装 JWT Bearer 包:

    dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
    
  2. Program.cs
    中配置JWT身份验证: 更新您的
    Program.cs
    以添加具有 RSA 安全密钥配置的 JWT Bearer 身份验证。这是一个例子:

    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.IdentityModel.Tokens;
    using System.Security.Cryptography;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.AddControllers();
    
    // Configure JWT authentication
    builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        // Load RSA public key
        var rsa = new RSACryptoServiceProvider();
        rsa.ImportRSAPublicKey(
            source: Convert.FromBase64String(builder.Configuration["Jwt:PublicKey"]), // your RSA public key
            bytesRead: out _
        );
    
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new RsaSecurityKey(rsa)
        };
    });
    
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }
    
    app.UseHttpsRedirection();
    app.UseAuthentication();
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.Run();
    
  3. 应用程序设置配置: 确保您的

    appsettings.json
    包含必要的 JWT 配置:

    {
        "Jwt": {
            "Issuer": "your_issuer",
            "Audience": "your_audience",
            "PublicKey": "your_rsa_public_key_base64"
        }
    }
    
  4. 保护您的控制器操作: 使用

    [Authorize]
    属性来保护您的 API 端点:

    [ApiController]
    [Route("[controller]")]
    [Authorize]
    public class YourController : ControllerBase
    {
        // Your actions here
    }
    
  5. 生成 RSA 密钥: 如果您尚未生成 RSA 密钥,则可以使用 OpenSSL 等工具或在 .NET 中以编程方式生成它们。确保公钥正确编码为 Base64,以便在

    appsettings.json
    中使用。

遵循这些步骤应该可以帮助您配置 .NET 7 以使用 RSA 安全密钥进行令牌验证来处理 JWT Bearer 令牌。此设置可确保您的令牌根据 RSA 密钥进行验证,从而提供强大且安全的身份验证机制。

© www.soinside.com 2019 - 2024. All rights reserved.