Giraffe icon indicating copy to clipboard operation
Giraffe copied to clipboard

authorizeRequest: Async or Task predicate

Open megafinz opened this issue 6 years ago • 4 comments

Yello.

Currently authorizeRequest expects a synchronous predicate : HttpContext -> bool. What do you think about adding an async version(s) of the predicate when we need to perform some IO in order to validate the request?

megafinz avatar Aug 27 '19 13:08 megafinz

Hi, I think it is not needed, but because the authentication/authorization piece in ASP.NET Core is so fragmented it can be easily misunderstood so that one would like to have such a handler.

May I ask what is it that you'd be doing with authorizeRequestAsync?

Here is why I believe you might not need it:

  • Use the policy based handlers to authorize a ClaimsPrincipal: authorizeByPolicyName and authorizeByPolicy via IAuthorizationService.AuthorizeAsync which is already async
  • If you want to change how the principal is created in the first place (= authentication, not authorization) then you should create your own authentication handler which implements IAuthenticationHandler. Check out this example.

My guess is that you probably want to do the latter. Unfortunately there is so much information scattered around the interent and ASP.NET (Core) that it can be hard to find one simple coherent example, if you struggle then let me know and I'll quickly knock out a very small example showing how it can be done with Giraffe!

dustinmoris avatar Sep 29 '19 12:09 dustinmoris

I was trying to port some code from C#. The flow was: user makes a request to a service with his access token to access some resource, this service then delegates token validation to another service and then composes a response. I believe we had a custom IAuthenticationHandler in C#, but I wanted to simplify this flow as much as possible, so authorizeRequest seemed relevant (a couple of lines of code instead of creating a separate class, setting up the DI, etc.). Unfortunately I'm no longer involved in this project so this issue is no longer relevant for me.

megafinz avatar Sep 30 '19 11:09 megafinz

I believe I may have found a use case for authorizeRequestAsync. We're using a custom implementation of it to do Google reCAPTCHA verification. Basically, this involves reading a token from the request (in our case, a query parameter) and POST-ing it to the reCAPTCHA service along with a secret key. If the reCAPTCHA service returns {"success": true , ...}, the request should be allowed.

Perhaps you're right @dustinmoris, that this would be better as an IAuthenticationHandler, but using authorizeRequestAsync feels more like staying in Giraffe land.

This is our implementation, in case it might be useful to someone:

let authorizeRequestAsync (predicate : HttpContext -> Async<bool>) (authFailedHandler : HttpHandler) : HttpHandler =
    fun (next : HttpFunc) (ctx : HttpContext) ->
        task {
            let! isAuthorized = predicate ctx
            return! (if isAuthorized then next else authFailedHandler earlyReturn) ctx
        }

jonekdahl avatar Oct 05 '21 10:10 jonekdahl

I have the same issue in the project I'm working on, the predicate function needs to access the DB and I want to do the DB stuff async, so I wrote something similar to what @jonekdahl wrote here. So +1 for this request. If it gets approved I can create a PR

ivan-brko avatar Oct 13 '22 05:10 ivan-brko