Skip to content

Commit 95a5cef

Browse files
committed
fix: better JWT claims and headers type handling - docs
1 parent 5515c40 commit 95a5cef

File tree

2 files changed

+132
-17
lines changed

2 files changed

+132
-17
lines changed

docs/API_CHEATSHEET.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,63 @@ The following algorithms are supported for Digest Authentication:
185185
| DigestAlgorithm::MD5_SESS | MD5-sess variant with client nonce (RFC 2617) |
186186
| DigestAlgorithm::SHA256 | SHA-256 algorithm (RFC 7616) |
187187
| DigestAlgorithm::SHA256_SESS | SHA-256-sess variant with client nonce (RFC 7616) |
188+
189+
## JWT Validation Rules
190+
191+
### Headers
192+
JWT headers must contain simple scalar values (strings, numbers, booleans):
193+
194+
```php
195+
// ✅ Valid header values
196+
$jwt->header('kid', 'key-123'); // string
197+
$jwt->header('version', 1); // integer
198+
$jwt->header('debug', true); // boolean
199+
$jwt->header('rate', 1.5); // float
200+
201+
// ❌ Invalid header values (will throw InvalidArgumentException)
202+
$jwt->header('metadata', ['key' => 'value']); // array not allowed
203+
$jwt->header('config', new stdClass()); // object not allowed
204+
205+
// ℹ️ Null values are ignored (header won't be added)
206+
$jwt->header('optional', null); // No error, but header is skipped
207+
```
208+
209+
### Claims (Payload)
210+
JWT claims can contain complex data structures as long as they're JSON serializable:
211+
212+
```php
213+
// ✅ Valid claim values
214+
$jwt->claim('user_id', 123); // scalar values
215+
$jwt->claim('roles', ['admin', 'user']); // arrays
216+
$jwt->claim('profile', [ // nested objects
217+
'name' => 'John Doe',
218+
'settings' => ['theme' => 'dark']
219+
]);
220+
$jwt->claim('permissions', [
221+
'read' => true,
222+
'write' => false,
223+
'admin' => ['users', 'settings']
224+
]);
225+
226+
// ❌ Invalid claim values (will throw InvalidArgumentException)
227+
$jwt->claim('resource', fopen('file.txt', 'r')); // resources not allowed
228+
$jwt->claim('callback', function() {}); // closures not allowed
229+
```
230+
231+
## RFC Compliance
232+
233+
The validation rules ensure compliance with JWT standards:
234+
235+
- **Headers (RFC 7515)**: Scalar values only - ensures interoperability
236+
- **Claims (RFC 7519)**: Any JSON data - supports standard and custom claims
237+
- **Standard claims**: `iss`, `sub`, `aud`, `exp`, `iat`, `nbf`, `jti` are properly handled
238+
239+
```php
240+
// RFC-compliant JWT
241+
$jwt = AuthGenerator::jwt()
242+
->claim('iss', 'https://app.com') // Standard issuer claim
243+
->claim('aud', ['api', 'web']) // Audience can be array (RFC 7519)
244+
->claim('custom', ['data' => 'ok']) // Custom claims support objects
245+
->header('kid', 'key-1') // Header values are strings
246+
->toString();
247+
```

docs/USER_GUIDE.md

