简体   繁体   中英

WebAPI Authorization Attribute not being called with IdentityServer3 Bearer Token

I have a WebAPI 2 project that uses a token issued by an IdentityServer3 token provider. In my Startup.cs file I have the IdentityServerBearerTokenAuthorization middleware implemented and it, along with a global AuthorizateAttribute filter, is requiring that a valid token be present in the request. However, I have also added ClaimsTransformation so I can extract "roles" from the claims in either a token issued using the implicit flow or a token issued for the client credential flow. I can't use a scope here because, I have 1 scope that gives you access to use my API, but all clients are not allowed to use all api endpoints.

Startup.cs

 JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();


        app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions()
        {
            Authority = ConfigurationManager.AppSettings["IdentityServer"],
            RequiredScopes = new[] { "my.api" },
        });



        httpConfig.MapHttpAttributeRoutes();
        httpConfig.Filters.Add(new AuthorizeAttribute());


        //SwaggerConfig.Register(httpConfig);

        app.UseAutofacMiddleware(container);
        app.UseAutofacWebApi(httpConfig);
        app.UseWebApi(httpConfig);

        app.UseClaimsTransformation(identity =>
        {
            var principal = new ClaimsPrincipal(identity);
            if (!identity.HasClaim(c => c.Type == "name") && identity.HasClaim(c => c.Type == "client_name"))
            {
                identity.Identities.First().AddClaim(new Claim("name", identity.Claims.First(c => c.Type == "client_name").Value));
            }

            //we want to remove the client_ from the claims so we can evaluate clients like they are users
            if (identity.Claims.Any(c => c.Type.Contains("client_")))
            {
                foreach (var claim in identity.Claims.Where(c => c.Type.Contains("client_")))
                {
                    var newClaimType = claim.Type.Replace("client_", "");
                    identity.Identities.First().AddClaim(new Claim(newClaimType, claim.Value));
                }
            }

            //set the scopes as roles also
            if (identity.Claims.Any(c => c.Type == "scope"))
            {
                identity.Identities.First().AddClaims(identity.Claims.Where(c => c.Type == "scope").Select(c => new Claim("role", c.Value)));
            }

            return Task.FromResult(principal);
        });

On my APIController operation, I have an Authorize attribute with a Roles property defined. The global Authorize attribute is working but the check for roles never happens. Am I missing something? \\ API Controller

    [HttpDelete]
    [Authorize(Roles = "item.deleter")]
    [Route("{itemId:guid}")]
    public async Task<HttpResponseMessage> DeleteAsync([ValidGuid] Guid itemId)
    {
        _log.Audit.Info($"Received Delete request for item {itemId} from user {User.Identity?.Name}.");
        if (!ModelState.IsValid)
      ....

Your authroize attribute is most likely firing before your claims transform fires.

In your owin pipeline, you've added webAPI before the claims transform. As your request travels along the pipeline, web api will get the request & run the authorize against it before the claims transform can do its bit.

Try moving the UseClaimsTransformation before the UseWebApi

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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