Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinmoris committed Oct 28, 2018
2 parents 0086747 + ed3f724 commit 0320a47
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 19 deletions.
37 changes: 30 additions & 7 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1978,9 +1978,34 @@ let webApp =
]
```

#### evaluateUserPolicy
#### authorizeRequest

The `evaluateUserPolicy (policy : ClaimsPrincipal -> bool) (authFailedHandler : HttpHandler)` http handler checks if an authenticated user meets a given user policy. If the policy cannot be satisfied then the `authFailedHandler` will be executed:
The `authorizeRequest (predicate : HttpContext -> bool) (authFailedHandler : HttpHandler)` http handler validates a request based on a given predicate. If the predicate returns false then the `authFailedHandler` will get executed:

```fsharp
let apiKey = "some-secret-key-1234"
let validateApiKey (ctx : HttpContext) =
match ctx.TryGetRequestHeader "X-API-Key" with
| Some key -> apiKey.Equals key
| None -> false
let accessDenied = setStatusCode 401 >=> text "Access Denied"
let requiresApiKey =
authorizeRequest validateApiKey accessDenied
let webApp =
choose [
route "/" >=> text "Hello World"
route "/private"
>=> requiresApiKey
>=> protectedResource
]
```

#### authorizeUser

The `authorizeUser (policy : ClaimsPrincipal -> bool) (authFailedHandler : HttpHandler)` http handler checks if an authenticated user meets a given user policy. If the policy cannot be satisfied then the `authFailedHandler` will get executed:

```fsharp
let notLoggedIn =
Expand All @@ -1994,12 +2019,11 @@ let accessDenied = setStatusCode 401 >=> text "Access Denied"
let mustBeLoggedIn = requiresAuthentication notLoggedIn
let mustBeJohn =
evaluateUserPolicy (fun u -> u.HasClaim (ClaimTypes.Name, "John")) accessDenied
authorizeUser (fun u -> u.HasClaim (ClaimTypes.Name, "John")) accessDenied
let webApp =
choose [
route "/" >=> text "Hello World"
route "/john-only"
>=> mustBeLoggedIn
>=> mustBeJohn
Expand All @@ -2009,7 +2033,7 @@ let webApp =

#### authorizeByPolicyName

The `authorizeByPolicyName (policyName : string) (authFailedHandler : HttpHandler)` http handler checks if an authenticated user meets a given authorization policy. If the policy cannot be satisfied then the `authFailedHandler` will be executed:
The `authorizeByPolicyName (policyName : string) (authFailedHandler : HttpHandler)` http handler checks if an authenticated user meets a given authorization policy. If the policy cannot be satisfied then the `authFailedHandler` will get executed:

```fsharp
let notLoggedIn =
Expand All @@ -2028,7 +2052,6 @@ let mustBeOver21 =
let webApp =
choose [
route "/" >=> text "Hello World"
route "/adults-only"
>=> mustBeLoggedIn
>=> mustBeOver21
Expand All @@ -2038,7 +2061,7 @@ let webApp =

#### authorizeByPolicy

The `authorizeByPolicy (policy : AuthorizationPolicy) (authFailedHandler : HttpHandler)` http handler checks if an authenticated user meets a given authorization policy. If the policy cannot be satisfied then the `authFailedHandler` will be executed.
The `authorizeByPolicy (policy : AuthorizationPolicy) (authFailedHandler : HttpHandler)` http handler checks if an authenticated user meets a given authorization policy. If the policy cannot be satisfied then the `authFailedHandler` will get executed.

See [authorizeByPolicyName](#authorizebypolicyname) for more information.

Expand Down
7 changes: 7 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Release Notes
=============

## 3.4.0

#### New features

- Added a new http handler called `authorizeRequest` to authorize a request based on a `HttpContext -> bool` predicate.
- Added a new http handler called `authorizeUser` which is an alias for `evaluateUserPolicy`. The `evaluateUserPolicy` handler will be removed in the next major release.

## 3.3.0

#### New features
Expand Down
2 changes: 1 addition & 1 deletion samples/SampleApp/SampleApp/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ let mustBeAdmin =

let mustBeJohn =
requiresAuthentication accessDenied
>=> evaluateUserPolicy (fun u -> u.HasClaim (ClaimTypes.Name, "John")) accessDenied
>=> authorizeUser (fun u -> u.HasClaim (ClaimTypes.Name, "John")) accessDenied

let loginHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
Expand Down
49 changes: 41 additions & 8 deletions src/Giraffe/Auth.fs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[<AutoOpen>]
module Giraffe.Auth

open System
open System.Security.Claims
open Microsoft.AspNetCore.Http
open Microsoft.AspNetCore.Authentication
Expand Down Expand Up @@ -47,7 +48,24 @@ let signOut (authScheme : string) : HttpHandler =

/// **Description**
///
/// Validates if a `ClaimsPrincipal` satisfies a certain condition. If the `policy` returns `true` then it will continue with the `next` function otherwise it will shortcircuit to the `authFailedHandler`.
/// Validates if a `HttpContext` satisfies a certain condition. If the `policy` returns `true` then it will continue with the `next` function otherwise it will short circuit and execute the `authFailedHandler`.
///
/// **Parameters**
///
/// - `policy`: One or many conditions which a `HttpContext` must meet. The `policy` function should return `true` on success and `false` on failure.
/// - `authFailedHandler`: A `HttpHandler` function which will be executed when the `policy` returns `false`.
///
/// **Output**
///
/// A Giraffe `HttpHandler` function which can be composed into a bigger web application.
///
let authorizeRequest (predicate : HttpContext -> bool) (authFailedHandler : HttpHandler) : HttpHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
(if predicate ctx then next else authFailedHandler finish) ctx

/// **Description**
///
/// Validates if a `ClaimsPrincipal` satisfies a certain condition. If the `policy` returns `true` then it will continue with the `next` function otherwise it will short circuit and execute the `authFailedHandler`.
///
/// **Parameters**
///
Expand All @@ -58,11 +76,26 @@ let signOut (authScheme : string) : HttpHandler =
///
/// A Giraffe `HttpHandler` function which can be composed into a bigger web application.
///
[<Obsolete("Please use `authorizeUser` as a replacement for `evaluateUserPolicy`. In the next major version this function will be removed.")>]
let evaluateUserPolicy (policy : ClaimsPrincipal -> bool) (authFailedHandler : HttpHandler) : HttpHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
if policy ctx.User
then next ctx
else authFailedHandler finish ctx
authorizeRequest
(fun ctx -> policy ctx.User)
authFailedHandler

/// **Description**
///
/// Validates if a `ClaimsPrincipal` satisfies a certain condition. If the `policy` returns `true` then it will continue with the `next` function otherwise it will short circuit and execute the `authFailedHandler`.
///
/// **Parameters**
///
/// - `policy`: One or many conditions which a `ClaimsPrincipal` must meet. The `policy` function should return `true` on success and `false` on failure.
/// - `authFailedHandler`: A `HttpHandler` function which will be executed when the `policy` returns `false`.
///
/// **Output**
///
/// A Giraffe `HttpHandler` function which can be composed into a bigger web application.
///
let authorizeUser = evaluateUserPolicy

/// **Description**
///
Expand All @@ -77,7 +110,7 @@ let evaluateUserPolicy (policy : ClaimsPrincipal -> bool) (authFailedHandler : H
/// A Giraffe `HttpHandler` function which can be composed into a bigger web application.
///
let requiresAuthentication (authFailedHandler : HttpHandler) : HttpHandler =
evaluateUserPolicy
authorizeUser
(fun user -> isNotNull user && user.Identity.IsAuthenticated)
authFailedHandler

Expand All @@ -95,7 +128,7 @@ let requiresAuthentication (authFailedHandler : HttpHandler) : HttpHandler =
/// A Giraffe `HttpHandler` function which can be composed into a bigger web application.
///
let requiresRole (role : string) (authFailedHandler : HttpHandler) : HttpHandler =
evaluateUserPolicy
authorizeUser
(fun user -> user.IsInRole role)
authFailedHandler

Expand All @@ -113,7 +146,7 @@ let requiresRole (role : string) (authFailedHandler : HttpHandler) : HttpHandler
/// A Giraffe `HttpHandler` function which can be composed into a bigger web application.
///
let requiresRoleOf (roles : string list) (authFailedHandler : HttpHandler) : HttpHandler =
evaluateUserPolicy
authorizeUser
(fun user -> List.exists user.IsInRole roles)
authFailedHandler

Expand Down
4 changes: 2 additions & 2 deletions src/Giraffe/Giraffe.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<!-- General -->
<AssemblyName>Giraffe</AssemblyName>
<Version>3.3.0</Version>
<Version>3.4.0</Version>
<Description>A native functional ASP.NET Core web framework for F# developers.</Description>
<Copyright>Copyright 2018 Dustin Moris Gorski</Copyright>
<Authors>Dustin Moris Gorski and contributors</Authors>
Expand Down Expand Up @@ -33,7 +33,7 @@
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<NoWarn>FS2003</NoWarn>
<NoWarn>FS2003;FS0044</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion tests/Giraffe.Tests/AuthTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ module TestApp =
let private mustBeOperatorOrAdmin = requiresRoleOf ["admin"; "operator"] accessDenied

let private isJohn (user : ClaimsPrincipal) = user.HasClaim (ClaimTypes.Name, "John")
let private mustBeJohn = evaluateUserPolicy isJohn accessDenied
let private mustBeJohn = authorizeUser isJohn accessDenied

let app =
GET >=> choose [
Expand Down

0 comments on commit 0320a47

Please sign in to comment.