natskell-1.0.0.1: internal/Policy/Auth/Credentials.hs
{-# LANGUAGE OverloadedStrings #-}
module Auth.Credentials
( JwtBundle (..)
, parseJwtBundle
) where
import qualified Data.ByteString as BS
import Data.Word (Word8)
data JwtBundle = JwtBundle
{ jwtToken :: BS.ByteString
, jwtSeed :: BS.ByteString
}
deriving (Eq)
instance Show JwtBundle where
show _ = "JwtBundle {jwtToken = <redacted>, jwtSeed = <redacted>}"
parseJwtBundle :: BS.ByteString -> Maybe JwtBundle
parseJwtBundle input = do
jwt <- extractBlock jwtStart jwtEnd input
seed <- extractBlock seedStart seedEnd input
pure (JwtBundle jwt seed)
extractBlock :: BS.ByteString -> BS.ByteString -> BS.ByteString -> Maybe BS.ByteString
extractBlock startMarker endMarker input = do
let (_, rest) = BS.breakSubstring startMarker input
if BS.null rest
then Nothing
else do
let afterStart = BS.drop (BS.length startMarker) rest
(block, end) = BS.breakSubstring endMarker afterStart
trimmed = trimAscii block
if BS.null end || BS.null trimmed
then Nothing
else Just trimmed
jwtStart, jwtEnd, seedStart, seedEnd :: BS.ByteString
jwtStart = "-----BEGIN NATS USER JWT-----"
jwtEnd = "------END NATS USER JWT------"
seedStart = "-----BEGIN USER NKEY SEED-----"
seedEnd = "------END USER NKEY SEED------"
trimAscii :: BS.ByteString -> BS.ByteString
trimAscii =
dropWhileEndAscii isSpaceAscii . BS.dropWhile isSpaceAscii
dropWhileEndAscii :: (Word8 -> Bool) -> BS.ByteString -> BS.ByteString
dropWhileEndAscii predicate =
BS.reverse . BS.dropWhile predicate . BS.reverse
isSpaceAscii :: Word8 -> Bool
isSpaceAscii w =
w == 9 || w == 10 || w == 13 || w == 32