JSON web tokens in OCaml
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Thomas Gazagnaire. All rights reserved.
3 SPDX-License-Identifier: MIT
4 ---------------------------------------------------------------------------*)
5
6(* Crowbar-based fuzz testing for JWT parsing *)
7
8open Crowbar
9
10(* Test that JWT parsing never crashes on arbitrary input *)
11let test_parse_no_crash input =
12 let _ = Jsonwt.parse input in
13 ()
14
15(* Test that JWT parsing in unsafe mode never crashes *)
16let test_parse_unsafe_no_crash input =
17 let _ = Jsonwt.parse_unsafe input in
18 ()
19
20(* Test that nested JWT parsing never crashes *)
21let test_parse_nested_no_crash input =
22 let _ = Jsonwt.parse_nested input in
23 ()
24
25(* Test header parsing never crashes *)
26let test_header_parse_no_crash input =
27 let _ = Jsonwt.Header.of_json input in
28 ()
29
30(* Test claims parsing never crashes *)
31let test_claims_parse_no_crash input =
32 let _ = Jsonwt.Claims.of_json input in
33 ()
34
35(* Test JWK parsing never crashes *)
36let test_jwk_parse_no_crash input =
37 let _ = Jsonwt.Jwk.of_json input in
38 ()
39
40(* Test algorithm parsing never crashes *)
41let test_algorithm_parse_no_crash input =
42 let _ = Jsonwt.Algorithm.of_string input in
43 ()
44
45(* Test base64url-like inputs (dots are JWT separators) *)
46let test_jwt_structure input1 input2 input3 =
47 let token = input1 ^ "." ^ input2 ^ "." ^ input3 in
48 let _ = Jsonwt.parse token in
49 ()
50
51(* Test error printing never crashes *)
52let () =
53 let errors =
54 [
55 Jsonwt.Invalid_json "test";
56 Jsonwt.Invalid_base64url "test";
57 Jsonwt.Invalid_structure "test";
58 Jsonwt.Invalid_header "test";
59 Jsonwt.Invalid_claims "test";
60 Jsonwt.Invalid_uri "test";
61 Jsonwt.Duplicate_claim "test";
62 Jsonwt.Unsupported_algorithm "test";
63 Jsonwt.Algorithm_not_allowed "test";
64 Jsonwt.Signature_mismatch;
65 Jsonwt.Token_expired;
66 Jsonwt.Token_not_yet_valid;
67 Jsonwt.Invalid_issuer;
68 Jsonwt.Invalid_audience;
69 Jsonwt.Key_type_mismatch "test";
70 Jsonwt.Unsecured_not_allowed;
71 Jsonwt.Nesting_too_deep;
72 ]
73 in
74 List.iter
75 (fun e ->
76 let _ = Format.asprintf "%a" Jsonwt.pp_error e in
77 let _ = Jsonwt.error_to_string e in
78 ())
79 errors
80
81let () =
82 add_test ~name:"jwt: parse no crash" [ bytes ] test_parse_no_crash;
83 add_test ~name:"jwt: parse_unsafe no crash" [ bytes ]
84 test_parse_unsafe_no_crash;
85 add_test ~name:"jwt: parse_nested no crash" [ bytes ]
86 test_parse_nested_no_crash;
87 add_test ~name:"jwt: header parse no crash" [ bytes ]
88 test_header_parse_no_crash;
89 add_test ~name:"jwt: claims parse no crash" [ bytes ]
90 test_claims_parse_no_crash;
91 add_test ~name:"jwt: jwk parse no crash" [ bytes ] test_jwk_parse_no_crash;
92 add_test ~name:"jwt: algorithm parse no crash" [ bytes ]
93 test_algorithm_parse_no_crash;
94 add_test ~name:"jwt: structured input" [ bytes; bytes; bytes ]
95 test_jwt_structure