-module(gbr@shared@jwt). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src\\gbr\\shared\\jwt.gleam"). -export([to_string/1, get_payload_claim/3, get_issuer/1, get_subject/1, get_audience/1, get_jwt_id/1, get_issued_at/1, get_not_before/1, get_expiration/1, error/1, from_string/1]). -export_type([jwt/0, jwt_decode_error/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( "\n" " Jwt read only functions.\n" "\n" ). -opaque jwt() :: {jwt, binary(), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), gleam@dict:dict(binary(), gleam@dynamic:dynamic_())}. -type jwt_decode_error() :: token_empty | header_empty | header_invalid | payload_empty | payload_invalid | claim_empty | {claim_invalid, list(gleam@dynamic@decode:decode_error())}. -file("src\\gbr\\shared\\jwt.gleam", 49). ?DOC(" To string encoded jwt\n"). -spec to_string(jwt()) -> binary(). to_string(In) -> erlang:element(2, In). -file("src\\gbr\\shared\\jwt.gleam", 97). ?DOC(" Retrieve and decode a claim from a JWT's payload.\n"). -spec get_payload_claim(jwt(), binary(), gleam@dynamic@decode:decoder(FMZ)) -> {ok, FMZ} | {error, jwt_decode_error()}. get_payload_claim(Jwt, Claim, Decoder) -> gleam@result:'try'( begin _pipe = erlang:element(4, Jwt), _pipe@1 = gleam_stdlib:map_get(_pipe, Claim), gleam@result:replace_error(_pipe@1, claim_empty) end, fun(Claim_value) -> _pipe@2 = gleam@dynamic@decode:run(Claim_value, Decoder), gleam@result:map_error(_pipe@2, fun(E) -> {claim_invalid, E} end) end ). -file("src\\gbr\\shared\\jwt.gleam", 55). ?DOC(" Retrieve the iss from the JWT's payload.\n"). -spec get_issuer(jwt()) -> {ok, binary()} | {error, jwt_decode_error()}. get_issuer(Jwt) -> get_payload_claim( Jwt, <<"iss"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1} ). -file("src\\gbr\\shared\\jwt.gleam", 61). ?DOC(" Retrieve the sub from the JWT's payload.\n"). -spec get_subject(jwt()) -> {ok, binary()} | {error, jwt_decode_error()}. get_subject(Jwt) -> get_payload_claim( Jwt, <<"sub"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1} ). -file("src\\gbr\\shared\\jwt.gleam", 67). ?DOC(" Retrieve the aud from the JWT's payload.\n"). -spec get_audience(jwt()) -> {ok, binary()} | {error, jwt_decode_error()}. get_audience(Jwt) -> get_payload_claim( Jwt, <<"aud"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1} ). -file("src\\gbr\\shared\\jwt.gleam", 73). ?DOC(" Retrieve the jti from the JWT's payload.\n"). -spec get_jwt_id(jwt()) -> {ok, binary()} | {error, jwt_decode_error()}. get_jwt_id(Jwt) -> get_payload_claim( Jwt, <<"jti"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_string/1} ). -file("src\\gbr\\shared\\jwt.gleam", 79). ?DOC(" Retrieve the iat from the JWT's payload.\n"). -spec get_issued_at(jwt()) -> {ok, integer()} | {error, jwt_decode_error()}. get_issued_at(Jwt) -> get_payload_claim( Jwt, <<"iat"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_int/1} ). -file("src\\gbr\\shared\\jwt.gleam", 85). ?DOC(" Retrieve the nbf from the JWT's payload.\n"). -spec get_not_before(jwt()) -> {ok, integer()} | {error, jwt_decode_error()}. get_not_before(Jwt) -> get_payload_claim( Jwt, <<"nbf"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_int/1} ). -file("src\\gbr\\shared\\jwt.gleam", 91). ?DOC(" Retrieve the exp from the JWT's payload.\n"). -spec get_expiration(jwt()) -> {ok, integer()} | {error, jwt_decode_error()}. get_expiration(Jwt) -> get_payload_claim( Jwt, <<"exp"/utf8>>, {decoder, fun gleam@dynamic@decode:decode_int/1} ). -file("src\\gbr\\shared\\jwt.gleam", 112). -spec error(jwt_decode_error()) -> binary(). error(Err) -> case Err of token_empty -> <<"Token string is empty or null"/utf8>>; header_empty -> <<"Header is empty or null"/utf8>>; header_invalid -> <<"Header is invalid"/utf8>>; payload_empty -> <<"Payload is empty or null"/utf8>>; payload_invalid -> <<"Payload is invalid"/utf8>>; claim_empty -> <<"Claim is empty or null"/utf8>>; {claim_invalid, List_dec_error} -> Dec_errors = gleam@list:map( List_dec_error, fun(Dec_error) -> <<<<<<"Expected: "/utf8, (erlang:element(2, Dec_error))/binary>>/binary, "Found: "/utf8>>/binary, (erlang:element(3, Dec_error))/binary>> end ), <<"Claim is invalid: "/utf8, (gleam@string:join(Dec_errors, <<"\n"/utf8>>))/binary>> end. -file("src\\gbr\\shared\\jwt.gleam", 133). -spec parts(binary()) -> {ok, {gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), gleam@dict:dict(binary(), gleam@dynamic:dynamic_()), gleam@option:option(binary())}} | {error, jwt_decode_error()}. parts(Jwt_string) -> Parts = gleam@string:split(Jwt_string, <<"."/utf8>>), gleam@result:'try'( begin _pipe = gleam@list:first(Parts), gleam@result:replace_error(_pipe, header_empty) end, fun(Encoded_header) -> Parts@1 = gleam@list:drop(Parts, 1), gleam@result:'try'( begin _pipe@1 = Encoded_header, _pipe@2 = gleam@bit_array:base64_url_decode(_pipe@1), _pipe@3 = gleam@result:'try'( _pipe@2, fun gleam@bit_array:to_string/1 ), gleam@result:replace_error(_pipe@3, header_invalid) end, fun(Header_string) -> gleam@result:'try'( begin _pipe@4 = gleam@json:parse( Header_string, gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ), gleam@result:replace_error(_pipe@4, header_invalid) end, fun(Header) -> gleam@result:'try'( begin _pipe@5 = gleam@list:first(Parts@1), gleam@result:replace_error( _pipe@5, payload_empty ) end, fun(Encoded_payload) -> Parts@2 = gleam@list:drop(Parts@1, 1), gleam@result:'try'( begin _pipe@6 = Encoded_payload, _pipe@7 = gleam@bit_array:base64_url_decode( _pipe@6 ), _pipe@8 = gleam@result:'try'( _pipe@7, fun gleam@bit_array:to_string/1 ), gleam@result:replace_error( _pipe@8, payload_invalid ) end, fun(Payload_string) -> gleam@result:map( begin _pipe@9 = gleam@json:parse( Payload_string, gleam@dynamic@decode:dict( {decoder, fun gleam@dynamic@decode:decode_string/1}, {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ) ), gleam@result:replace_error( _pipe@9, payload_invalid ) end, fun(Payload) -> Signature = begin _pipe@10 = Parts@2, _pipe@11 = gleam@list:first( _pipe@10 ), gleam@option:from_result( _pipe@11 ) end, {Header, Payload, Signature} end ) end ) end ) end ) end ) end ). -file("src\\gbr\\shared\\jwt.gleam", 39). ?DOC(" From string encoded jwt\n"). -spec from_string(binary()) -> {ok, jwt()} | {error, jwt_decode_error()}. from_string(Raw) -> gleam@bool:guard( gleam@string:is_empty(Raw), {error, token_empty}, fun() -> gleam@result:map( parts(Raw), fun(_use0) -> {Header, Payload, _} = _use0, {jwt, Raw, Header, Payload} end ) end ).