3 people like it.

Creating and validating JWTs in just 35 lines of F# code.

A fast and lightweight json web token (JWT) creator and validator.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
module JsonWebToken =
    open System
    open System.Text
    open System.Text.RegularExpressions
    open System.Security.Cryptography
    let replace (oldVal: string) (newVal: string) = fun (s: string) -> s.Replace(oldVal, newVal)
    let minify = 
        let regex = Regex("(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", RegexOptions.Compiled|||RegexOptions.CultureInvariant)
        fun s ->
            regex.Replace(s, "$1")
    let base64UrlEncode bytes =
        Convert.ToBase64String(bytes) |> replace "+" "-" |> replace "/" "_" |> replace "=" ""
    type IJwtAuthority =
        inherit IDisposable
        abstract member IssueToken: header:string -> payload:string -> string
        abstract member VerifyToken: string -> bool
    let newJwtAuthority (initAlg: byte array -> HMAC) key =
        let alg = initAlg(key)
        let encode = minify >> Encoding.UTF8.GetBytes >> base64UrlEncode
        let issue header payload =
            let parts = [header; payload] |> List.map encode |> String.concat "."
            let signature = parts |> Encoding.UTF8.GetBytes |> alg.ComputeHash |> base64UrlEncode
            [parts; signature] |> String.concat "."
        let verify (token: string) =
            let secondDot = token.LastIndexOf(".")
            let parts = token.Substring(0, secondDot)
            let signature = token.Substring(secondDot + 1)
            (parts |> Encoding.UTF8.GetBytes |> alg.ComputeHash |> base64UrlEncode) = signature

        {
            new IJwtAuthority with
                member this.IssueToken header payload = issue header payload
                member this.VerifyToken token = verify token
                member this.Dispose() = alg.Dispose()
        }

open System.Text
open System.Security.Cryptography
open JsonWebToken
let header = 
    """{
        "alg": "HS256",
        "typ": "JWT"
    }"""
let payload = 
    """{
        "sub": "1234567890",
        "name": "John Doe",
        "admin": true
    }"""
let encodedSecret = "secret" |> Encoding.UTF8.GetBytes
let testAuth = newJwtAuthority (fun key -> new HMACSHA256(key) :> HMAC) encodedSecret
let token = testAuth.IssueToken header payload
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
testAuth.VerifyToken token
testAuth.Dispose()
namespace System
namespace System.Text
namespace System.Text.RegularExpressions
namespace System.Security
namespace System.Security.Cryptography
val replace : oldVal:string -> newVal:string -> s:string -> string

Full name: Script.JsonWebToken.replace
val oldVal : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val newVal : string
val s : string
String.Replace(oldValue: string, newValue: string) : string
String.Replace(oldChar: char, newChar: char) : string
val minify : (string -> string)

Full name: Script.JsonWebToken.minify
val regex : Regex
Multiple items
type Regex =
  new : pattern:string -> Regex + 1 overload
  member GetGroupNames : unit -> string[]
  member GetGroupNumbers : unit -> int[]
  member GroupNameFromNumber : i:int -> string
  member GroupNumberFromName : name:string -> int
  member IsMatch : input:string -> bool + 1 overload
  member Match : input:string -> Match + 2 overloads
  member Matches : input:string -> MatchCollection + 1 overload
  member Options : RegexOptions
  member Replace : input:string * replacement:string -> string + 5 overloads
  ...

Full name: System.Text.RegularExpressions.Regex

--------------------
Regex(pattern: string) : unit
Regex(pattern: string, options: RegexOptions) : unit
type RegexOptions =
  | None = 0
  | IgnoreCase = 1
  | Multiline = 2
  | ExplicitCapture = 4
  | Compiled = 8
  | Singleline = 16
  | IgnorePatternWhitespace = 32
  | RightToLeft = 64
  | ECMAScript = 256
  | CultureInvariant = 512

Full name: System.Text.RegularExpressions.RegexOptions
field RegexOptions.Compiled = 8
field RegexOptions.CultureInvariant = 512
Regex.Replace(input: string, evaluator: MatchEvaluator) : string
Regex.Replace(input: string, replacement: string) : string
Regex.Replace(input: string, evaluator: MatchEvaluator, count: int) : string
Regex.Replace(input: string, replacement: string, count: int) : string
Regex.Replace(input: string, evaluator: MatchEvaluator, count: int, startat: int) : string
Regex.Replace(input: string, replacement: string, count: int, startat: int) : string
val base64UrlEncode : bytes:byte [] -> string

Full name: Script.JsonWebToken.base64UrlEncode
val bytes : byte []
type Convert =
  static val DBNull : obj
  static member ChangeType : value:obj * typeCode:TypeCode -> obj + 3 overloads
  static member FromBase64CharArray : inArray:char[] * offset:int * length:int -> byte[]
  static member FromBase64String : s:string -> byte[]
  static member GetTypeCode : value:obj -> TypeCode
  static member IsDBNull : value:obj -> bool
  static member ToBase64CharArray : inArray:byte[] * offsetIn:int * length:int * outArray:char[] * offsetOut:int -> int + 1 overload
  static member ToBase64String : inArray:byte[] -> string + 3 overloads
  static member ToBoolean : value:obj -> bool + 17 overloads
  static member ToByte : value:obj -> byte + 18 overloads
  ...

