simonh1000/elm-jwt/3.0.0

NOTE: this package is not compatible with Elm 0.19.1

Jwt

Helper functions for Jwt tokens.

This package provides functions for reading tokens, and for using them to make authenticated Http requests.

Token reading

decodeToken : Decoder a -> Token -> Result JwtError a

decodeToken parses the token, checking that it meets the Jwt standards.

decodeToken dec token

In the event of success, decodeToken returns an Elm record structure using the JSON Decoder.

isExpired : Time -> Token -> Result JwtError Bool

`Checks whether a token has expired, and returns True or False, or any error that occurred while decoding the token.

Note: This function assumes that the expiry was set in seconds and thus multiplies by 1000 to compare with Javascript time (in milliseconds). You may need to write a custom version if your server-side Jwt library works differently.

Authenticated Http requests

authenticate : (Result Error a -> msg) -> String -> Decoder a -> Value -> Cmd msg

authenticate is a standard Http POST method containing login credentials, and using a json decoder to extract the returned token.

submitCredentials : Model -> Cmd Msg
submitCredentials model =
    E.object
        [ ("username", E.string model.uname)
        , ("password", E.string model.pword)
        ]
    |> authenticate Auth "/sessions" tokenStringDecoder
createRequest : String -> Token -> String -> Decoder a -> Body -> Request a

createRequest creates a Http.Request with the token added to the headers, and sets the withCredentials field to True.

get : Token -> String -> Decoder a -> Request a

get is a replacement for Http.get that returns a Http.Request with the token attached the headers.

Task.perform
    PostFail PostSucess
    (get token dataDecoder "/api/data")
get_ : Token -> String -> Decoder a -> Task Never (Result JwtError a)

get_ takes the same parameters as get, but returns a Task where a 401 Unauthorized error due to token expiry has been converted into a TokenExpired.

update ... =
GetResult (Result.Err err) ->
    case err of
        Jwt.TokenExpired ->
            { model | msg = "Token expired" } ! []
        _ ->
            { model | msg = toString err } ! []


[...]
tryToken : String -> Cmd Msg
tryToken token =
    Jwt.get_ token "/api/data" dataDecoder
    |> Task.perform GetResult
post : (Result Error a -> msg) -> Token -> Decoder a -> String -> Body -> Cmd msg

post is a replacement for Http.post that attaches a provided Jwt token to the headers.

put : (Result Error a -> msg) -> Token -> Decoder a -> String -> Body -> Cmd msg

put provides Http.put with the token attached to the headers.

promote401 : Token -> Error -> Task Never (Result JwtError a)

Examines a 401 Unauthorized reponse, and converts the error to TokenExpired when that is the case.

getAuth : Token -> String -> Json.Decoder a -> Task Never (Result JwtError a)
getAuth token url dec =
    createRequest "GET" token url dec Http.emptyBody
    |> toTask
    |> Task.map Result.Ok
    |> Task.onError (promote401 token)

Errors

= HttpError Error
| TokenExpired
| TokenNotAccepted
| TokenProcessingError String
| TokenDecodeError String

We distinguish between various errors

  • From Http.Error. We pass these straight through unless using promote401,
  • 401 (Unauthorized) errors, due either to token expiry or some other reason
  • issues with processing (e.g. base 64 decoding) the token, and
  • problems decoding the json data within the content of the token