|
26 | 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27 | 27 | */
|
28 | 28 |
|
29 |
| -:- module(jwt_io, [jwt_encode/3, jwt_decode/3]). |
| 29 | +:- module(jwt_io, [jwt_encode/3, jwt_decode/3, jwt_decode_head/2]). |
30 | 30 | /** <module> Json Web Tokens implementation
|
31 | 31 |
|
32 | 32 | Generates and verifies Json Web Tokens.
|
|
44 | 44 | * =kid=: key id for identifying the key to use
|
45 | 45 | * =type=: type of the key, one of HMAC, RSA or ECDSA.
|
46 | 46 | * =algorithm=: algorithm to use, one of HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384 or ES512.
|
47 |
| - * =key=: private key to use - string for HMAC, private key file for RSA and private PEM file for ECDSA. |
| 47 | + * =key=: private key to use - string for HMAC, private key file for RSA and private PEM file for ECDSA. Optional for decoding, mandatory for encoding. |
48 | 48 | * =public_key=: public key to use - irrelevant for HMAC, public key file for RSA and public PEM file for ECDSA.
|
49 | 49 |
|
50 | 50 | RSA keys can be generated by:
|
|
102 | 102 | claims_with_aud(Claims, ClaimsWithAud),
|
103 | 103 | claims_with_iat(ClaimsWithAud, ClaimsWithIat),
|
104 | 104 | claims_with_iss(ClaimsWithIat, Key, ClaimsWithIss),
|
105 |
| - ClaimsNew = ClaimsWithIss.put(_{kid: Kid, jti: Jti}), |
| 105 | + ClaimsNew = ClaimsWithIss.put(_{jti: Jti}), |
106 | 106 | atom_json_dict(Data,ClaimsNew,[as(atom)]),
|
107 |
| - jwt_encode_from_string(Data, Token, Key.key, Key.algorithm). |
| 107 | + jwt_encode_from_string(Data, Token, Key.key, Key.algorithm, Kid). |
108 | 108 |
|
109 | 109 | %! jwt_decode(+Data: atom, -Payload:dict, +Options:options) is semidet
|
110 | 110 | %
|
|
126 | 126 | % @arg Options options
|
127 | 127 | %
|
128 | 128 | jwt_decode(Data, Payload, Options) :-
|
129 |
| - jwt_decode_from_string(Data, PayloadFirst, _, ''), |
130 |
| - atom_json_dict(PayloadFirst, PayloadDict, [as(string)]), |
131 |
| - atom_string(Kid, PayloadDict.kid), |
| 129 | + jwt_decode_head(Data, PayloadFirst), |
| 130 | + atom_json_dict(PayloadFirst, PayloadHeader, [as(string)]), |
| 131 | + atom_string(Kid, PayloadHeader.kid), |
132 | 132 | get_key_from_settings(Kid, KeyDict),
|
133 | 133 | jwt_decode_from_string(Data, Payload, KeyDict),
|
| 134 | + atom_json_dict(Payload, PayloadDict, [as(string)]), |
134 | 135 | jwt_jti_valid(PayloadDict),
|
135 | 136 | jwt_exp_valid(PayloadDict),
|
136 | 137 | jwt_nbf_valid(PayloadDict),
|
137 | 138 | jwt_iss_valid(PayloadDict, Options),
|
138 | 139 | jwt_aud_valid(PayloadDict, Options),
|
139 | 140 | jwt_iat_valid(PayloadDict).
|
140 | 141 |
|
| 142 | +jwt_decode_head(Data, Payload) :- |
| 143 | + jwt_parse_head(Data, Payload). |
| 144 | + |
141 | 145 | get_jti(Jti) :-
|
142 | 146 | setting(jti_generator, Generator),
|
143 | 147 | call(Generator, Jti).
|
|
203 | 207 |
|
204 | 208 | jwt_decode_from_string(Data, Payload, Key) :-
|
205 | 209 | member(Key.type, ['RSA', 'ECDSA']),
|
| 210 | + !, |
206 | 211 | jwt_decode_from_string(Data, Payload, Key.algorithm, Key.public_key),
|
207 | 212 | !.
|
208 | 213 |
|
|
268 | 273 | !.
|
269 | 274 | read_key_file(Key,KeyRead) :-
|
270 | 275 | member(Key.type, ['RSA', 'ECDSA']),
|
271 |
| - read_file_to_string(Key.key, KeyStr, []), |
| 276 | + get_dict('key', Key, PrivateKeyFile), |
| 277 | + !, |
| 278 | + read_file_to_string(PrivateKeyFile, KeyStr, []), |
272 | 279 | read_file_to_string(Key.public_key, PublicKeyStr, []),
|
273 | 280 | atom_string(KeyAtom, KeyStr),
|
274 | 281 | atom_string(PublicKeyAtom, PublicKeyStr),
|
275 | 282 | KeyRead = Key.put(_{key: KeyAtom, public_key: PublicKeyAtom}),
|
276 | 283 | !.
|
| 284 | +read_key_file(Key, KeyRead) :- |
| 285 | + member(Key.type, ['RSA', 'ECDSA']), |
| 286 | + read_file_to_string(Key.public_key, PublicKeyStr, []), |
| 287 | + atom_string(PublicKeyAtom, PublicKeyStr), |
| 288 | + KeyRead = Key.put(_{public_key: PublicKeyAtom}), |
| 289 | + !. |
| 290 | + |
277 | 291 |
|
278 | 292 | get_key_file(File, Key) :-
|
279 | 293 | read_file_to_string(File, KeyStr, []),
|
|
0 commit comments