Full name: System.Convert
Convert.ToBase64String(inArray: byte []) : string
Convert.ToBase64String(inArray: byte [], options: Base64FormattingOptions) : string
Convert.ToBase64String(inArray: byte [], offset: int, length: int) : string
Convert.ToBase64String(inArray: byte [], offset: int, length: int, options: Base64FormattingOptions) : string
type IJwtAuthority =
  interface
    inherit IDisposable
    abstract member IssueToken : header:string -> payload:string -> string
    abstract member VerifyToken : string -> bool
  end

Full name: Script.JsonWebToken.IJwtAuthority
type IDisposable =
  member Dispose : unit -> unit

Full name: System.IDisposable
abstract member IJwtAuthority.IssueToken : header:string -> payload:string -> string

Full name: Script.JsonWebToken.IJwtAuthority.IssueToken
abstract member IJwtAuthority.VerifyToken : string -> bool

Full name: Script.JsonWebToken.IJwtAuthority.VerifyToken
type bool = Boolean

Full name: Microsoft.FSharp.Core.bool
val newJwtAuthority : initAlg:(byte array -> HMAC) -> key:byte array -> IJwtAuthority

Full name: Script.JsonWebToken.newJwtAuthority
val initAlg : (byte array -> HMAC)
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.byte

--------------------
type byte = Byte

Full name: Microsoft.FSharp.Core.byte
type 'T array = 'T []

Full name: Microsoft.FSharp.Core.array<_>
type HMAC =
  inherit KeyedHashAlgorithm
  member HashName : string with get, set
  member Initialize : unit -> unit
  member Key : byte[] with get, set
  static member Create : unit -> HMAC + 1 overload

Full name: System.Security.Cryptography.HMAC
val key : byte array
val alg : HMAC
val encode : (string -> string)
type Encoding =
  member BodyName : string
  member Clone : unit -> obj
  member CodePage : int
  member DecoderFallback : DecoderFallback with get, set
  member EncoderFallback : EncoderFallback with get, set
  member EncodingName : string
  member Equals : value:obj -> bool
  member GetByteCount : chars:char[] -> int + 3 overloads
  member GetBytes : chars:char[] -> byte[] + 5 overloads
  member GetCharCount : bytes:byte[] -> int + 2 overloads
  ...

Full name: System.Text.Encoding
property Encoding.UTF8: Encoding
Encoding.GetBytes(s: string) : byte []
Encoding.GetBytes(chars: char []) : byte []
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
Encoding.GetBytes(s: string, charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Encoding.GetBytes(chars: char [], charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
val issue : (string -> string -> string)
val header : string
val payload : string
val parts : string
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member GetSlice : startIndex:int option * endIndex:int option -> 'T list
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val map : mapping:('T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Encoding) : unit
val concat : sep:string -> strings:seq<string> -> string

Full name: Microsoft.FSharp.Core.String.concat
val signature : string
HashAlgorithm.ComputeHash(buffer: byte []) : byte []
HashAlgorithm.ComputeHash(inputStream: IO.Stream) : byte []
HashAlgorithm.ComputeHash(buffer: byte [], offset: int, count: int) : byte []
val verify : (string -> bool)
val token : string
val secondDot : int
String.LastIndexOf(value: string) : int
String.LastIndexOf(value: char) : int
String.LastIndexOf(value: string, comparisonType: StringComparison) : int
String.LastIndexOf(value: string, startIndex: int) : int
String.LastIndexOf(value: char, startIndex: int) : int
String.LastIndexOf(value: string, startIndex: int, comparisonType: StringComparison) : int
String.LastIndexOf(value: string, startIndex: int, count: int) : int
String.LastIndexOf(value: char, startIndex: int, count: int) : int
String.LastIndexOf(value: string, startIndex: int, count: int, comparisonType: StringComparison) : int
String.Substring(startIndex: int) : string
String.Substring(startIndex: int, length: int) : string
val this : IJwtAuthority
abstract member IJwtAuthority.IssueToken : header:string -> payload:string -> string
abstract member IJwtAuthority.VerifyToken : string -> bool
IDisposable.Dispose() : unit
HashAlgorithm.Dispose() : unit
module JsonWebToken

from Script
val header : string

Full name: Script.header
val payload : string

Full name: Script.payload
val encodedSecret : byte []

Full name: Script.encodedSecret
val testAuth : IJwtAuthority

Full name: Script.testAuth
Multiple items
type HMACSHA256 =
  inherit HMAC
  new : unit -> HMACSHA256 + 1 overload

Full name: System.Security.Cryptography.HMACSHA256

--------------------
HMACSHA256() : unit
HMACSHA256(key: byte []) : unit
val token : string

Full name: Script.token
System.IDisposable.Dispose() : unit
Raw view Test code New version

More information

Link:http://fssnip.net/7RK
Posted:7 years ago
Author:Sebastian Fialka
Tags: #web , #jwt , #security