JWT and CWT Implementation TODO#
RFC 7519 (JWT) and RFC 8392 (CWT) compliance tracking for jsonwt.
Implementation Status#
JSON Web Token (JWT) - RFC 7519#
- Type definitions for all registered claims
- Type definitions for JOSE header parameters
- Type definitions for algorithms
- Base64url encoding/decoding
- Basic JWT structure parsing (3-part split)
- JSON parsing with jsont
- Signature creation and verification (HMAC, ECDSA, EdDSA)
- Claims validation
- JWK parsing and serialization
- Structured error types
- Comprehensive tests (30 tests passing)
CBOR Web Token (CWT) - RFC 8392#
- Type definitions for COSE algorithms (HMAC, ECDSA, EdDSA)
- Type definitions for COSE keys (Symmetric, Ec2, Okp)
- Claims with integer keys (1=iss, 2=sub, 3=aud, 4=exp, 5=nbf, 6=iat, 7=cti)
- CBOR encoding via cbort library
- COSE_Mac0 structure (MACed CWT)
- COSE_Sign1 structure (Signed CWT)
- Signature creation and verification (HMAC, ECDSA, EdDSA)
- Claims validation (same as JWT)
- Structured error types
- Comprehensive tests (28 tests passing)
CBOR Codec - RFC 8949#
- Low-level CBOR encoding primitives (Cbor_rw)
- Major type constants and encoding functions
- Integer encoding (positive and negative)
- Float encoding (IEEE 754 double precision)
- Text string and byte string encoding
- Array and map encoding
- Tag encoding
- Simple value encoding (false, true, null, undefined)
- Comprehensive tests with RFC 8949 Appendix A vectors (46 tests passing)
Completed Phases#
Phase 0: Error Types and Core Infrastructure - DONE#
- Structured error type with all RFC-compliant variants
-
pp_erroranderror_to_stringfunctions - StringOrURI validation (validates URIs per RFC 3986)
Phase 1: JSON Parsing with jsont - DONE#
- Header JSON codec (
Header.of_json,Header.to_json) - Claims JSON codec with strict mode for duplicate detection
- JWK JSON codec for all key types (Oct, RSA, EC, OKP)
Phase 2: Signature Operations - PARTIALLY DONE#
- HMAC Signatures (HS256, HS384, HS512) - using digestif
- ECDSA Signatures (ES256, ES384, ES512) - using mirage-crypto-ec
- EdDSA Signatures (Ed25519) - using mirage-crypto-ec
- Unsecured JWT ("none") - with explicit
~allow_none:trueopt-in - Nested JWT Support -
parse_nestedwith max_depth protection - RSA Signatures (RS256, RS384, RS512) - STUBBED, needs JWK-to-RSA key parsing
Phase 3: Claims Validation - DONE#
- Time-based claims (exp, nbf) with leeway support
- Issuer validation (iss)
- Audience validation (aud)
-
is_expiredhelper function -
time_to_expiryhelper function
Phase 4: Full JWT Creation Flow - DONE#
-
createfunction for signing JWTs - Algorithm/key type validation
Phase 5: Tests - DONE (104 tests passing)#
JWT Tests (30 tests)#
RFC Test Vectors:
- RFC 7519 Section 3.1 HS256 JWT
- RFC 7519 Section 6.1 Unsecured JWT
Algorithm Coverage:
- HS256 sign/verify
- HS384 sign/verify
- HS512 sign/verify
- RS256 sign/verify (stubbed)
- RS384 sign/verify (stubbed)
- RS512 sign/verify (stubbed)
- ES256 sign/verify
- ES384 sign/verify
- ES512 sign/verify
- EdDSA sign/verify
- none (unsecured) with opt-in
Validation Tests:
- Expired token rejection
- Not-yet-valid token rejection
- Issuer mismatch rejection
- Audience mismatch rejection
- Leeway handling
Error Cases:
- Invalid base64url
- Invalid JSON
- Wrong number of parts
- Signature mismatch
- Algorithm not in allowed list
- Unsecured JWT without allow_none
CWT Tests (28 tests)#
RFC Test Vectors:
- RFC 8392 Appendix A claims timestamps
- RFC 8392 example values (hex test vectors)
Algorithm Coverage:
- HMAC_256_64 (alg=4)
- HMAC_256 (alg=5)
- HMAC_384 (alg=6)
- HMAC_512 (alg=7)
- ES256 (alg=-7)
- ES384 (alg=-35)
- ES512 (alg=-36)
- EdDSA (alg=-8)
COSE Key Tests:
- Symmetric key creation
- Ed25519 key creation
- P-256 key creation
- Key ID (kid) support
Claims Tests:
- Claims builder
- Timestamp claims (exp, nbf, iat)
- Single and multiple audience
- CWT ID (cti)
- CBOR serialization
Validation Tests:
- Expired token rejection
- Not-yet-valid token rejection
- Issuer validation
- Audience validation
- Leeway handling
CBOR Tests (46 tests)#
RFC 8949 Appendix A Test Vectors:
- Unsigned integers (0-1000000000000)
- Negative integers (-1 to -1000)
- Booleans and null
- Floats (1.0, 1.1, -4.1, 1.0e+300, Infinity, NaN)
- Text strings (empty, ASCII, UTF-8 with Unicode)
- Byte strings
- Arrays (empty, nested, 25 items)
- Maps (empty, int keys, string keys, nested)
- Tags (epoch timestamp)
- Constants (major types, simple values, additional info)
Remaining Work#
JWT: RSA Signatures (RS256, RS384, RS512)#
Status: Stubbed - returns Key_type_mismatch "RSA signing/verification not yet implemented"
Required:
- Implement JWK-to-RSA key parsing for
n,e(public) andd,p,q,dp,dq,qi(private) fields - Use
mirage-crypto-pkfor RSASSA-PKCS1-v1_5 signatures - Add tests with RFC test vectors
CWT: CBOR Decoding#
Status: Not implemented - current implementation only encodes CWTs
Required:
- Add CBOR decoding functions to Cbor_rw module
- Implement
Cwt.parseto decode CWT from CBOR bytes - Add tests with RFC 8392 Appendix A encoded test vectors
CWT: COSE Key Encoding/Decoding#
Status: Keys are created in memory but not serialized
Required:
- Add
Cose_key.to_cborandCose_key.of_cborfunctions - Follow RFC 9052 Section 7 (COSE Key) format
- Add tests with RFC test vectors
CWT: CWT Tag Support#
Status: Partial - encodes COSE structures but not outer CWT tag
Required:
- Add support for CWT tag (61) wrapping per RFC 8392 Section 2
- Add support for optional outer COSE tag per RFC 9052
Future Work (Not in Current Scope)#
-
JWK Set (JWKS): RFC 7517 Section 5 support for multiple keys
- Useful for key rotation and fetching keys from JWKS endpoints
- Example:
/.well-known/jwks.json - Consider adding
Jwks.ttype andJwks.find_key : kid:string -> Jwks.t -> Jwk.t option
-
JWE Support: RFC 7516 JSON Web Encryption
- Required for encrypted JWTs (as opposed to signed JWTs)
- Lower priority unless needed for specific use cases
Design Decisions (Implemented)#
-
StringOrURI validation: YES - Validates that
iss/subvalues containing ":" are valid URIs per RFC 3986. -
Duplicate claims: STRICT MODE - Rejects JWTs with duplicate claim names by default.
~strict:falseallows lenient parsing. -
"none" algorithm: REQUIRE OPT-IN -
~allow_none:boolparameter toverify(default false). Unsecured JWTs rejected unless explicitly allowed. -
Error types: STRUCTURED - Proper error variant type for pattern matching and error handling.
-
Algorithm allowlist: YES -
~allowed_algsparameter toverify, defaulting to all algorithms (except none). -
Clock source: EXPLICIT - Always requires
~now:Ptime.tparameter. No implicit system clock usage. -
Nested JWTs: YES - Support via
parse_nestedwith~max_depthprotection (default 2).
File Summary#
| File | Lines | Description |
|---|---|---|
lib/jsonwt.ml |
~1010 | JWT implementation |
lib/jsonwt.mli |
~480 | JWT interface with RFC documentation |
lib/cwt.ml |
~760 | CWT implementation |
lib/cwt.mli |
~400 | CWT interface with RFC documentation |
cbort/cbor_rw.ml |
~200 | Low-level CBOR encoding primitives |
cbort/cbor_rw.mli |
~200 | CBOR encoding interface |
cbort/cbort.ml |
~300 | CBOR codec for jsont types |
cbort/cbort.mli |
~100 | CBOR codec interface |
test/test_jsonwt.ml |
~440 | 30 JWT tests |
test/test_cwt.ml |
~500 | 28 CWT tests |
test/test_cbor.ml |
~320 | 46 CBOR encoding tests |
References#
JWT (JSON Web Token)#
- RFC 7519 - JSON Web Token (JWT)
- RFC 7515 - JSON Web Signature (JWS)
- RFC 7517 - JSON Web Key (JWK)
- RFC 7518 - JSON Web Algorithms (JWA)
- RFC 8037 - CFRG Elliptic Curve (EdDSA)