Skip to content

Instantly share code, notes, and snippets.

@sebfia
Created January 18, 2017 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sebfia/832c9f76a4ffa064f88e876a4a1a7c4b to your computer and use it in GitHub Desktop.
Save sebfia/832c9f76a4ffa064f88e876a4a1a7c4b to your computer and use it in GitHub Desktop.
Creating and validating JWTs in just 35 lines of F# code.
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()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment