3
3
4
4
-include (" jwt.hrl" ).
5
5
6
+ % %%------------------------------------------------------------------------
7
+ % %% External interface functions
8
+ % %%------------------------------------------------------------------------
9
+
6
10
encode (Algorithm , Payload , Secret ) ->
7
11
encode (Algorithm , Payload , Secret , []).
8
12
9
13
encode (Algorithm , Payload , Secret , HeaderExtra ) ->
10
14
AlgorithmName = atom_to_algorithm (Algorithm ),
11
- Header = jsx :encode ([{typ , <<" JWT" >>}, {alg , AlgorithmName }|HeaderExtra ]),
12
- PayloadJson = jsx :encode (Payload ),
13
- Signature = get_signature (Algorithm , PayloadJson , Secret ),
14
- Parts = [Header , PayloadJson , Signature ],
15
- EncodedParts = [base64url :encode (Item ) || Item <- Parts ],
16
- JwtData = bin_join (EncodedParts , <<" ." >>),
17
- {ok , JwtData }.
15
+ Header = jsx :encode ([{typ , <<" JWT" >>},
16
+ {alg , AlgorithmName } | HeaderExtra ]),
17
+ HeaderEncoded = base64url :encode (Header ),
18
+ PayloadEncoded = base64url :encode (jsx :encode (Payload )),
19
+ DataEncoded = <<HeaderEncoded /binary , $. , PayloadEncoded /binary >>,
20
+ Signature = get_signature (Algorithm , DataEncoded , Secret ),
21
+ SignatureEncoded = base64url :encode (Signature ),
22
+ {ok , <<DataEncoded /binary , $. , SignatureEncoded /binary >>}.
18
23
19
24
decode (Data , Secret ) when is_binary (Data ) ->
20
- Parts = binary :split (Data , [<<" ." >>], [global ]),
21
- try
22
- DecodedParts = [base64url :decode (Item ) || Item <- Parts ],
23
-
24
- if
25
- length (DecodedParts ) < 3 ->
26
- {error , badtoken };
27
- true ->
28
- [HeaderJson ,BodyRaw ,Signature |_Tail ] = DecodedParts ,
29
- Header = jsx :decode (HeaderJson ),
30
- AlgorithmStr = proplists :get_value (<<" alg" >>, Header ),
31
- Expiration = proplists :get_value (<<" exp" >>, Header , noexp ),
32
- Algorithm = algorithm_to_atom (AlgorithmStr ),
33
-
34
- Type = proplists :get_value (<<" typ" >>, Header ),
35
-
36
- ActualSignature = get_signature (Algorithm , BodyRaw , Secret ),
37
-
38
- Jwt = # jwt {typ = Type , body = BodyRaw , alg = Algorithm ,
39
- sig = Signature , actual_sig = ActualSignature },
40
-
41
- if
42
- Signature =:= ActualSignature ->
43
- % TODO: leeway
44
- NowSecs = now_secs (),
45
- if Expiration == noexp orelse Expiration > NowSecs ->
25
+ try binary :split (Data , [<<" ." >>], [global ]) of
26
+ [HeaderEncoded , PayloadEncoded , SignatureEncoded ] ->
27
+ Header = jsx :decode (base64url :decode (HeaderEncoded )),
28
+ Type = proplists :get_value (<<" typ" >>, Header ),
29
+ AlgorithmStr = proplists :get_value (<<" alg" >>, Header ),
30
+ Expiration = proplists :get_value (<<" exp" >>, Header , noexp ),
31
+ Algorithm = algorithm_to_atom (AlgorithmStr ),
32
+ DataEncoded = <<HeaderEncoded /binary , $. , PayloadEncoded /binary >>,
33
+ ActualSignature = get_signature (Algorithm , DataEncoded , Secret ),
34
+ Signature = base64url :decode (SignatureEncoded ),
35
+ Payload = jsx :decode (base64url :decode (PayloadEncoded )),
36
+ Jwt = # jwt {typ = Type , body = Payload , alg = Algorithm ,
37
+ sig = Signature , actual_sig = ActualSignature },
38
+ if
39
+ Signature =:= ActualSignature ->
40
+ % TODO: leeway
41
+ NowSecs = now_secs (),
42
+ if
43
+ Expiration == noexp orelse Expiration > NowSecs ->
46
44
{ok , Jwt };
47
- true ->
48
- {error , {expired , Expiration }}
49
- end ;
50
-
51
- true ->
52
- {error , {badsig , Jwt }}
53
- end
54
- end
55
- catch error :E ->
56
- {error , E }
45
+ true ->
46
+ {error , {expired , Expiration }}
47
+ end ;
48
+ true ->
49
+ {error , {badsig , Jwt }}
50
+ end ;
51
+ _ ->
52
+ {error , badtoken }
53
+ catch
54
+ error :E ->
55
+ {error , E }
57
56
end .
58
57
59
- % % private
60
-
61
- bin_join (Items , Sep ) ->
62
- lists :foldl (fun (Val , <<>>) -> Val ;
63
- (Val , Accum ) ->
64
- <<Accum /binary , Sep /binary , Val /binary >>
65
- end , <<>>, Items ).
58
+ % %%------------------------------------------------------------------------
59
+ % %% Private functions
60
+ % %%------------------------------------------------------------------------
66
61
67
62
algorithm_to_atom (<<" HS256" >>) -> hs256 ;
68
63
algorithm_to_atom (<<" HS384" >>) -> hs384 ;
@@ -78,7 +73,7 @@ algorithm_to_crypto_algorithm(hs512) -> sha512.
78
73
79
74
get_signature (Algorithm , Data , Secret ) ->
80
75
CryptoAlg = algorithm_to_crypto_algorithm (Algorithm ),
81
- crypto :hmac (CryptoAlg , Data , Secret ).
76
+ crypto :hmac (CryptoAlg , Secret , Data ).
82
77
83
78
now_secs () ->
84
79
{MegaSecs , Secs , _MicroSecs } = os :timestamp (),
0 commit comments