This commit is contained in:
Daniel J. Summers 2020-11-17 20:07:28 -05:00
parent db40a5cffd
commit 167b8b7bb4
3 changed files with 41 additions and 6 deletions

View File

@ -12,13 +12,14 @@ type FSharpJsonSerializer () =
Json.deserialize<'T> json Json.deserialize<'T> json
open Data
open Domain
open JWT.Algorithms
open JWT.Builder
open System
open System.Net.Http open System.Net.Http
open System.Net.Http.Headers open System.Net.Http.Headers
open Data open JWT.Exceptions
open JWT.Builder
open JobsJobsJobs.Api.Domain
open JWT.Algorithms
open System
/// Verify a user's credentials with No Agenda Social /// Verify a user's credentials with No Agenda Social
let verifyWithMastodon accessToken = async { let verifyWithMastodon accessToken = async {
@ -53,3 +54,18 @@ let createJwt citizenId = async {
| Ok None -> return Error (exn "Citizen record not found") | Ok None -> return Error (exn "Citizen record not found")
| Error exn -> return Error exn | Error exn -> return Error exn
} }
/// Validate the given token
let validateJwt token =
try
let paylod =
JwtBuilder()
.WithAlgorithm(HMACSHA256Algorithm ())
// TODO: generate separate secret for server
.WithSecret(config.auth.secret)
.MustVerifySignature()
.Decode<Map<string, obj>> token
CitizenId.tryParse (paylod.["sub"] :?> string)
with
| :? TokenExpiredException -> Error "Token is expired"
| :? SignatureVerificationException -> Error "Invalid token signature"

View File

@ -12,11 +12,29 @@ module private Internal =
open Suave.Writers open Suave.Writers
/// Read the JWT and get the authorized user ID
let authorizedUser : WebPart =
fun ctx ->
match ctx.request.header "Authorization" with
| Choice1Of2 bearer ->
let token = (bearer.Split " ").[1]
match Auth.validateJwt token with
| Ok citizenId ->
setUserData "citizenId" citizenId ctx
| Error err ->
RequestErrors.BAD_REQUEST err ctx
| Choice2Of2 _ ->
RequestErrors.BAD_REQUEST "Authorization header must be specified" ctx
/// Send a JSON response /// Send a JSON response
let json x = let json x =
Successful.OK (Json.serialize x) Successful.OK (Json.serialize x)
>=> setMimeType "application/json; charset=utf-8" >=> setMimeType "application/json; charset=utf-8"
/// Get the current citizen ID from the context
let currentCitizenId ctx =
ctx.userState.["citizenId"] :?> CitizenId
/// Handler to return the Vue application /// Handler to return the Vue application
module Vue = module Vue =

View File

@ -2,7 +2,8 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<LangVersion>preview</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>