@t4h.framework/jwks 0.7.7 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ai/skills/framework-jwks/SKILL.md +79 -238
- package/CHANGELOG.md +6 -0
- package/README.md +14 -59
- package/package.json +2 -2
|
@@ -1,267 +1,108 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: framework-jwks
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
Verifies RS256 JWTs and detached public-key signatures against a JWKS
|
|
5
|
+
endpoint with @t4h.framework/jwks. Use when a T4H Framework workflow or App
|
|
6
|
+
needs JWKSAuthorization, when an async activity such as webhook() declares
|
|
7
|
+
auth { type: 'jwt' } or auth { type: 'jwks' } for its callbacks, or when the
|
|
8
|
+
user mentions a JWKS URL, .well-known/jwks.json, kid, issuer, audience,
|
|
9
|
+
JWKSAlgorithm, a bearer JWT (Google Pub/Sub push, Cloud Tasks) or a signature
|
|
10
|
+
verified with a key published in a JWKS.
|
|
10
11
|
---
|
|
11
12
|
|
|
12
13
|
# @t4h.framework/jwks
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
The package has two uses. Pick the one that matches the task:
|
|
15
16
|
|
|
16
|
-
**
|
|
17
|
+
- **Protect a workflow or an `App`**: `new JWKSAuthorization(context)`.
|
|
18
|
+
- **Verify the callbacks of an async activity**: declare
|
|
19
|
+
`auth: { type: 'jwt', … }` or `auth: { type: 'jwks', … }` on the activity
|
|
20
|
+
(for `webhook()`, see the **framework-webhook** skill). The host verifies
|
|
21
|
+
each callback with `@t4h.framework/jwks/callback`. You do not import it.
|
|
17
22
|
|
|
18
|
-
|
|
23
|
+
## Protect a workflow or an App
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Imports
|
|
25
|
-
|
|
26
|
-
| Entry | Purpose |
|
|
27
|
-
|-------|---------|
|
|
28
|
-
| `@t4h.framework/jwks` | `JWKSAuthorization`, `JWKSAuthorizationContext`, `JWKSAuthorizationManifest`, `JWKSAlgorithm`, re-exports authorize module |
|
|
29
|
-
| `@t4h.framework/jwks/authorize` | Default async handler: `(context) => Promise<boolean>` |
|
|
30
|
-
| `@t4h.framework/jwks/callback` | Default export `jwksCallback`: `(auth, delivery) => Promise<boolean>`, the authorizer hosts pass to the core `AsyncActivityCallback.authorize` for `jwt` (bearer JWT) and `jwks` (detached signature over the body, key resolved by `kid` from a JWKS URL) |
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
import {
|
|
34
|
-
JWKSAuthorization,
|
|
35
|
-
type JWKSAuthorizationContext,
|
|
36
|
-
JWKSAlgorithm,
|
|
37
|
-
} from '@t4h.framework/jwks'
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Do **not** assume OIDC discovery, env-variable mapping, or `credentialSource` helpers—this package does not read HTTP headers or env. Your app or hosting layer supplies `signature`, `rawPayload`, and `url`.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Wiring authorization (core)
|
|
45
|
-
|
|
46
|
-
`JWKSAuthorization` extends core `Authorization`. Attach to a **Workflow** or **App**; `toManifest()` registers the handler module for the platform.
|
|
25
|
+
The handler picks the path from `signature`: a value that decodes as a JWT
|
|
26
|
+
takes the JWT path, any other value takes the raw-payload path.
|
|
47
27
|
|
|
48
28
|
```typescript
|
|
49
|
-
import { App, Workflow } from '@t4h.framework/core'
|
|
50
29
|
import { JWKSAuthorization } from '@t4h.framework/jwks'
|
|
51
30
|
|
|
52
|
-
const authorization = new JWKSAuthorization({
|
|
31
|
+
export const authorization = new JWKSAuthorization({
|
|
53
32
|
url: 'https://auth.example.com/.well-known/jwks.json',
|
|
54
|
-
signature: '<
|
|
55
|
-
rawPayload: '
|
|
33
|
+
signature: '<jwt-from-the-request>',
|
|
34
|
+
rawPayload: '',
|
|
35
|
+
issuer: 'https://auth.example.com/',
|
|
56
36
|
audience: 'https://api.example.com',
|
|
57
37
|
})
|
|
58
|
-
|
|
59
|
-
const workflow = new Workflow(
|
|
60
|
-
{ id: 'protected/v1', authorization },
|
|
61
|
-
async () => ({ ok: true }),
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
const app = new App({
|
|
65
|
-
id: 'my-app',
|
|
66
|
-
workflows: [workflow],
|
|
67
|
-
authorization, // optional app-level default
|
|
68
|
-
})
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Manifest shape (from tests):
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
{
|
|
75
|
-
pathToModule: '@t4h.framework/jwks/authorize',
|
|
76
|
-
context: {
|
|
77
|
-
url: string
|
|
78
|
-
signature: string
|
|
79
|
-
rawPayload: string
|
|
80
|
-
issuer?: string
|
|
81
|
-
audience?: string
|
|
82
|
-
kid?: string
|
|
83
|
-
algorithm?: string
|
|
84
|
-
signatureFormat?: string
|
|
85
|
-
},
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Optional manifest fields are still present as `undefined` when omitted (`toManifest` copies all keys).
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Context: `JWKSAuthorizationContext`
|
|
94
|
-
|
|
95
|
-
| Field | Required | Description |
|
|
96
|
-
|-------|----------|-------------|
|
|
97
|
-
| `url` | Yes | JWKS document URL (`jwks-rsa` `jwksUri`). |
|
|
98
|
-
| `signature` | Yes | Credential to verify: JWT string, or detached signature for non-JWT path. Empty string → handler returns `false`. |
|
|
99
|
-
| `rawPayload` | Yes | Payload bytes as string for non-JWT verification; for JWT path, tests pass the same string as `signature` (handler only uses `signature` on JWT path). |
|
|
100
|
-
| `issuer` | No | When set, passed to `jwt.verify` as expected `iss`. Mismatch **rejects** (throws). |
|
|
101
|
-
| `audience` | No | When set, passed to `jwt.verify` as expected `aud`. |
|
|
102
|
-
| `kid` | Non-JWT path | Key id to look up in the JWKS. Used when `signature` is **not** a decodable JWT. |
|
|
103
|
-
| `algorithm` | Non-JWT path | **Enum key** on `JWKSAlgorithm` (e.g. `RS256`), not the Node crypto string. |
|
|
104
|
-
| `signatureFormat` | Non-JWT path | Encoding for the signature buffer (`hex`, `base64`, etc.—`BinaryToTextEncoding`). |
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
## Runtime handler (`@t4h.framework/jwks/authorize`)
|
|
109
|
-
|
|
110
|
-
Default export:
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
(options: JWKSAuthorizationContext) => Promise<boolean>
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
Behavior (from `jwks-authorize.ts` and tests):
|
|
117
|
-
|
|
118
|
-
1. If `signature` is falsy → **`false`** (no throw).
|
|
119
|
-
2. Build `JwksClient({ jwksUri: options.url })`.
|
|
120
|
-
3. `jwt.decode(signature, { complete: true })`:
|
|
121
|
-
- **Decoded (JWT path)** → `validateJwt(signature, client, { issuer, audience })`.
|
|
122
|
-
- **Not decoded (non-JWT path)** → verify the detached signature with `kid`, `algorithm` and `signatureFormat`.
|
|
123
|
-
|
|
124
|
-
### JWT path (`validateJwt`)
|
|
125
|
-
|
|
126
|
-
- Algorithm must be **RS256** (`decoded.header.alg === 'RS256'`); otherwise **`false`** (e.g. HS256 tokens return `false`, not throw).
|
|
127
|
-
- Header must include **`kid`**; used to `getSigningKey(kid)` from JWKS.
|
|
128
|
-
- **`exp` enforced** (`ignoreExpiration: false`). Expired or wrong signing key → **`jwt.verify` rejects** (promise rejection / throw from handler).
|
|
129
|
-
- Optional `issuer` / `audience` from context applied when present.
|
|
130
|
-
|
|
131
|
-
### Non-JWT path
|
|
132
|
-
|
|
133
|
-
Uses Node `crypto.createVerify` with public key from JWKS:
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
authorizer.update(options.rawPayload)
|
|
137
|
-
authorizer.verify(signingKey, options.signature, signatureFormat)
|
|
138
38
|
```
|
|
139
39
|
|
|
140
|
-
|
|
40
|
+
Attach it to the `authorization` option of a `Workflow` or an `App`. For a
|
|
41
|
+
detached signature, give the signed bytes in `rawPayload` and set `kid`,
|
|
42
|
+
`algorithm` and `signatureFormat`.
|
|
141
43
|
|
|
142
|
-
|
|
44
|
+
## Verify async activity callbacks
|
|
143
45
|
|
|
144
46
|
```typescript
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
RS384 = 'RSA-SHA384',
|
|
148
|
-
RS512 = 'RSA-SHA512',
|
|
149
|
-
PS256 = 'RSA-PSS-SHA256',
|
|
150
|
-
PS384 = 'RSA-PSS-SHA384',
|
|
151
|
-
PS512 = 'RSA-PSS-SHA512',
|
|
152
|
-
ES256 = 'ECDSA-SHA256',
|
|
153
|
-
ES384 = 'ECDSA-SHA384',
|
|
154
|
-
ES512 = 'ECDSA-SHA512',
|
|
47
|
+
auth: {
|
|
48
|
+
type: ('jwt', jwksUri, issuer, audience)
|
|
155
49
|
}
|
|
156
50
|
```
|
|
157
51
|
|
|
158
|
-
Handler uses `JWKSAlgorithm[algorithm]` as the `createVerify` algorithm name. Pass `algorithm: 'RS256'`, not `'RSA-SHA256'`.
|
|
159
|
-
|
|
160
|
-
Returns **`true`** on successful verification, **`false`** when verification fails (non-JWT invalid signature).
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## Examples
|
|
165
|
-
|
|
166
|
-
### RS256 JWT (typical API Bearer token)
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
import { JWKSAuthorization } from '@t4h.framework/jwks'
|
|
170
|
-
|
|
171
|
-
const authorization = new JWKSAuthorization({
|
|
172
|
-
url: 'https://id.example.com/.well-known/jwks.json',
|
|
173
|
-
signature: bearerToken, // without "Bearer " prefix if your layer strips it
|
|
174
|
-
rawPayload: bearerToken,
|
|
175
|
-
issuer: 'https://issuer.example.com',
|
|
176
|
-
audience: 'my-api',
|
|
177
|
-
})
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Token must be signed RS256 with `kid` in header. Platform invokes `@t4h.framework/jwks/authorize` with manifest `context` when the protected workflow runs.
|
|
181
|
-
|
|
182
|
-
### Detached signature (non-JWT)
|
|
183
|
-
|
|
184
|
-
```typescript
|
|
185
|
-
new JWKSAuthorization({
|
|
186
|
-
url: 'https://id.example.com/jwks',
|
|
187
|
-
signature: detachedSignatureHex,
|
|
188
|
-
rawPayload: canonicalPayloadString,
|
|
189
|
-
kid: 'key-1',
|
|
190
|
-
algorithm: 'RS256',
|
|
191
|
-
signatureFormat: 'hex',
|
|
192
|
-
})
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
If `signature` accidentally looks like a JWT to `jwt.decode`, the JWT path runs instead—structure payloads accordingly.
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## Return values vs errors
|
|
200
|
-
|
|
201
|
-
| Situation | Result |
|
|
202
|
-
|-----------|--------|
|
|
203
|
-
| Empty `signature` | `false` |
|
|
204
|
-
| Valid RS256 JWT, matching JWKS key | `true` |
|
|
205
|
-
| JWT wrong alg (e.g. HS256), no `kid`, undecodable token | `false` |
|
|
206
|
-
| Expired JWT, issuer mismatch, signature mismatch | **Rejected** (throw from `jwt.verify`) |
|
|
207
|
-
| Non-JWT verify fails | `false` |
|
|
208
|
-
|
|
209
|
-
Design callers so manifest context is complete **before** the handler runs; missing non-JWT fields are programmer errors, not silent denials.
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
## Testing the handler locally
|
|
214
|
-
|
|
215
|
-
Unit tests mock `jwks-rsa` and use real RSA key pairs + `jsonwebtoken`:
|
|
216
|
-
|
|
217
52
|
```typescript
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
53
|
+
auth: {
|
|
54
|
+
type: 'jwks',
|
|
55
|
+
jwksUri: 'https://partner.example.com/.well-known/jwks.json',
|
|
56
|
+
header: 'x-signature',
|
|
57
|
+
kidHeader: 'x-key-id',
|
|
223
58
|
algorithm: 'RS256',
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
jwks({
|
|
230
|
-
url: 'https://example.com/jwks',
|
|
231
|
-
signature: token,
|
|
232
|
-
rawPayload: token,
|
|
233
|
-
}),
|
|
234
|
-
).resolves.toBe(true)
|
|
59
|
+
signatureFormat: 'base64',
|
|
60
|
+
timestampHeader: 'x-timestamp',
|
|
61
|
+
toleranceInSeconds: 300,
|
|
62
|
+
signedPayload: '{timestamp}.{body}',
|
|
63
|
+
}
|
|
235
64
|
```
|
|
236
65
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
-
|
|
246
|
-
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
##
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
66
|
+
On `jwks`, each of `kid`, `algorithm` and `signatureFormat` is a fixed value or
|
|
67
|
+
a `*Header` name. A fixed value wins. `signatureFormat` defaults to `'hex'`.
|
|
68
|
+
|
|
69
|
+
## Traps
|
|
70
|
+
|
|
71
|
+
- The field is `signature`. There is no `value` field.
|
|
72
|
+
- The JWT path accepts only RS256 tokens with a `kid` in the header. HS256 or
|
|
73
|
+
ES256 tokens give `false`.
|
|
74
|
+
- On the JWT path `rawPayload` is not used. Pass `''`.
|
|
75
|
+
- `algorithm` is a `JWKSAlgorithm` KEY such as `'RS256'`, not the Node name
|
|
76
|
+
`'RSA-SHA256'`. Today only `RS256`, `RS384` and `RS512` verify; the `PS*` and
|
|
77
|
+
`ES*` keys throw `Invalid digest`.
|
|
78
|
+
- A detached signature that happens to decode as a JWT takes the JWT path.
|
|
79
|
+
- `JWKSAuthorization`: a denied raw-payload signature gives `false`, but an
|
|
80
|
+
expired JWT, an `issuer` or `audience` mismatch, a bad JWT signature or a
|
|
81
|
+
missing `kid`/`algorithm`/`signatureFormat` THROWS. On a callback each error
|
|
82
|
+
becomes a refusal.
|
|
83
|
+
- Always set `issuer` and `audience` for a JWT. Without them a token minted for
|
|
84
|
+
another service passes.
|
|
85
|
+
- Callback timestamps: all digits with 13 or more digits are milliseconds,
|
|
86
|
+
fewer are seconds. Other strings go through `Date.parse`.
|
|
87
|
+
- The package does not read HTTP headers or env, and has no OIDC discovery. For
|
|
88
|
+
a token from an OIDC provider, see **framework-oidc**.
|
|
89
|
+
|
|
90
|
+
## Test
|
|
91
|
+
|
|
92
|
+
The handler fetches keys over HTTP from `url`. Serve a JWKS from a local HTTP
|
|
93
|
+
server in the test (export the public key with
|
|
94
|
+
`publicKey.export({ format: 'jwk' })` and add `kid`), sign a token with
|
|
95
|
+
`jsonwebtoken` (`algorithm: 'RS256'`, `keyid`), and call the default export of
|
|
96
|
+
`@t4h.framework/jwks/authorize`.
|
|
97
|
+
|
|
98
|
+
## Related skills
|
|
99
|
+
|
|
100
|
+
- **framework-hmac**: shared-secret signatures.
|
|
101
|
+
- **framework-webhook**: wait for a partner callback that uses this `auth`.
|
|
102
|
+
|
|
103
|
+
## Reference
|
|
104
|
+
|
|
105
|
+
- Guide: <https://tech4humans-brasil.github.io/framework/jwks/>
|
|
106
|
+
- Types: `node_modules/@t4h.framework/jwks/dist/jwks.d.ts`
|
|
107
|
+
- Callback `auth` types: `AsyncActivityCallbackAuthJwt` and
|
|
108
|
+
`AsyncActivityCallbackAuthJwks` in `node_modules/@t4h.framework/core/dist/`
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @t4h.framework/jwks
|
|
2
2
|
|
|
3
|
+
## 0.7.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#257](https://github.com/tech4humans-brasil/framework/pull/257) [`586bfb4`](https://github.com/tech4humans-brasil/framework/commit/586bfb4663f4a478527ee0c8db360603f034d615) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The jwks README is now short and links to the site. The site page now describes the `jwt` and `jwks` callback `auth`, the results and errors, and says that only the `RS*` keys verify a detached signature.
|
|
8
|
+
|
|
3
9
|
## 0.7.7
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,76 +1,31 @@
|
|
|
1
1
|
# @t4h.framework/jwks
|
|
2
2
|
|
|
3
|
-
JWKS
|
|
3
|
+
JWKS authorization for the T4H Framework. It verifies an RS256 JWT, or a
|
|
4
|
+
detached signature over a raw payload, against the public keys of a JWKS
|
|
5
|
+
endpoint, for a workflow, an app or the callbacks of an async activity.
|
|
4
6
|
|
|
5
|
-
##
|
|
7
|
+
## Install
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## Exports
|
|
10
|
-
|
|
11
|
-
| Entry | Purpose |
|
|
12
|
-
|------------------|---------|
|
|
13
|
-
| `@t4h.framework/jwks` | `JWKSAuthorization`, `JWKSAuthorizationContext`, and related types |
|
|
14
|
-
| `@t4h.framework/jwks/authorize` | Default async handler invoked by the runtime with the manifest context |
|
|
15
|
-
| `@t4h.framework/jwks/callback` | Default export `jwksCallback`: the `jwt` (bearer JWT) and `jwks` (detached signature verified with a JWKS key) callback authorizer for the core `AsyncActivityCallback.authorize` |
|
|
16
|
-
|
|
17
|
-
## `JWKSAuthorization`
|
|
18
|
-
|
|
19
|
-
Subclass of [`Authorization`](https://github.com/tech4humans-brasil/framework/tree/main/packages/core) from core. `toManifest()` points the runtime at `@t4h.framework/jwks/authorize` and passes a `JWKSAuthorizationContext`.
|
|
20
|
-
|
|
21
|
-
Construct it with a full `JWKSAuthorizationContext`. `url`, `signature` and `rawPayload` are required. Your app or deployment pipeline supplies `signature` and `rawPayload`, for example from a request header or by runtime injection. This package does not read HTTP or env.
|
|
22
|
-
|
|
23
|
-
## Context: `JWKSAuthorizationContext`
|
|
24
|
-
|
|
25
|
-
| Field | Required | Description |
|
|
26
|
-
|-------|----------|-------------|
|
|
27
|
-
| `url` | Yes | JWKS document URL (`jwks-rsa` `jwksUri`). |
|
|
28
|
-
| `signature` | Yes | Credential to verify: a JWT, or a detached signature for the non-JWT path. An empty string gives `false`. |
|
|
29
|
-
| `rawPayload` | Yes | The signed payload for the non-JWT path. The JWT path does not use it; pass an empty string. |
|
|
30
|
-
| `issuer` | No | JWT path: the expected `iss`. |
|
|
31
|
-
| `audience` | No | JWT path: the expected `aud`. |
|
|
32
|
-
| `kid` | Non-JWT path | Key id to find in the JWKS. Required when `signature` is **not** a JWT that decodes. |
|
|
33
|
-
| `algorithm` | Non-JWT path | A key of `JWKSAlgorithm` (`RS256`, `PS256`, `ES256`, …). |
|
|
34
|
-
| `signatureFormat` | Non-JWT path | Encoding of `signature` (`hex`, `base64`, …). |
|
|
35
|
-
|
|
36
|
-
There is no OIDC discovery (`JWKS_ISSUER`), no environment-variable mapping in this package, and no `credentialSource` helper. Your application or hosting layer gives `signature` and `rawPayload`.
|
|
37
|
-
|
|
38
|
-
## Runtime handler (`jwks/authorize`)
|
|
39
|
-
|
|
40
|
-
The default export is an async function:
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
(options: JWKSAuthorizationContext) => Promise<boolean>
|
|
9
|
+
```bash
|
|
10
|
+
npm install @t4h.framework/jwks @t4h.framework/core
|
|
44
11
|
```
|
|
45
12
|
|
|
46
|
-
|
|
47
|
-
- Returns `true` if verification succeeds.
|
|
48
|
-
|
|
49
|
-
### JWT path
|
|
50
|
-
|
|
51
|
-
If `signature` decodes as a JWT (`jsonwebtoken` `decode` with `complete: true` succeeds), the handler verifies it with `validateJwt` ([source](https://github.com/tech4humans-brasil/framework/blob/main/packages/jwks/src/helpers/validateJwt.ts)):
|
|
52
|
-
|
|
53
|
-
- The algorithm must be **RS256**. A different `alg` in the header gives `false`.
|
|
54
|
-
- The header must have a `kid`, which selects the signing key in the JWKS. No `kid` gives `false`.
|
|
55
|
-
- `exp` is enforced.
|
|
56
|
-
- `issuer` and `audience` from the context apply when you set them.
|
|
57
|
-
- An expired token, an `issuer` or `audience` mismatch, or a bad signature makes `jwt.verify` throw, so the handler throws.
|
|
58
|
-
|
|
59
|
-
### Non-JWT path
|
|
60
|
-
|
|
61
|
-
If `signature` does not decode as a JWT, the handler needs `kid`, `algorithm` and `signatureFormat` on the context. If one of them is missing, it **throws**. It gets the public key from the JWKS by `kid`, and verifies `signature` over `rawPayload` with Node `crypto.createVerify`. A signature that does not match gives `false`.
|
|
62
|
-
|
|
63
|
-
## Example
|
|
13
|
+
## Usage
|
|
64
14
|
|
|
65
15
|
```typescript
|
|
66
16
|
import { JWKSAuthorization } from '@t4h.framework/jwks'
|
|
67
17
|
|
|
68
18
|
const authorization = new JWKSAuthorization({
|
|
69
19
|
url: 'https://auth.example.com/.well-known/jwks.json',
|
|
70
|
-
signature: '<
|
|
20
|
+
signature: '<jwt-from-the-request>',
|
|
71
21
|
rawPayload: '',
|
|
22
|
+
issuer: 'https://auth.example.com/',
|
|
72
23
|
audience: 'https://api.example.com',
|
|
73
24
|
})
|
|
74
25
|
```
|
|
75
26
|
|
|
76
|
-
|
|
27
|
+
Attach `authorization` to a `Workflow` or an `App`.
|
|
28
|
+
|
|
29
|
+
## Documentation
|
|
30
|
+
|
|
31
|
+
<https://tech4humans-brasil.github.io/framework/jwks/>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t4h.framework/jwks",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "JWKS module for the T4H Framework authorization",
|
|
5
5
|
"homepage": "https://github.com/tech4humans-brasil/framework/tree/main/packages/jwks",
|
|
6
6
|
"bugs": "https://github.com/tech4humans-brasil/framework/issues",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"test:watch": "vitest"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@t4h.framework/core": "^0.
|
|
46
|
+
"@t4h.framework/core": "^0.21.0",
|
|
47
47
|
"@types/jsonwebtoken": "^9",
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
49
|
"vitest": "^4.0.18"
|