简体   繁体   English

使用Asp.Net Core WebAPI进行授权

[英]Authorization with Asp.Net Core WebAPI

Admittedly, this is a first stab at building an Asp.Net Core web api project.. One requirement is to support OAuth2. 不可否认,这是建立Asp.Net Core web api项目的第一步。一个要求是支持OAuth2。 The Api and Identity server are two separate projects, both started from an Asp.Net core Empty template. Api和Identity服务器是两个独立的项目,都是从Asp.Net核心空模板开始的。

Identity server is up and running, and tokens are being provided via the resource owner flow. 身份服务器已启动并正在运行,并且正在通过资源所有者流提供令牌。 Getting the token is fine, scopes and relevant access_token details appear to be correct. 获取令牌很好,范围和相关的access_token详细信息似乎是正确的。

When I issue a get request to my resource end-point, I get the following at first... 当我向我的资源端点发出get请求时,我首先得到以下信息......

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:12886/v1/mystuff
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[2]
      Successfully validated the token.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[3]
      HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[8]
      AuthenticationScheme: Bearer was successfully authenticated.
info: IdentityModel.AspNetCore.ScopeValidation.ScopeValidationMiddleware[0]
      Scopes found on current principal: scope: stuffdetails, scope: stuffmover
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[8]
      AuthenticationScheme: Bearer was successfully authenticated.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful for user: 939d72dd-654c-447f-a65d-d0426b1eca59.

So, I can tell middleware is validating my token, reading scopes, and the authenticating the token. 所以,我可以告诉中间件正在验证我的令牌,读取范围以及验证令牌。 However, immediately following the initial success, I get authorization failures. 但是,在最初的成功之后,我立即获得了授权失败。

info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: 939d72dd-654c-447f-a65d-d0426b1eca59.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware[13]
      AuthenticationScheme: Bearer was forbidden.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action TestApi.StuffController.GetStuff (TestApi) in 32.4439ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 1207.1769ms 403

Here is what I believe are the relevant bits in startup. 以下是我认为启动时的相关内容。

ConfigureServices... ConfigureServices ...

services.AddMvcCore()
        .AddAuthorization(opts =>
            {
                opts.AddPolicy("stuffdetails",
                    policy => policy.RequireClaim("stuffdetails"));
            }
        )
        .AddJsonFormatters();

services.AddOptions();

Configure -- Note that I know my configOptions are correct because the initial token challenge is successful. 配置 - 请注意,我知道我的configOptions是正确的,因为初始令牌质询是成功的。

var authServerOptions = new IdentityServerAuthenticationOptions
{
    Authority =  configOptions.Value.AuthServerSettings.AuthServerURI,
    RequireHttpsMetadata = configOptions.Value.AuthServerSettings.RequiresHttpsMetaData,
    ApiName = configOptions.Value.AuthServerSettings.ApiName,
    AllowedScopes = configOptions.Value.AuthServerSettings.AllowedScopes,
    SupportedTokens = IdentityServer4.AccessTokenValidation.SupportedTokens.Jwt,
    AuthenticationScheme = "Bearer",
    SaveToken = true,
    ValidateScope = true
};

app.UseIdentityServerAuthentication(authServerOptions);
app.UseMvc();

Stuff Controller 东西控制器

[Route("v1/[controller]")]
[Authorize(ActiveAuthenticationSchemes = "Bearer")]
public class StuffController : Controller
{
    [HttpGet]
    [Authorize(Policy = "stuffdetails")]
    public JsonResult GetStuff()
    {
        return new JsonResult(new
        {
            Message = "You've got stuff.."
        });
    }
}

If I remove the Authorize attribute from the GetStuff method, everything is fine because as the log showed, the bearer token is authorized. 如果我从GetStuff方法中删除Authorize属性,一切都很好,因为如日志所示,持有者令牌被授权。

The questions: 问题:

  1. Is authorization failing because my policy is incorrect, and if so how should it be setup? 授权是否失败,因为我的政策不正确,如果是这样,应如何设置?
  2. If I want to validate a token contains the proper claims, and was authorized, is it correct to use policies as I have? 如果我想验证令牌包含正确的声明并获得授权,那么使用我的策略是否正确?
  3. Am I making a mistake trying to use UseIdentityServerAuthentication instead of UseJwtBearerAuthentication ? 我是否在尝试使用UseIdentityServerAuthentication而不是UseJwtBearerAuthentication时犯了错误

Any help is greatly appreciated.. 任何帮助是极大的赞赏..

Is authorization failing because my policy is incorrect, and if so how should it be setup? 授权是否失败,因为我的政策不正确,如果是这样,应如何设置?

What you've got looks correct, but you can easily verify by just removing the 'policy' part of your Authorize attribute: if it now works then the problem is to do with your policy, if it still fails then it is a broader problem than just your policy. 您所看到的内容看起来是正确的,但您只需删除“授权”属性的“政策”部分即可轻松验证:如果它现在有效,则问题与您的政策有关,如果仍然失败那么这是一个更广泛的问题而不仅仅是你的政策。 I'm assuming you're adding the 'stuffdetails' claim into your access_token with your own implementation of the IProfileService ? 我假设您使用自己的IProfileService实现将“stuffdetails”声明添加到access_token中?

If I want to validate a token contains the proper claims, and was authorized, is it correct to use policies as I have? 如果我想验证令牌包含正确的声明并获得授权,那么使用我的策略是否正确?

Yes that seems to be the aspnet core way of doing custom authorization. 是的,似乎是aspnet进行自定义授权的核心方式。

Am I making a mistake trying to use UseIdentityServerAuthentication instead of UseJwtBearerAuthentication? 我是否在尝试使用UseIdentityServerAuthentication而不是UseJwtBearerAuthentication时犯了错误?

I am using the UseIdentityServerAuthentication with the ResourceOwnerPassword flow. 我正在使用UseIdentityServerAuthenticationResourceOwnerPassword流。 I'd be interested to hear if the UseJwtBearerAuthentication approach is preferred or offers other features. 我有兴趣听听UseJwtBearerAuthentication方法是首选还是提供其他功能。

The error on my part was the way I created my policy: 我的错误是我创建政策的方式:

opts.AddPolicy("stuffdetails",
                            policy => policy.RequireClaim("stuffdetails"));

Should be: 应该:

opts.AddPolicy("stuffdetails",
                            policy => policy.RequireClaim("scope","stuffdetails"));

The policy was supposed to confirm the scopes included "stuffdetails".. A great resource for anyone having trouble is a post by damienbod, Authorization Policies and Data Protection with IdentityServer4 in ASP.Net Cord 该策略应该确认范围包括“stuffdetails”..对于任何遇到麻烦的人来说,一个很好的资源是在db.Net Cord中使用IdentityServer4的damienbod, 授权策略和数据保护的帖子

Additionally you could implement this leveraging Microsoft.Aspnetcore.Authorization. 此外,您可以利用Microsoft.Aspnetcore.Authorization实现此功能。 The main benefits being that's it's simpler to read and it allows you to specify multiple scopes (union/or). 主要的好处是它更易于阅读,它允许您指定多个范围(union /或)。

opts.AddPolicy("stuffdetails", ScopePolicy.Create("stuffdetails", "stuffdetails2"));

instead of 代替

opts.AddPolicy("stuffdetails",
                        policy => policy.RequireClaim("scope","stuffdetails"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM