codeandcloud
codeandcloud

Reputation: 55210

response is always 200 ok when using custom authorize

I have a CustomAuthorizeAttributeclass implemented like this.

Public Overrides Sub OnAuthorization(actionContext As HttpActionContext)
    If Authorize(actionContext) Then
        Return
    End If
    HandleUnauthorizedRequest(actionContext)
End Sub

Protected Overrides Sub HandleUnauthorizedRequest(actionContext As HttpActionContext)
    Dim challengeMessage = New HttpResponseMessage(HttpStatusCode.Unauthorized)
    challengeMessage.Headers.Add("WWW-Authenticate", "Basic")
    Throw New HttpResponseException(challengeMessage)

End Sub

Private Function Authorize(actionContext As HttpActionContext) As Boolean
    Dim isAuthorized = False
    Try
        'make it true if all goes validations go well
        Return True
    Catch generatedExceptionName As Exception
    End Try
    Return isAuthorized
End Function

When authorization fails, it gets hit on Throw New HttpResponseException(challengeMessage) and never enters the service endpoint as expected. The problem is that my HTTPResponse=200 OK when I call the API instead of 403 UnAuthorized. What is wrong with my code?

Update:

<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Method, AllowMultiple:=False, Inherited:=True)>
Public Class CustomAuthorizeAttribute
    Inherits AuthorizeAttribute

Upvotes: 1

Views: 759

Answers (1)

David Tansey
David Tansey

Reputation: 6023

It looks like the 200 response you receive at the client is because the response is converted to a 302 redirect to the login page (which is what you would likely want if the request was coming from a ASP.NET WebForm or MVC view).

Try editing Startup.Auth.vb and replace the original app.UseCookieAuthentication with the following:

    app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
        .AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        .Provider = New CookieAuthenticationProvider() With {
            .OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser)(
                validateInterval:=TimeSpan.FromMinutes(30),
                regenerateIdentity:=Function(manager, user) user.GenerateUserIdentityAsync(manager)),
            .OnApplyRedirect =
                Function(ctx)
                    If Not IsApiRequest(ctx.Request) Then
                        ctx.Response.Redirect(ctx.RedirectUri)
                    End If
                End Function
        },
        .LoginPath = New PathString("/Account/Login")})

which will also require you to add the following function IsApiRequest at the bottom of Startup.Auth.vb after the ConfigureAuth function block and before the End Class statement:

Private Shared Function IsApiRequest(request As IOwinRequest) As Boolean
    Dim apiPath As String = VirtualPathUtility.ToAbsolute("~/api/")
    Return request.Uri.LocalPath.StartsWith(apiPath)
End Function

This will avoid the redirect to the login form (for requests that are directed to your WebApi routes) and return the HTTP status 401 that your code is throwing.

More information about this (C# only) can be found in this article:

http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/

Upvotes: 3

Related Questions