suave icon indicating copy to clipboard operation
suave copied to clipboard

Support for a user object in the authenticate methods?

Open njlr opened this issue 1 year ago • 0 comments

Usually when authenticating, we care about who is authenticated!

However, the current methods in Authentication support this only via context, which has some issues:

  • Lacks type-safety
  • Lacks null-safety

I propose a new combinator like this:

let authenticateBasicUserAsync (tryAuthenticate : string * string -> Async<'user option>) (makeProtectedPart : 'user -> WebPart) : WebPart =
  fun ctx ->
    async {
      let p = ctx.request
      match p.header "authorization" with
      | Choice1Of2 header ->
        let (typ, username, password) = parseAuthenticationToken header
        if (typ.Equals("basic")) then
          let! maybeUser = tryAuthenticate (username, password)
      
          match maybeUser with
          | Some user ->
            return! makeProtectedPart user (addUserName username ctx)
          | None ->
            return! challenge ctx
        else 
          return! challenge ctx
      | Choice2Of2 _ ->
        return! challenge ctx
    }

The existing combinators can be defined in terms of this:

let authenticateBasicAsync (f : string * string -> Async<bool>) (protectedPart : WebPart) : WebPart =
  authenticateBasicUserAsync 
    (fun (username, password) ->
      async {
        let! isAuthenticated = f (username, password)

        if isAuthenticated then
          return Some ()
        else
          return None 
      })
    (fun () -> protectedPart)

njlr avatar Feb 16 '24 11:02 njlr