从Owin WebApi2返回描述性401消息

时间:2021-09-24 12:49:08

I have an asp.net 4.5 web api running using owin. Whenever an unauthorized request is made it returns a 401 with the following response as expected:

我有一个使用owin运行的asp.net 4.5 web api。无论何时发出未经授权的请求,它都会返回401,其响应符合预期:

{"Message":"Authorization has been denied for this request."}

I would like to add additional detail to this response (expired token, invalid role, etc...) and implemented a custom [AuthorizeAttribute] based on this SO post.

我想在此响应中添加其他详细信息(过期令牌,无效角色等等),并根据此SO帖子实现自定义[AuthorizeAttribute]。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        var response = actionContext.Request.CreateResponse<MyError>
            (new MyError() { Description = "This is why you're unauthorized" });
        response.StatusCode = HttpStatusCode.Unauthorized;
        actionContext.Response = response;
    }
}

and then used it on my controllers like this:

然后在我的控制器上使用它,如下所示:

[MyAuthorizeAttribute(Roles = "Foo")]
public class MyController : ApiController
{
    ...
}

which returns a 401 with the following response as expected:

返回401,并按预期返回以下响应:

{"Description": "This is why you're unauthorized"}

However, I do not see how to determine the reason the request is unauthorized from the HttpActionContext passed to MyAuthorizeAttribute.HandleUnauthorizedRequest. For instance, when I'm debugging locally and make a request with an expired token it throws a SecurityTokenExpiredException explaining IDX10223: Lifetime validation failed. The token is expired. ValidTo: '...' Current time: '...'. or with a invalid audience it throws a SecurityTokenInvalidAudienceException explaining Message=IDX10214: Audience validation failed. Audiences: '...'. Did not match: validationParameters.ValidAudience: 'null' or validationParameters.ValidAudiences: '...'. I've set several breakpoints in my Startup.cs yet have been unable to even catch one of these exceptions before they're thrown.

但是,我没有看到如何从传递给MyAuthorizeAttribute.HandleUnauthorizedRequest的HttpActionContext中确定请求未经授权的原因。例如,当我在本地调试并使用过期令牌发出请求时,它会抛出一个解释IDX10223的SecurityTokenExpiredException:Lifetime验证失败。令牌已过期。 ValidTo:'...'当前时间:'...'。或者对于无效的受众,它会抛出SecurityTokenInvalidAudienceException,解释Message = IDX10214:受众验证失败。观众:'......'。不匹配:validationParameters.ValidAudience:'null'或validationParameters.ValidAudiences:'...'。我在我的Startup.cs中设置了几个断点,但在它们被抛出之前甚至无法捕获其中一个异常。

How can I determine the specific reason a request is unauthorized using owin middleware?

如何使用owin中间件确定请求未经授权的具体原因?

1 个解决方案

#1


0  

Haven't figured out how to identify expirations nor invalid audiences and such, but I ended up using this to at least return 403s based on roles.

还没有弄清楚如何识别到期时间或无效的受众等等,但我最终使用它来至少根据角色返回403。

You can customize the message ("You must have role X to access this action ...") using the example in my question above.

您可以使用上面问题中的示例自定义消息(“您必须具有角色X以访问此操作...”)。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);

        if (actionContext.RequestContext.Principal != null && 
            actionContext.RequestContext.Principal.Identity.IsAuthenticated && 
            Roles != null)
        {
            if (!Roles.Split(',').Any(x => 
                actionContext.RequestContext.Principal.IsInRole(x.Trim())))
            {
                actionContext.Response.StatusCode = HttpStatusCode.Forbidden;
            }
        }
    }
}

#1


0  

Haven't figured out how to identify expirations nor invalid audiences and such, but I ended up using this to at least return 403s based on roles.

还没有弄清楚如何识别到期时间或无效的受众等等,但我最终使用它来至少根据角色返回403。

You can customize the message ("You must have role X to access this action ...") using the example in my question above.

您可以使用上面问题中的示例自定义消息(“您必须具有角色X以访问此操作...”)。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
    {
        base.HandleUnauthorizedRequest(actionContext);

        if (actionContext.RequestContext.Principal != null && 
            actionContext.RequestContext.Principal.Identity.IsAuthenticated && 
            Roles != null)
        {
            if (!Roles.Split(',').Any(x => 
                actionContext.RequestContext.Principal.IsInRole(x.Trim())))
            {
                actionContext.Response.StatusCode = HttpStatusCode.Forbidden;
            }
        }
    }
}