Lines changed: 72 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -234,32 +234,87 @@ $token = AuthGenerator::jwt()
234234
->toString();
235235
```
236236

237-
### Supported Algorithms
237+
### Working with Complex Data
238238

239-
The library supports various algorithms for JWT signing:
239+
JWT claims can contain complex nested data structures:
240240

241241
```php
242-
use Chr15k\AuthGenerator\Enums\Algorithm;
242+
$token = AuthGenerator::jwt()
243+
->key('secret-key')
244+
->claim('user', [
245+
'id' => 123,
246+
'name' => 'John Doe',
247+
'roles' => ['admin', 'user'],
248+
'permissions' => [
249+
'read' => true,
250+
'write' => true,
251+
'admin' => ['users', 'settings']
252+
]
253+
])
254+
->claim('metadata', [
255+
'ip' => '192.168.1.1',
256+
'device' => 'mobile',
257+
'location' => ['city' => 'New York', 'country' => 'US']
258+
])
259+
->toString();
260+
```
243261

244-
// HMAC algorithms
245-
$token = AuthGenerator::jwt()->algorithm(Algorithm::HS256)->toString(); // HMAC with SHA-256
246-
$token = AuthGenerator::jwt()->algorithm(Algorithm::HS384)->toString(); // HMAC with SHA-384
247-
$token = AuthGenerator::jwt()->algorithm(Algorithm::HS512)->toString(); // HMAC with SHA-512
262+
### Data Type Rules
248263

249-
// RSA algorithms
250-
$token = AuthGenerator::jwt()->algorithm(Algorithm::RS256)->toString(); // RSA with SHA-256
251-
$token = AuthGenerator::jwt()->algorithm(Algorithm::RS384)->toString(); // RSA with SHA-384
252-
$token = AuthGenerator::jwt()->algorithm(Algorithm::RS512)->toString(); // RSA with SHA-512
264+
The library enforces different validation rules for headers vs claims:
253265

254-
// ECDSA algorithms
255-
$token = AuthGenerator::jwt()->algorithm(Algorithm::ES256)->toString(); // ECDSA with P-256 and SHA-256
256-
$token = AuthGenerator::jwt()->algorithm(Algorithm::ES384)->toString(); // ECDSA with P-384 and SHA-384
257-
$token = AuthGenerator::jwt()->algorithm(Algorithm::ES256K)->toString(); // ECDSA with secp256k1 and SHA-256
266+
**Headers** - Must be scalar values (strings, numbers, booleans):
267+
```php
268+
$jwt->header('kid', 'key-123'); // ✅ String
269+
$jwt->header('version', 1); // ✅ Integer
270+
$jwt->header('debug', true); // ✅ Boolean
271+
$jwt->header('invalid', []); // ❌ Arrays not allowed
272+
$jwt->header('optional', null); // ℹ️ Null values are ignored
273+
```
258274

259-
// Edwards-curve Digital Signature Algorithm
260-
$token = AuthGenerator::jwt()->algorithm(Algorithm::EdDSA)->toString(); // EdDSA
275+
**Claims** - Can be any JSON-serializable data:
276+
```php
277+
$jwt->claim('simple', 123); // ✅ Scalar values
278+
$jwt->claim('array', [1, 2, 3]); // ✅ Arrays
279+
$jwt->claim('nested', ['a' => ['b' => 'c']]); // ✅ Nested structures
280+
$jwt->claim('invalid', fopen('file', 'r')); // ❌ Resources not allowed
261281
```
262282

283+
### Validation Alignment with RFC Standards
284+
285+
The library's validation rules are designed to ensure compliance with JWT standards:
286+
287+
**RFC 7515 (JSON Web Signature) - Headers:**
288+
- Headers contain algorithm parameters and metadata for token processing
289+
- Values should be simple strings or numbers for interoperability
290+
- Complex data structures in headers can cause compatibility issues with other JWT libraries
291+
- Our validation enforces scalar types (strings, numbers, booleans) to maintain standard compliance
292+
293+
**RFC 7519 (JSON Web Token) - Claims:**
294+
- Claims are designed to convey assertions about an entity (typically the user)
295+
- The payload can contain any valid JSON data structure
296+
- Standard claims like `iss`, `sub`, `aud` can be strings or arrays
297+
- Custom claims can be any JSON-serializable data to support application-specific requirements
298+
- Our validation allows complex data structures while preventing non-serializable types
299+
300+
**Example of RFC-compliant usage:**
301+
```php
302+
$jwt = AuthGenerator::jwt()
303+
->key('secret-key')
304+
// RFC 7519 standard claims
305+
->claim('iss', 'https://myapp.com') // Issuer (string)
306+
->claim('sub', 'user-123') // Subject (string)
307+
->claim('aud', ['api', 'mobile']) // Audience (string or array)
308+
->claim('exp', time() + 3600) // Expiration (number)
309+
->claim('iat', time()) // Issued at (number)
310+
// Custom claims with complex data (RFC compliant)
311+
->claim('permissions', ['read', 'write']) // Array
312+
->claim('profile', ['name' => 'John']) // Object
313+
// RFC 7515 compliant headers
314+
->header('kid', 'key-id-123') // Key ID (string)
315+
->header('typ', 'JWT') // Type (string)
316+
->toString();
317+
```
263318
## HTTP Headers
264319

265320
The library provides helper methods to format tokens for use in HTTP headers.

0 commit comments

Comments
 (0)