first commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# token-issuer
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Issues signed JWTs with per-tenant claims using the `jose` library. The `TokenIssuer` class wraps `SignJWT` with tenant-aware defaults: it injects `tenant_id`, `session_id`, `domains`, `role`, and `permissions` claims alongside standard `sub`, `iat`, `exp`, and `jti`. An injectable `Clock` makes token timestamps deterministic for unit tests. Duration strings like `"1h"` are parsed to seconds for `exp` computation.
|
||||
|
||||
## Features
|
||||
|
||||
- `TokenIssuer` class with configurable issuer, default expiry, and injectable clock
|
||||
- `createToken(keyPair, options)` — signs a JWT with tenant claims
|
||||
- `createTokenIssuer(config)` — factory function
|
||||
- `signToken(keyPair, options, config?)` — standalone convenience function
|
||||
- Duration string parsing: `"1h"`, `"15m"`, `"30s"`, `"2d"`, `"500ms"`
|
||||
- Standard `jti` (UUID), `iat`, `exp`, `sub`, `iss` claim population
|
||||
- Optional `additionalClaims` spread for domain-specific payloads
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { generateKeyPair } from "@suaveplan/jwt-tenant/keys/key-generator";
|
||||
import { TokenIssuer } from "@suaveplan/jwt-tenant/token/token-issuer";
|
||||
|
||||
const keyPair = await generateKeyPair("EdDSA");
|
||||
const issuer = new TokenIssuer({ issuer: "https://auth.example.com" });
|
||||
const token = await issuer.createToken(keyPair, {
|
||||
subject: "user-123",
|
||||
tenantId: "acme",
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { signToken } from "@suaveplan/jwt-tenant/token/token-issuer";
|
||||
|
||||
const clock = () => new Date("2025-06-01T00:00:00Z").getTime();
|
||||
const token = await signToken(keyPair, {
|
||||
subject: "svc-account",
|
||||
tenantId: "internal",
|
||||
expiresIn: "15m",
|
||||
role: "service",
|
||||
permissions: ["read:metrics", "write:events"],
|
||||
sessionId: "sess-abc123",
|
||||
additionalClaims: { env: "production" },
|
||||
}, { clock });
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `TokenIssuer`
|
||||
|
||||
Constructor: `new TokenIssuer(config?: TokenIssuerConfig)`.
|
||||
|
||||
- `config.issuer` — `iss` claim (optional)
|
||||
- `config.defaultExpiresIn` — default duration string (default `"1h"`)
|
||||
- `config.clock` — injectable clock for `iat`/`exp`
|
||||
|
||||
#### Methods
|
||||
|
||||
- **`createToken(keyPair, options): Promise<string>`** — Signs and returns a compact JWT.
|
||||
|
||||
### `createTokenIssuer(config?): TokenIssuer`
|
||||
|
||||
Factory function.
|
||||
|
||||
### `signToken(keyPair, options, config?): Promise<string>`
|
||||
|
||||
Standalone convenience that creates a `TokenIssuer` internally and issues one token.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Duration strings are parsed with a simple regex supporting `ms`, `s`, `m`, `h`, `d` units. Fractional values are not supported. The `exp` claim is set to `floor(now/1000) + duration_in_seconds`, matching the JWT spec's integer seconds requirement. The `jti` is a `crypto.randomUUID()` call for uniqueness.
|
||||
Reference in New Issue
Block a user