4

我使用Asp.net核心rc2与OpenIdConnectServer。我正在使用angular 1.x和augular-oauth2。几天后,我的错误话题扯到基于Asp.net核心令牌的声明认证与OpenIdConnect和angularjs:承载被禁止

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:54275/api/Account/Username 
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token. 
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer. 
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was successfully authenticated. 
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: . 
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Warning: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'. 
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (Bearer). 
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden. 

我ConfigureServices由

services.AddAuthorization(options => 
      { 
       options.AddPolicy("UsersOnly", policy => 
       { 
        policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme); 
        policy.RequireClaim("role"); 
       }); 
      }); 

我的配置已经

app.UseWhen(context => context.Request.Path.StartsWithSegments(new PathString("/api")), branch => 
      { 
       branch.UseJwtBearerAuthentication(new JwtBearerOptions 
       { 
        AutomaticAuthenticate = true, 
        AutomaticChallenge = true, 
        RequireHttpsMetadata = false, 

        Audience = "http://localhost:54275/", 
        Authority = "http://localhost:54275/", 
        TokenValidationParameters = new TokenValidationParameters 
        { 
         ValidAudience = "client1", 
         //ValidAudiences = new List<string> { "", "empty", "null"} 
        } 
       }); 
      }); 

      app.UseOpenIdConnectServer(options => 
      { 
       options.AuthenticationScheme = OpenIdConnectServerDefaults.AuthenticationScheme; 
       options.Provider = new SimpleAuthorizationServerProvider(); 
       options.AccessTokenHandler = new JwtSecurityTokenHandler(); 
       options.ApplicationCanDisplayErrors = true; 
       options.AllowInsecureHttp = true; 
       options.TokenEndpointPath = new PathString("/oauth2/token"); 
       options.LogoutEndpointPath = new PathString("/oauth2/logout"); 
       options.RevocationEndpointPath = new PathString("/oauth2/revoke"); 
       options.UseJwtTokens(); 
       //options.AccessTokenLifetime = TimeSpan.FromHours(1); 
      }); 

我的授权属性控制器上的定义为

[Authorize(Policy = "UsersOnly", ActiveAuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme), Route("api/Account")] 

我将令牌存储为cookie,并使用http拦截器将其附加到请求中。

我生成

public override async Task GrantResourceOwnerCredentials(GrantResourceOwnerCredentialsContext context) 
     { 
      // validate user credentials (demo mode) 
      // should be stored securely (salted, hashed, iterated) 
      using (var con = new SqlConnection(ConnectionManager.GetDefaultConnectionString())) 
      { 
       if (!Hashing.ValidatePassword(context.Password, await con.ExecuteScalarAsync<string>("SELECT PassHash FROM dbo.Users WHERE Username = @UserName", new { context.UserName }))) 
       { 
        context.Reject(
         error: "bad_userpass", 
         description: "UserName/Password combination was invalid." 
         ); 
        return; 
       } 

       // create identity 
       var id = new ClaimsIdentity(context.Options.AuthenticationScheme); 
       id.AddClaim(new Claim("sub", context.UserName)); 
       id.AddClaim(new Claim("role", "user")); 

       // create metadata to pass on to refresh token provider 
       var props = new AuthenticationProperties(new Dictionary<string, string> 
       { 
        {"as:client_id", context.ClientId} 
       }); 
       var ticket = new AuthenticationTicket(new ClaimsPrincipal(id), props, 
        context.Options.AuthenticationScheme); 
       ticket.SetAudiences("client1"); 
       //ticket.SetScopes(OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, "api-resource-controller"); 
       context.Validate(ticket); 
      } 
     } 

我已经花了过去三天在这个问题上的记号,我意识到,在这一点上,我可能失去了一些东西很明显,由于睡眠不足。任何帮助,将不胜感激。

+0

哪个dotnet核心程序集包含扩展方法UseOpenIdConnectServer – schmidlop

回答

4

你看到的可能是由两个因素造成的错误:

  • 你没有安装一个明确的目的地,您的自定义role要求,使之永远的访问令牌序列化。您可以找到有关此安全功能on this other SO post的更多信息。

  • policy.RequireClaim("role");可能无法正常工作OTB,作为IdentityModel使用内部映射,其将著名的智威汤逊声称他们ClaimTypes等价的:在这里,role将可能由http://schemas.microsoft.com/ws/2008/06/identity/claims/roleClaimTypes.Role)所取代。我建议使用policy.RequireRole("user")代替。

另外值得一提的是手动存储client_id是没有必要的,因为它是你由ID连接服务器中间件已经完成。

您可以使用ticket.GetPresenters()检索它,它返回授权演示者列表(这里是客户端标识符)。请注意,它也会自动确保发给客户端A的刷新令牌不能由客户端B使用,因此您不必在自己的代码中执行此操作。

相关问题