src/foodog_ver.erl

-module(foodog_ver).

-export([exp/1, iss/2, key/2, fields/1]).

-spec fields(binary()) -> {ok, map()} | {error, any()}.
fields(Token) ->
    try jose_jwt:peek_payload(Token) of
        Result ->
            case Result of
                {jose_jwt, Payload} ->
                    {ok, Payload};
                _ ->
                    {error, invalid_jwt_format}
            end
    catch
        _:_ ->
            {error, decoding_error}
    end.

-spec key(binary(), binary()) -> {ok, map()} | {error, any()}.
key(Token, Key) ->
    try jose_jwt:verify_strict(
            foodog_util:binary_to_key(Key), [<<"HS256">>], Token)
    of
        Jwt ->
            case Jwt of
                {true, {jose_jwt, Fields}, _} ->
                    {ok, Fields};
                _ ->
                    {error, verification_failed}
            end
    catch
        _:_ ->
            {error, decoding_error}
    end.

-spec exp(map()) -> {ok, map()} | {error, token_expired}.
exp(#{<<"exp">> := ExpTime} = Payload) ->
    Now = erlang:system_time(second),
    case Now < ExpTime of
        true ->
            {ok, Payload};
        false ->
            {error, token_expired}
    end;
exp(Payload) ->
    {ok, Payload}.

-spec iss(map(), binary()) -> {ok, map()} | {error, invalid_issuer}.
iss(#{<<"iss">> := IssuerA} = Payload, IssuerB) ->
    case IssuerA == IssuerB of
        false ->
            {error, invalid_issuer};
        true ->
            {ok, Payload}
    end;
iss(Payload, _IssuerB) ->
    {ok, Payload}.

-ifdef(TEST).

-include_lib("eunit/include/eunit.hrl").

fields_test() ->
    Payload = #{<<"foobar">> => <<"barfoo">>},
    {ok, Token} = foodog_gen:token(Payload, <<"12345">>),
    {ok, Fields} = fields(Token),
    ?assertEqual(Payload, Fields).

iss_test() ->
    Payload = #{<<"foobar">> => <<"barfoo">>, <<"iss">> => <<"example.com">>},
    ?assertEqual({ok, Payload}, iss(Payload, <<"example.com">>)),
    ?assertEqual({error, invalid_issuer}, iss(Payload, <<"example2.com">>)).

-endif.