使用 Windows 身份验证生成 JWT 时,授权属性不起作用

时间:2021-06-04 20:16:12

标签: c# asp.net-mvc oauth jwt access-token

背景

我继承了一个 .NET 框架 v4.6.1 MVC Web 应用程序。身份验证是Windows auth,我们无权添加IdentityServer 或Azure AD。

我们将在 6 个月内重新编写整个应用程序,但现在我们需要实现一个功能,该功能需要生成 JWT 并将其应用于特定的控制器/操作。

问题

我已经实现了自己的 OAuth 授权服务器,但是当我使用 @x 属性修饰控制器的操作时,HTTP 请求对操作进行了任何拦截。

代码

[Authorize]

Startup.cs

[assembly: OwinStartup(typeof(SomeNamespace.Startup))] namespace SomeNamespace { public class Startup { public void Configuration(IAppBuilder app) { //removed for brevity... app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions { AuthenticationMode = AuthenticationMode.Active, AllowedAudiences = new [] { ConfigurationManager.AppSettings["Jwt-Audience"] }, TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateIssuerSigningKey = true, ValidIssuer = ConfigurationManager.AppSettings["Jwt-Issuer"], ValidAudience = ConfigurationManager.AppSettings["Jwt-Audience"], IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(ConfigurationManager.AppSettings["Jwt-SigningKey"])) } }); app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions { AllowInsecureHttp = true, TokenEndpointPath = new PathString("/oauth2/token"), AccessTokenExpireTimeSpan = TimeSpan.FromSeconds(30), Provider = new MyOAuthProvider(), AccessTokenFormat = new MyJwtFormat(ConfigurationManager.AppSettings["Jwt-Issuer"]) }); } } public class MyJwtFormat : ISecureDataFormat<AuthenticationTicket> { private static readonly byte[] _secret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["Jwt-SigningKey"]); private readonly string _issuer; public MyJwtFormat(string issuer) { _issuer = issuer; } public string Protect(AuthenticationTicket data) { if (data == null) { throw new ArgumentNullException(nameof(data)); } var issued = data.Properties.IssuedUtc; var expires = data.Properties.ExpiresUtc; var securityKey = new SymmetricSecurityKey(_secret); var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature); return new JwtSecurityTokenHandler().WriteToken(new JwtSecurityToken(_issuer, ConfigurationManager.AppSettings["Jwt-Audience"], data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingCredentials)); } public AuthenticationTicket Unprotect(string protectedText) { throw new NotImplementedException(); } } public class MyOAuthProvider : OAuthAuthorizationServerProvider { public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { context.Validated(); return Task.FromResult<object>(null); } public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); //Owin doesn't seem to have any knowledge of my DbContext var user = context.OwinContext.Get<MyContext>(null).StaffMembers.AsNoTracking().FirstOrDefault(x => x.Username == context.OwinContext.Authentication.User.Identity.Name); //temp hack to get the user from the DB user = new MyContext().StaffMembers.AsNoTracking().FirstOrDefault(x => x.Username == "someuser"); if (user == null) { context.SetError("invalid_grant", "The user is not a registered"); context.Rejected(); return Task.FromResult<object>(null); } var ticket = new AuthenticationTicket(SetClaimsIdentity(context, user), new AuthenticationProperties()); context.Validated(ticket); return Task.FromResult<object>(null); } private static ClaimsIdentity SetClaimsIdentity(OAuthGrantResourceOwnerCredentialsContext context, StaffMember model) { var identity = new ClaimsIdentity("JWT"); var claims = new List<Claim> { new Claim(ClaimTypes.Sid, model.StaffId.ToString()), new Claim(ClaimTypes.Name, model.FullName), new Claim(ClaimTypes.WindowsAccountName, model.Username), //new Claim(ClaimTypes.Expiration, newExpiry.ToString("yyyy-MM-dd HH:mm:ss")), }; identity.AddClaims(claims); return identity; } }

Sample controller action

[System.Web.Mvc.HttpGet] [System.Web.Mvc.Authorize] public async Task<ActionResult> Something() { var result = await _service.SomeMethod(); return new JsonStringResult(result); } (尝试使用和不使用此过滤器注册)

FilterConfig.cs

0 个答案:

没有答案