@sentropic/auth-hono 0.3.0 → 0.4.0
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/README.md +55 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/oauth/service-auth-middleware.d.ts +30 -0
- package/dist/oauth/service-auth-middleware.d.ts.map +1 -0
- package/dist/oauth/service-auth-middleware.js +170 -0
- package/dist/oauth/service-auth-middleware.js.map +1 -0
- package/dist/oauth/state-store-types.d.ts +14 -0
- package/dist/oauth/state-store-types.d.ts.map +1 -1
- package/dist/oauth/token-handler.d.ts +1 -0
- package/dist/oauth/token-handler.d.ts.map +1 -1
- package/dist/oauth/token-handler.js +120 -2
- package/dist/oauth/token-handler.js.map +1 -1
- package/dist/oauth/wellknown-handler.js +2 -2
- package/dist/oauth/wellknown-handler.js.map +1 -1
- package/dist/ports.d.ts +1 -1
- package/dist/ports.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/oauth/service-auth-middleware.ts +250 -0
- package/src/oauth/state-store-types.ts +15 -0
- package/src/oauth/token-handler.ts +174 -3
- package/src/oauth/wellknown-handler.ts +2 -2
- package/src/ports.ts +1 -0
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ All package handlers emit structured responses to keep contracts predictable acr
|
|
|
77
77
|
| Endpoint | Description |
|
|
78
78
|
| --- | --- |
|
|
79
79
|
| `GET /oauth/authorize` | Authorization Code + PKCE entry point (S256 required) |
|
|
80
|
-
| `POST /oauth/token` | Token issuance (`grant_type=authorization_code`
|
|
80
|
+
| `POST /oauth/token` | Token issuance (`grant_type=authorization_code` and `client_credentials` since 0.4.0) |
|
|
81
81
|
| `GET\|POST /oauth/userinfo` | Returns claims for a valid access token |
|
|
82
82
|
| `POST /oauth/revoke` | Revokes an access token (RFC 7009) |
|
|
83
83
|
| `POST /oauth/introspect` | Token introspection (RFC 7662, client-auth required) |
|
|
@@ -158,6 +158,56 @@ The package never imports Postgres or any persistence library. Sentropic supplie
|
|
|
158
158
|
|
|
159
159
|
Set `dpop_bound_access_tokens: true` on the OAuth client record. Bound clients must send a `DPoP: <proof-jwt>` header on `/token`, `/userinfo`, and `/revoke`. The IdP verifies `htm`, `htu`, `iat` skew, unique proof `jti`, and `ath` on resource calls. Access and ID tokens include `cnf.jkt`.
|
|
160
160
|
|
|
161
|
+
### Service-to-service auth — `client_credentials` (since 0.4.0)
|
|
162
|
+
|
|
163
|
+
Backend services mint scoped, audience-bound, **stateless** access tokens without
|
|
164
|
+
a human via the `client_credentials` grant.
|
|
165
|
+
|
|
166
|
+
- **Service clients** are a separate record type, `ServiceClientRecord`, looked up
|
|
167
|
+
through an **optional** `findServiceClient?(clientId)` method on
|
|
168
|
+
`OauthStateStorePort`. Existing implementors of the `0.3.0` contract keep
|
|
169
|
+
compiling; if the method is absent, `client_credentials` returns
|
|
170
|
+
`unsupported_grant_type`.
|
|
171
|
+
- **Auth methods**: `client_secret_basic` and `client_secret_post`, verified via
|
|
172
|
+
`ports.tokens.hashSecret`.
|
|
173
|
+
- **Scopes**: empty/absent `scope` grants the client's full `allowed_scopes`;
|
|
174
|
+
otherwise the request must be a subset (else `invalid_scope`).
|
|
175
|
+
- **RFC 8707 resource indicators**: the issued token `aud` is the resolved
|
|
176
|
+
`resource`, which must be in the client's `resource_indicators`. Resolution: 1
|
|
177
|
+
indicator + no `resource` ⇒ use it; >1 + no `resource` ⇒ `invalid_target`; 0
|
|
178
|
+
indicators ⇒ `resource` required else `invalid_target`; unknown `resource` ⇒
|
|
179
|
+
`invalid_target`.
|
|
180
|
+
- **Stateless** (no `saveTokenMeta`, no `oauth_tokens` row): security relies on a
|
|
181
|
+
short TTL (`serviceAccessTokenTtlSeconds`, default `900`) + secret rotation.
|
|
182
|
+
Service-token revocation/introspection are deferred to BR-39h.
|
|
183
|
+
- **DPoP** is opt-in via `dpop_bound_access_tokens` and strongly recommended for
|
|
184
|
+
production S2S.
|
|
185
|
+
|
|
186
|
+
Resource servers verify these tokens with `createRequireServiceAuth`:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { createRequireServiceAuth, type ServiceAuthPorts } from '@sentropic/auth-hono';
|
|
190
|
+
|
|
191
|
+
const ports: ServiceAuthPorts = {
|
|
192
|
+
clock, // AuthHonoClockPort
|
|
193
|
+
jwks, // JwksPort
|
|
194
|
+
dpopReplay: { recordDpopJti }, // optional, required to enforce DPoP replay
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
app.get(
|
|
198
|
+
'/internal/ping',
|
|
199
|
+
createRequireServiceAuth({ issuer, resource, requiredScopes: ['service:ping'], ports }),
|
|
200
|
+
(c) => c.json({ ok: true, client: c.get('serviceClient') }),
|
|
201
|
+
);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`ServiceAuthPorts` is a **narrow** port (`Pick<AuthHonoPorts,'jwks'|'clock'> & { dpopReplay? }`):
|
|
205
|
+
resource servers do not construct user/credential/session/email ports just to
|
|
206
|
+
verify a token. The middleware validates `iss`, `aud === resource`, `exp`, and
|
|
207
|
+
`scope ⊇ requiredScopes`; for `cnf.jkt`-bound tokens it requires a DPoP proof,
|
|
208
|
+
enforces `ath` (RFC 9449 §4.3), and records the proof `jti` for replay defense.
|
|
209
|
+
On failure it returns 401/403 with a `WWW-Authenticate` header.
|
|
210
|
+
|
|
161
211
|
### Claims and ACR levels
|
|
162
212
|
|
|
163
213
|
| Claim | Source | Notes |
|
|
@@ -176,6 +226,8 @@ Set `dpop_bound_access_tokens: true` on the OAuth client record. Bound clients m
|
|
|
176
226
|
| `OAUTH_ID_TOKEN_TTL_SEC` | ID token lifetime | `3600` |
|
|
177
227
|
| `OAUTH_AUTHORIZATION_CODE_TTL_SEC` | Authorization code TTL | `60` |
|
|
178
228
|
| `OAUTH_DPOP_IAT_SKEW_SEC` | DPoP proof `iat` tolerance | `60` |
|
|
229
|
+
| `OAUTH_SERVICE_ACCESS_TOKEN_TTL_SEC` | Stateless service token TTL (`client_credentials`) | `900` |
|
|
230
|
+
| `OAUTH_SERVICE_RESOURCE_URI` | Service token `aud` this API accepts/advertises | Derived from issuer |
|
|
179
231
|
|
|
180
232
|
### End-to-end example
|
|
181
233
|
|
|
@@ -187,8 +239,9 @@ This is a brand-new public package. First publish requires the one-shot bootstra
|
|
|
187
239
|
|
|
188
240
|
## Versioning
|
|
189
241
|
|
|
190
|
-
This branch ships `0.
|
|
242
|
+
This branch ships `0.4.0`:
|
|
191
243
|
|
|
192
244
|
- `0.2.0` adds `AuthHonoRouteHandlerError` short-circuit on WebAuthn prepare/resolve hooks and the `finalizeRegistration`/`finalizeAuthentication` post-verify hooks. Additive; existing handler signatures stay valid.
|
|
193
245
|
- `0.2.1` patches `extractChallenge` (both WebAuthn handlers) to handle `credential.response === null` defensively (returns 400 `invalid_credential` instead of throwing 500).
|
|
194
246
|
- `0.3.0` adds the OAuth2/OIDC IdP surface: `createOAuthRouter`, `createWellKnownRouter`, `createJwksService`, `OauthStateStorePort`, `JwksPort`, Ed25519 signing, DPoP opt-in, and all six OAuth endpoints. Additive; existing WebAuthn/session handler signatures unchanged.
|
|
247
|
+
- `0.4.0` adds the S2S `client_credentials` grant (stateless service tokens), `createRequireServiceAuth` + `ServiceAuthPorts`, the optional `findServiceClient?` on `OauthStateStorePort`, `ServiceClientRecord`, and RFC 8707 resource indicators. Discovery now advertises `client_credentials` and `client_secret_post`. Additive and non-breaking — existing `0.3.0` implementors keep compiling.
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from './oauth/introspect-handler.js';
|
|
|
12
12
|
export * from './oauth/jwks-service.js';
|
|
13
13
|
export * from './oauth/router.js';
|
|
14
14
|
export * from './oauth/revoke-handler.js';
|
|
15
|
+
export * from './oauth/service-auth-middleware.js';
|
|
15
16
|
export * from './oauth/session-resolver.js';
|
|
16
17
|
export * from './oauth/state-store-types.js';
|
|
17
18
|
export * from './oauth/state-codec.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2CAA2C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2CAA2C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export * from './oauth/introspect-handler.js';
|
|
|
12
12
|
export * from './oauth/jwks-service.js';
|
|
13
13
|
export * from './oauth/router.js';
|
|
14
14
|
export * from './oauth/revoke-handler.js';
|
|
15
|
+
export * from './oauth/service-auth-middleware.js';
|
|
15
16
|
export * from './oauth/session-resolver.js';
|
|
16
17
|
export * from './oauth/state-store-types.js';
|
|
17
18
|
export * from './oauth/state-codec.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2CAA2C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oCAAoC,CAAC;AACnD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2CAA2C,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from 'hono';
|
|
2
|
+
import type { AuthHonoClockPort } from '../ports.js';
|
|
3
|
+
import type { JwksPort, OauthStateStorePort } from './state-store-types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Narrow port set for resource-server verification (BR39d-D6). Resource servers
|
|
6
|
+
* must not construct users/credentials/sessions/email ports just to verify a
|
|
7
|
+
* bearer or DPoP-bound access token.
|
|
8
|
+
*/
|
|
9
|
+
export interface ServiceAuthPorts {
|
|
10
|
+
clock: AuthHonoClockPort;
|
|
11
|
+
jwks: JwksPort;
|
|
12
|
+
dpopReplay?: Pick<OauthStateStorePort, 'recordDpopJti'>;
|
|
13
|
+
}
|
|
14
|
+
export interface ServiceAuthContext {
|
|
15
|
+
clientId: string;
|
|
16
|
+
scopes: string[];
|
|
17
|
+
jkt: string | null;
|
|
18
|
+
}
|
|
19
|
+
export interface CreateRequireServiceAuthOptions {
|
|
20
|
+
issuer: string;
|
|
21
|
+
requiredScopes?: string[];
|
|
22
|
+
resource: string;
|
|
23
|
+
ports: ServiceAuthPorts;
|
|
24
|
+
/** DPoP proof iat acceptance window in seconds (default 60). */
|
|
25
|
+
dpopIatSkewSeconds?: number;
|
|
26
|
+
/** Context key the verified service-client context is stored under (default 'serviceClient'). */
|
|
27
|
+
contextKey?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare const createRequireServiceAuth: (options: CreateRequireServiceAuthOptions) => MiddlewareHandler;
|
|
30
|
+
//# sourceMappingURL=service-auth-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-auth-middleware.d.ts","sourceRoot":"","sources":["../../src/oauth/service-auth-middleware.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAW,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE5E;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,iBAAiB,CAAC;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,IAAI,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,gBAAgB,CAAC;IACxB,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iGAAiG;IACjG,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAcD,eAAO,MAAM,wBAAwB,YAC1B,+BAA+B,KACvC,iBA6BF,CAAC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { calculateJwkThumbprint, decodeProtectedHeader, importJWK, jwtVerify, } from 'jose';
|
|
2
|
+
import { sha256Base64url } from './crypto-utils.js';
|
|
3
|
+
class ServiceAuthError extends Error {
|
|
4
|
+
status;
|
|
5
|
+
code;
|
|
6
|
+
scheme;
|
|
7
|
+
constructor(status, code, message, scheme = 'Bearer') {
|
|
8
|
+
super(message);
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.scheme = scheme;
|
|
12
|
+
this.name = 'ServiceAuthError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export const createRequireServiceAuth = (options) => {
|
|
16
|
+
const issuer = trimTrailingSlash(options.issuer);
|
|
17
|
+
const requiredScopes = options.requiredScopes ?? [];
|
|
18
|
+
const contextKey = options.contextKey ?? 'serviceClient';
|
|
19
|
+
return async (c, next) => {
|
|
20
|
+
try {
|
|
21
|
+
const { scheme, token } = parseAuthorization(c.req.header('authorization'));
|
|
22
|
+
const payload = await verifyAccessToken(token, options.ports, issuer, options.resource);
|
|
23
|
+
const scopes = parseScopes(payload.scope);
|
|
24
|
+
assertScopes(scopes, requiredScopes);
|
|
25
|
+
const jkt = await enforceDpop(c, payload, token, scheme, options);
|
|
26
|
+
const serviceContext = {
|
|
27
|
+
clientId: typeof payload.client_id === 'string' ? payload.client_id : String(payload.sub ?? ''),
|
|
28
|
+
jkt,
|
|
29
|
+
scopes,
|
|
30
|
+
};
|
|
31
|
+
c.set(contextKey, serviceContext);
|
|
32
|
+
await next();
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (error instanceof ServiceAuthError) {
|
|
36
|
+
return serviceAuthErrorResponse(c, error);
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
const parseAuthorization = (header) => {
|
|
43
|
+
if (!header) {
|
|
44
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Authorization header is required.');
|
|
45
|
+
}
|
|
46
|
+
const [scheme, token] = header.split(/\s+/, 2);
|
|
47
|
+
if (!token) {
|
|
48
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Authorization header is malformed.');
|
|
49
|
+
}
|
|
50
|
+
if (scheme === 'Bearer')
|
|
51
|
+
return { scheme: 'Bearer', token };
|
|
52
|
+
if (scheme === 'DPoP')
|
|
53
|
+
return { scheme: 'DPoP', token };
|
|
54
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Unsupported authorization scheme.');
|
|
55
|
+
};
|
|
56
|
+
const verifyAccessToken = async (token, ports, issuer, resource) => {
|
|
57
|
+
let kid;
|
|
58
|
+
try {
|
|
59
|
+
kid = decodeProtectedHeader(token).kid;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token header is invalid.');
|
|
63
|
+
}
|
|
64
|
+
if (!kid) {
|
|
65
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token is missing a key id.');
|
|
66
|
+
}
|
|
67
|
+
const key = await ports.jwks.findKeyByKid(kid);
|
|
68
|
+
if (!key) {
|
|
69
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token signing key is unknown.');
|
|
70
|
+
}
|
|
71
|
+
const publicKey = await importJWK(key.publicJwk, key.alg);
|
|
72
|
+
const currentDate = ports.clock.now();
|
|
73
|
+
try {
|
|
74
|
+
const { payload } = await jwtVerify(token, publicKey, {
|
|
75
|
+
audience: resource,
|
|
76
|
+
currentDate,
|
|
77
|
+
issuer,
|
|
78
|
+
});
|
|
79
|
+
return payload;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token is invalid, expired, or has the wrong audience.');
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const parseScopes = (scope) => typeof scope === 'string' ? scope.split(/\s+/).filter(Boolean) : [];
|
|
86
|
+
const assertScopes = (scopes, requiredScopes) => {
|
|
87
|
+
const granted = new Set(scopes);
|
|
88
|
+
const missing = requiredScopes.filter((scope) => !granted.has(scope));
|
|
89
|
+
if (missing.length > 0) {
|
|
90
|
+
throw new ServiceAuthError(403, 'insufficient_scope', `Missing required scope: ${missing.join(' ')}.`);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const enforceDpop = async (c, payload, accessToken, scheme, options) => {
|
|
94
|
+
const boundJkt = payload.cnf?.jkt;
|
|
95
|
+
if (!boundJkt)
|
|
96
|
+
return null;
|
|
97
|
+
if (scheme !== 'DPoP') {
|
|
98
|
+
throw new ServiceAuthError(401, 'invalid_token', 'DPoP-bound token requires the DPoP authorization scheme.', 'DPoP');
|
|
99
|
+
}
|
|
100
|
+
const proof = c.req.header('dpop');
|
|
101
|
+
if (!proof) {
|
|
102
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof is required.', 'DPoP');
|
|
103
|
+
}
|
|
104
|
+
const verifiedJkt = await verifyServiceDpopProof({
|
|
105
|
+
accessToken,
|
|
106
|
+
htm: c.req.method,
|
|
107
|
+
htu: c.req.url,
|
|
108
|
+
iatSkewSeconds: options.dpopIatSkewSeconds,
|
|
109
|
+
ports: options.ports,
|
|
110
|
+
proof,
|
|
111
|
+
});
|
|
112
|
+
if (verifiedJkt !== boundJkt) {
|
|
113
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof key does not match the bound token.', 'DPoP');
|
|
114
|
+
}
|
|
115
|
+
return verifiedJkt;
|
|
116
|
+
};
|
|
117
|
+
const verifyServiceDpopProof = async (options) => {
|
|
118
|
+
const header = decodeProtectedHeader(options.proof);
|
|
119
|
+
const publicJwk = header.jwk;
|
|
120
|
+
if (!publicJwk || !header.alg || header.typ !== 'dpop+jwt') {
|
|
121
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof header is invalid.', 'DPoP');
|
|
122
|
+
}
|
|
123
|
+
const key = await importJWK(publicJwk, header.alg);
|
|
124
|
+
let payload;
|
|
125
|
+
try {
|
|
126
|
+
({ payload } = await jwtVerify(options.proof, key));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof signature is invalid.', 'DPoP');
|
|
130
|
+
}
|
|
131
|
+
const skew = options.iatSkewSeconds ?? 60;
|
|
132
|
+
if (payload.htm !== options.htm.toUpperCase()) {
|
|
133
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP htm claim does not match the request method.', 'DPoP');
|
|
134
|
+
}
|
|
135
|
+
if (payload.htu !== options.htu) {
|
|
136
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP htu claim does not match the request URL.', 'DPoP');
|
|
137
|
+
}
|
|
138
|
+
if (!payload.jti || typeof payload.jti !== 'string') {
|
|
139
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP jti claim is required.', 'DPoP');
|
|
140
|
+
}
|
|
141
|
+
if (typeof payload.iat !== 'number') {
|
|
142
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP iat claim is required.', 'DPoP');
|
|
143
|
+
}
|
|
144
|
+
const nowSeconds = Math.floor(options.ports.clock.now().getTime() / 1000);
|
|
145
|
+
if (Math.abs(payload.iat - nowSeconds) > skew) {
|
|
146
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP iat claim is outside the allowed skew.', 'DPoP');
|
|
147
|
+
}
|
|
148
|
+
// RFC 9449 §4.3: bind the proof to the access token (BR39d-D7).
|
|
149
|
+
if (payload.ath !== (await sha256Base64url(options.accessToken))) {
|
|
150
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP ath claim does not match the access token.', 'DPoP');
|
|
151
|
+
}
|
|
152
|
+
if (options.ports.dpopReplay) {
|
|
153
|
+
const expiresAt = options.ports.clock.addSeconds(options.ports.clock.now(), skew);
|
|
154
|
+
const recorded = await options.ports.dpopReplay.recordDpopJti(payload.jti, expiresAt);
|
|
155
|
+
if (!recorded) {
|
|
156
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof jti was already used.', 'DPoP');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return calculateJwkThumbprint(publicJwk);
|
|
160
|
+
};
|
|
161
|
+
const serviceAuthErrorResponse = (c, error) => {
|
|
162
|
+
c.header('WWW-Authenticate', buildWwwAuthenticate(error));
|
|
163
|
+
return c.json({ error: { code: error.code, message: error.message } }, error.status);
|
|
164
|
+
};
|
|
165
|
+
const buildWwwAuthenticate = (error) => {
|
|
166
|
+
const params = [`error="${error.code}"`, `error_description="${error.message}"`];
|
|
167
|
+
return `${error.scheme} ${params.join(', ')}`;
|
|
168
|
+
};
|
|
169
|
+
const trimTrailingSlash = (value) => value.replace(/\/+$/u, '');
|
|
170
|
+
//# sourceMappingURL=service-auth-middleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-auth-middleware.js","sourceRoot":"","sources":["../../src/oauth/service-auth-middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,8 +49,22 @@ export interface DpopProofRecord {
|
|
|
49
49
|
expiresAt: Date;
|
|
50
50
|
createdAt: Date;
|
|
51
51
|
}
|
|
52
|
+
export interface ServiceClientRecord {
|
|
53
|
+
id: string;
|
|
54
|
+
clientId: string;
|
|
55
|
+
clientSecretHash: string;
|
|
56
|
+
displayName: string | null;
|
|
57
|
+
allowedScopes: string[];
|
|
58
|
+
resourceIndicators: string[];
|
|
59
|
+
dpopBoundAccessTokens: boolean;
|
|
60
|
+
tenantId: string | null;
|
|
61
|
+
secretRotatedAt: Date | null;
|
|
62
|
+
createdAt: Date;
|
|
63
|
+
revokedAt: Date | null;
|
|
64
|
+
}
|
|
52
65
|
export interface OauthStateStorePort {
|
|
53
66
|
findClient(clientId: string): Promise<OauthClientRecord | null>;
|
|
67
|
+
findServiceClient?(clientId: string): Promise<ServiceClientRecord | null>;
|
|
54
68
|
saveAuthCode(code: string, payload: AuthCodePayload, ttlSec: number): Promise<void>;
|
|
55
69
|
consumeAuthCode(code: string): Promise<AuthCodePayload | null>;
|
|
56
70
|
saveTokenMeta(jti: string, meta: TokenMeta, ttlSec: number): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-store-types.d.ts","sourceRoot":"","sources":["../../src/oauth/state-store-types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"state-store-types.d.ts","sourceRoot":"","sources":["../../src/oauth/state-store-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ export interface OAuthTokenHandlerOptions {
|
|
|
6
6
|
idTokenTtlSeconds?: number;
|
|
7
7
|
issuer: string;
|
|
8
8
|
ports: AuthHonoPorts;
|
|
9
|
+
serviceAccessTokenTtlSeconds?: number;
|
|
9
10
|
}
|
|
10
11
|
export declare const createOAuthTokenHandler: (options: OAuthTokenHandlerOptions) => (c: Context) => Promise<Response>;
|
|
11
12
|
//# sourceMappingURL=token-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/token-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"token-handler.d.ts","sourceRoot":"","sources":["../../src/oauth/token-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;AASrE,MAAM,WAAW,wBAAwB;IACvC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC;AAYD,eAAO,MAAM,uBAAuB,YACxB,wBAAwB,SACxB,OAAO,KAAG,QAAQ,QAAQ,CAqCnC,CAAC"}
|
|
@@ -2,10 +2,15 @@ import { createJwksService } from './jwks-service.js';
|
|
|
2
2
|
import { oauthJsonError } from './http-utils.js';
|
|
3
3
|
import { sha256Base64url } from './crypto-utils.js';
|
|
4
4
|
import { OAuthDpopProofError, verifyOAuthDpopProof } from './dpop.js';
|
|
5
|
+
const DEFAULT_SERVICE_ACCESS_TOKEN_TTL_SECONDS = 900;
|
|
5
6
|
export const createOAuthTokenHandler = (options) => async (c) => {
|
|
6
7
|
const form = new URLSearchParams(await c.req.text());
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const grantType = form.get('grant_type');
|
|
9
|
+
if (grantType === 'client_credentials') {
|
|
10
|
+
return handleClientCredentials(c, form, options);
|
|
11
|
+
}
|
|
12
|
+
if (grantType !== 'authorization_code') {
|
|
13
|
+
return oauthJsonError(c, 400, 'unsupported_grant_type', 'Only authorization_code and client_credentials grants are supported.');
|
|
9
14
|
}
|
|
10
15
|
const auth = await authenticateClient(c, form, options.ports);
|
|
11
16
|
if (auth instanceof Response)
|
|
@@ -89,6 +94,119 @@ const resolveDpopJkt = async (c, options, client, codePayload) => {
|
|
|
89
94
|
throw error;
|
|
90
95
|
}
|
|
91
96
|
};
|
|
97
|
+
const handleClientCredentials = async (c, form, options) => {
|
|
98
|
+
const findServiceClient = options.ports.oauthStateStore.findServiceClient;
|
|
99
|
+
if (!findServiceClient) {
|
|
100
|
+
return oauthJsonError(c, 400, 'unsupported_grant_type', 'The client_credentials grant is not supported.');
|
|
101
|
+
}
|
|
102
|
+
const auth = await authenticateServiceClient(c, form, options.ports, findServiceClient);
|
|
103
|
+
if (auth instanceof Response)
|
|
104
|
+
return auth;
|
|
105
|
+
const scope = resolveServiceScope(c, form, auth.client);
|
|
106
|
+
if (scope instanceof Response)
|
|
107
|
+
return scope;
|
|
108
|
+
const resource = resolveResourceIndicator(c, form, auth.client);
|
|
109
|
+
if (resource instanceof Response)
|
|
110
|
+
return resource;
|
|
111
|
+
const dpopJkt = await resolveServiceDpopJkt(c, options, auth.client);
|
|
112
|
+
if (dpopJkt instanceof Response)
|
|
113
|
+
return dpopJkt;
|
|
114
|
+
const tokens = await issueServiceToken(options, auth.client, scope, resource, dpopJkt);
|
|
115
|
+
return c.json(tokens);
|
|
116
|
+
};
|
|
117
|
+
const authenticateServiceClient = async (c, form, ports, findServiceClient) => {
|
|
118
|
+
const credentials = parseClientCredentials(c.req.header('authorization'), form);
|
|
119
|
+
if (!credentials.clientId || !credentials.secret) {
|
|
120
|
+
return oauthJsonError(c, 401, 'invalid_client', 'Client authentication is required.');
|
|
121
|
+
}
|
|
122
|
+
const client = await findServiceClient(credentials.clientId);
|
|
123
|
+
if (!client)
|
|
124
|
+
return oauthJsonError(c, 401, 'invalid_client', 'Client authentication failed.');
|
|
125
|
+
const secretHash = await ports.tokens.hashSecret(credentials.secret);
|
|
126
|
+
if (secretHash !== client.clientSecretHash) {
|
|
127
|
+
return oauthJsonError(c, 401, 'invalid_client', 'Client authentication failed.');
|
|
128
|
+
}
|
|
129
|
+
return { client, secret: credentials.secret };
|
|
130
|
+
};
|
|
131
|
+
const resolveServiceScope = (c, form, client) => {
|
|
132
|
+
const requested = (form.get('scope') ?? '').split(/\s+/).filter(Boolean);
|
|
133
|
+
if (requested.length === 0) {
|
|
134
|
+
return client.allowedScopes.join(' ');
|
|
135
|
+
}
|
|
136
|
+
const allowed = new Set(client.allowedScopes);
|
|
137
|
+
const unauthorized = requested.filter((scope) => !allowed.has(scope));
|
|
138
|
+
if (unauthorized.length > 0) {
|
|
139
|
+
return oauthJsonError(c, 400, 'invalid_scope', `Scope not allowed: ${unauthorized.join(' ')}.`);
|
|
140
|
+
}
|
|
141
|
+
return requested.join(' ');
|
|
142
|
+
};
|
|
143
|
+
const resolveResourceIndicator = (c, form, client) => {
|
|
144
|
+
const requested = form.get('resource');
|
|
145
|
+
const indicators = client.resourceIndicators;
|
|
146
|
+
if (requested) {
|
|
147
|
+
if (!indicators.includes(requested)) {
|
|
148
|
+
return oauthJsonError(c, 400, 'invalid_target', 'Requested resource is not allowed for this client.');
|
|
149
|
+
}
|
|
150
|
+
return requested;
|
|
151
|
+
}
|
|
152
|
+
if (indicators.length === 1) {
|
|
153
|
+
return indicators[0];
|
|
154
|
+
}
|
|
155
|
+
if (indicators.length === 0) {
|
|
156
|
+
return oauthJsonError(c, 400, 'invalid_target', 'A resource indicator is required for this client.');
|
|
157
|
+
}
|
|
158
|
+
return oauthJsonError(c, 400, 'invalid_target', 'A resource indicator must be specified when multiple are allowed.');
|
|
159
|
+
};
|
|
160
|
+
const resolveServiceDpopJkt = async (c, options, client) => {
|
|
161
|
+
if (!client.dpopBoundAccessTokens)
|
|
162
|
+
return null;
|
|
163
|
+
const proof = c.req.header('dpop');
|
|
164
|
+
if (!proof)
|
|
165
|
+
return oauthJsonError(c, 400, 'invalid_dpop_proof', 'DPoP proof is required.');
|
|
166
|
+
try {
|
|
167
|
+
const verified = await verifyOAuthDpopProof({
|
|
168
|
+
htm: 'POST',
|
|
169
|
+
htu: c.req.url,
|
|
170
|
+
iatSkewSeconds: options.dpopIatSkewSeconds,
|
|
171
|
+
ports: options.ports,
|
|
172
|
+
proof,
|
|
173
|
+
});
|
|
174
|
+
return verified.jkt;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
if (error instanceof OAuthDpopProofError) {
|
|
178
|
+
return oauthJsonError(c, 400, 'invalid_dpop_proof', error.message);
|
|
179
|
+
}
|
|
180
|
+
throw error;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const issueServiceToken = async (options, client, scope, resource, dpopJkt) => {
|
|
184
|
+
const ttlSeconds = options.serviceAccessTokenTtlSeconds ?? DEFAULT_SERVICE_ACCESS_TOKEN_TTL_SECONDS;
|
|
185
|
+
const now = options.ports.clock.now();
|
|
186
|
+
const expiresAt = options.ports.clock.addSeconds(now, ttlSeconds);
|
|
187
|
+
const cnf = dpopJkt ? { jkt: dpopJkt } : undefined;
|
|
188
|
+
const jwks = createJwksService({ clock: options.ports.clock, jwksPort: options.ports.jwks });
|
|
189
|
+
const accessJti = options.ports.random.uuid();
|
|
190
|
+
const accessToken = await jwks.signJwt({
|
|
191
|
+
client_id: client.clientId,
|
|
192
|
+
...(cnf ? { cnf } : {}),
|
|
193
|
+
scope,
|
|
194
|
+
}, {
|
|
195
|
+
audience: resource,
|
|
196
|
+
expiresAt,
|
|
197
|
+
issuer: trimTrailingSlash(options.issuer),
|
|
198
|
+
jti: accessJti,
|
|
199
|
+
subject: client.clientId,
|
|
200
|
+
type: 'JWT',
|
|
201
|
+
});
|
|
202
|
+
// Service tokens are stateless (BR39d-D5): no saveTokenMeta, no oauth_tokens row.
|
|
203
|
+
return {
|
|
204
|
+
access_token: accessToken,
|
|
205
|
+
expires_in: ttlSeconds,
|
|
206
|
+
scope,
|
|
207
|
+
token_type: dpopJkt ? 'DPoP' : 'Bearer',
|
|
208
|
+
};
|
|
209
|
+
};
|
|
92
210
|
const issueTokens = async (options, client, codePayload, user, dpopJkt) => {
|
|
93
211
|
const accessTokenTtlSeconds = options.accessTokenTtlSeconds ?? 3600;
|
|
94
212
|
const idTokenTtlSeconds = options.idTokenTtlSeconds ?? 3600;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-handler.js","sourceRoot":"","sources":["../../src/oauth/token-handler.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"token-handler.js","sourceRoot":"","sources":["../../src/oauth/token-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ export const createWellKnownRouter = (options) => {
|
|
|
9
9
|
claims_supported: ['sub', 'aud', 'iss', 'exp', 'iat', 'nonce', 'auth_time', 'acr', 'email', 'email_verified', 'name'],
|
|
10
10
|
code_challenge_methods_supported: ['S256'],
|
|
11
11
|
dpop_signing_alg_values_supported: ['EdDSA'],
|
|
12
|
-
grant_types_supported: ['authorization_code'],
|
|
12
|
+
grant_types_supported: ['authorization_code', 'client_credentials'],
|
|
13
13
|
id_token_signing_alg_values_supported: ['EdDSA'],
|
|
14
14
|
introspection_endpoint: `${issuer}${oauthPrefix}/introspect`,
|
|
15
15
|
issuer,
|
|
@@ -19,7 +19,7 @@ export const createWellKnownRouter = (options) => {
|
|
|
19
19
|
scopes_supported: ['openid', 'profile', 'email'],
|
|
20
20
|
subject_types_supported: ['public'],
|
|
21
21
|
token_endpoint: `${issuer}${oauthPrefix}/token`,
|
|
22
|
-
token_endpoint_auth_methods_supported: ['client_secret_basic', 'none'],
|
|
22
|
+
token_endpoint_auth_methods_supported: ['client_secret_basic', 'client_secret_post', 'none'],
|
|
23
23
|
userinfo_endpoint: `${issuer}${oauthPrefix}/userinfo`,
|
|
24
24
|
}));
|
|
25
25
|
router.get('/jwks.json', async (c) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wellknown-handler.js","sourceRoot":"","sources":["../../src/oauth/wellknown-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAQtD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAAqC,EAAQ,EAAE;IACnF,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,mBAAmB,CAAC,OAAO,CAAC,eAAe,IAAI,oBAAoB,CAAC,CAAC;IAEzF,MAAM,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC,EAAE,EAAE,CACxC,CAAC,CAAC,IAAI,CAAC;QACL,sBAAsB,EAAE,GAAG,MAAM,GAAG,WAAW,YAAY;QAC3D,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC;QACrH,gCAAgC,EAAE,CAAC,MAAM,CAAC;QAC1C,iCAAiC,EAAE,CAAC,OAAO,CAAC;QAC5C,qBAAqB,EAAE,CAAC,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"wellknown-handler.js","sourceRoot":"","sources":["../../src/oauth/wellknown-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAQtD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAAqC,EAAQ,EAAE;IACnF,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,mBAAmB,CAAC,OAAO,CAAC,eAAe,IAAI,oBAAoB,CAAC,CAAC;IAEzF,MAAM,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC,EAAE,EAAE,CACxC,CAAC,CAAC,IAAI,CAAC;QACL,sBAAsB,EAAE,GAAG,MAAM,GAAG,WAAW,YAAY;QAC3D,gBAAgB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC;QACrH,gCAAgC,EAAE,CAAC,MAAM,CAAC;QAC1C,iCAAiC,EAAE,CAAC,OAAO,CAAC;QAC5C,qBAAqB,EAAE,CAAC,oBAAoB,EAAE,oBAAoB,CAAC;QACnE,qCAAqC,EAAE,CAAC,OAAO,CAAC;QAChD,sBAAsB,EAAE,GAAG,MAAM,GAAG,WAAW,aAAa;QAC5D,MAAM;QACN,QAAQ,EAAE,GAAG,MAAM,wBAAwB;QAC3C,wBAAwB,EAAE,CAAC,MAAM,CAAC;QAClC,mBAAmB,EAAE,GAAG,MAAM,GAAG,WAAW,SAAS;QACrD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC;QAChD,uBAAuB,EAAE,CAAC,QAAQ,CAAC;QACnC,cAAc,EAAE,GAAG,MAAM,GAAG,WAAW,QAAQ;QAC/C,qCAAqC,EAAE,CAAC,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,CAAC;QAC5F,iBAAiB,EAAE,GAAG,MAAM,GAAG,WAAW,WAAW;KACtD,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7F,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;QACjD,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAEhF,MAAM,mBAAmB,GAAG,CAAC,KAAa,EAAU,EAAE;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACtC,CAAC,CAAC"}
|
package/dist/ports.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { JwksPort, OauthStateStorePort } from './oauth/state-store-types.js';
|
|
2
|
-
export type { AuthCodePayload, DpopProofRecord, JwksKeyRecord, JwksPort, JwksPublicJwk, OauthClientRecord, OauthStateStorePort, OauthTokenType, TokenMeta, } from './oauth/state-store-types.js';
|
|
2
|
+
export type { AuthCodePayload, DpopProofRecord, JwksKeyRecord, JwksPort, JwksPublicJwk, OauthClientRecord, OauthStateStorePort, OauthTokenType, ServiceClientRecord, TokenMeta, } from './oauth/state-store-types.js';
|
|
3
3
|
export type AuthHonoAccountStatus = 'active' | 'pending_admin_approval' | 'approval_expired_readonly' | 'disabled_by_user' | 'disabled_by_admin' | (string & {});
|
|
4
4
|
export type AuthHonoChallengeType = 'registration' | 'authentication';
|
|
5
5
|
export interface AuthHonoDeviceInfo {
|
package/dist/ports.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../src/ports.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from './oauth/introspect-handler.js';
|
|
|
12
12
|
export * from './oauth/jwks-service.js';
|
|
13
13
|
export * from './oauth/router.js';
|
|
14
14
|
export * from './oauth/revoke-handler.js';
|
|
15
|
+
export * from './oauth/service-auth-middleware.js';
|
|
15
16
|
export * from './oauth/session-resolver.js';
|
|
16
17
|
export * from './oauth/state-store-types.js';
|
|
17
18
|
export * from './oauth/state-codec.js';
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import {
|
|
2
|
+
calculateJwkThumbprint,
|
|
3
|
+
decodeProtectedHeader,
|
|
4
|
+
importJWK,
|
|
5
|
+
jwtVerify,
|
|
6
|
+
type JWK,
|
|
7
|
+
type JWTPayload,
|
|
8
|
+
} from 'jose';
|
|
9
|
+
import type { Context, MiddlewareHandler } from 'hono';
|
|
10
|
+
|
|
11
|
+
import type { AuthHonoClockPort } from '../ports.js';
|
|
12
|
+
import { sha256Base64url } from './crypto-utils.js';
|
|
13
|
+
import type { JwksPort, OauthStateStorePort } from './state-store-types.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Narrow port set for resource-server verification (BR39d-D6). Resource servers
|
|
17
|
+
* must not construct users/credentials/sessions/email ports just to verify a
|
|
18
|
+
* bearer or DPoP-bound access token.
|
|
19
|
+
*/
|
|
20
|
+
export interface ServiceAuthPorts {
|
|
21
|
+
clock: AuthHonoClockPort;
|
|
22
|
+
jwks: JwksPort;
|
|
23
|
+
dpopReplay?: Pick<OauthStateStorePort, 'recordDpopJti'>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ServiceAuthContext {
|
|
27
|
+
clientId: string;
|
|
28
|
+
scopes: string[];
|
|
29
|
+
jkt: string | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface CreateRequireServiceAuthOptions {
|
|
33
|
+
issuer: string;
|
|
34
|
+
requiredScopes?: string[];
|
|
35
|
+
resource: string;
|
|
36
|
+
ports: ServiceAuthPorts;
|
|
37
|
+
/** DPoP proof iat acceptance window in seconds (default 60). */
|
|
38
|
+
dpopIatSkewSeconds?: number;
|
|
39
|
+
/** Context key the verified service-client context is stored under (default 'serviceClient'). */
|
|
40
|
+
contextKey?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class ServiceAuthError extends Error {
|
|
44
|
+
constructor(
|
|
45
|
+
readonly status: 401 | 403,
|
|
46
|
+
readonly code: string,
|
|
47
|
+
message: string,
|
|
48
|
+
readonly scheme: 'Bearer' | 'DPoP' = 'Bearer'
|
|
49
|
+
) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.name = 'ServiceAuthError';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const createRequireServiceAuth = (
|
|
56
|
+
options: CreateRequireServiceAuthOptions
|
|
57
|
+
): MiddlewareHandler => {
|
|
58
|
+
const issuer = trimTrailingSlash(options.issuer);
|
|
59
|
+
const requiredScopes = options.requiredScopes ?? [];
|
|
60
|
+
const contextKey = options.contextKey ?? 'serviceClient';
|
|
61
|
+
|
|
62
|
+
return async (c, next) => {
|
|
63
|
+
try {
|
|
64
|
+
const { scheme, token } = parseAuthorization(c.req.header('authorization'));
|
|
65
|
+
const payload = await verifyAccessToken(token, options.ports, issuer, options.resource);
|
|
66
|
+
const scopes = parseScopes(payload.scope);
|
|
67
|
+
assertScopes(scopes, requiredScopes);
|
|
68
|
+
|
|
69
|
+
const jkt = await enforceDpop(c, payload, token, scheme, options);
|
|
70
|
+
|
|
71
|
+
const serviceContext: ServiceAuthContext = {
|
|
72
|
+
clientId: typeof payload.client_id === 'string' ? payload.client_id : String(payload.sub ?? ''),
|
|
73
|
+
jkt,
|
|
74
|
+
scopes,
|
|
75
|
+
};
|
|
76
|
+
c.set(contextKey, serviceContext);
|
|
77
|
+
|
|
78
|
+
await next();
|
|
79
|
+
} catch (error) {
|
|
80
|
+
if (error instanceof ServiceAuthError) {
|
|
81
|
+
return serviceAuthErrorResponse(c, error);
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const parseAuthorization = (header: string | undefined): { scheme: 'Bearer' | 'DPoP'; token: string } => {
|
|
89
|
+
if (!header) {
|
|
90
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Authorization header is required.');
|
|
91
|
+
}
|
|
92
|
+
const [scheme, token] = header.split(/\s+/, 2);
|
|
93
|
+
if (!token) {
|
|
94
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Authorization header is malformed.');
|
|
95
|
+
}
|
|
96
|
+
if (scheme === 'Bearer') return { scheme: 'Bearer', token };
|
|
97
|
+
if (scheme === 'DPoP') return { scheme: 'DPoP', token };
|
|
98
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Unsupported authorization scheme.');
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const verifyAccessToken = async (
|
|
102
|
+
token: string,
|
|
103
|
+
ports: ServiceAuthPorts,
|
|
104
|
+
issuer: string,
|
|
105
|
+
resource: string
|
|
106
|
+
): Promise<JWTPayload & { scope?: unknown; client_id?: unknown; cnf?: { jkt?: string } }> => {
|
|
107
|
+
let kid: string | undefined;
|
|
108
|
+
try {
|
|
109
|
+
kid = decodeProtectedHeader(token).kid;
|
|
110
|
+
} catch {
|
|
111
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token header is invalid.');
|
|
112
|
+
}
|
|
113
|
+
if (!kid) {
|
|
114
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token is missing a key id.');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const key = await ports.jwks.findKeyByKid(kid);
|
|
118
|
+
if (!key) {
|
|
119
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token signing key is unknown.');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const publicKey = await importJWK(key.publicJwk, key.alg);
|
|
123
|
+
const currentDate = ports.clock.now();
|
|
124
|
+
try {
|
|
125
|
+
const { payload } = await jwtVerify(token, publicKey, {
|
|
126
|
+
audience: resource,
|
|
127
|
+
currentDate,
|
|
128
|
+
issuer,
|
|
129
|
+
});
|
|
130
|
+
return payload;
|
|
131
|
+
} catch {
|
|
132
|
+
throw new ServiceAuthError(401, 'invalid_token', 'Access token is invalid, expired, or has the wrong audience.');
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const parseScopes = (scope: unknown): string[] =>
|
|
137
|
+
typeof scope === 'string' ? scope.split(/\s+/).filter(Boolean) : [];
|
|
138
|
+
|
|
139
|
+
const assertScopes = (scopes: string[], requiredScopes: string[]): void => {
|
|
140
|
+
const granted = new Set(scopes);
|
|
141
|
+
const missing = requiredScopes.filter((scope) => !granted.has(scope));
|
|
142
|
+
if (missing.length > 0) {
|
|
143
|
+
throw new ServiceAuthError(403, 'insufficient_scope', `Missing required scope: ${missing.join(' ')}.`);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const enforceDpop = async (
|
|
148
|
+
c: Context,
|
|
149
|
+
payload: { cnf?: { jkt?: string } },
|
|
150
|
+
accessToken: string,
|
|
151
|
+
scheme: 'Bearer' | 'DPoP',
|
|
152
|
+
options: CreateRequireServiceAuthOptions
|
|
153
|
+
): Promise<string | null> => {
|
|
154
|
+
const boundJkt = payload.cnf?.jkt;
|
|
155
|
+
if (!boundJkt) return null;
|
|
156
|
+
|
|
157
|
+
if (scheme !== 'DPoP') {
|
|
158
|
+
throw new ServiceAuthError(401, 'invalid_token', 'DPoP-bound token requires the DPoP authorization scheme.', 'DPoP');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const proof = c.req.header('dpop');
|
|
162
|
+
if (!proof) {
|
|
163
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof is required.', 'DPoP');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const verifiedJkt = await verifyServiceDpopProof({
|
|
167
|
+
accessToken,
|
|
168
|
+
htm: c.req.method,
|
|
169
|
+
htu: c.req.url,
|
|
170
|
+
iatSkewSeconds: options.dpopIatSkewSeconds,
|
|
171
|
+
ports: options.ports,
|
|
172
|
+
proof,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
if (verifiedJkt !== boundJkt) {
|
|
176
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof key does not match the bound token.', 'DPoP');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return verifiedJkt;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
interface VerifyServiceDpopProofOptions {
|
|
183
|
+
accessToken: string;
|
|
184
|
+
htm: string;
|
|
185
|
+
htu: string;
|
|
186
|
+
iatSkewSeconds?: number;
|
|
187
|
+
ports: ServiceAuthPorts;
|
|
188
|
+
proof: string;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const verifyServiceDpopProof = async (options: VerifyServiceDpopProofOptions): Promise<string> => {
|
|
192
|
+
const header = decodeProtectedHeader(options.proof);
|
|
193
|
+
const publicJwk = header.jwk as JWK | undefined;
|
|
194
|
+
if (!publicJwk || !header.alg || header.typ !== 'dpop+jwt') {
|
|
195
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof header is invalid.', 'DPoP');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const key = await importJWK(publicJwk, header.alg);
|
|
199
|
+
let payload: JWTPayload;
|
|
200
|
+
try {
|
|
201
|
+
({ payload } = await jwtVerify(options.proof, key));
|
|
202
|
+
} catch {
|
|
203
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof signature is invalid.', 'DPoP');
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const skew = options.iatSkewSeconds ?? 60;
|
|
207
|
+
if (payload.htm !== options.htm.toUpperCase()) {
|
|
208
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP htm claim does not match the request method.', 'DPoP');
|
|
209
|
+
}
|
|
210
|
+
if (payload.htu !== options.htu) {
|
|
211
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP htu claim does not match the request URL.', 'DPoP');
|
|
212
|
+
}
|
|
213
|
+
if (!payload.jti || typeof payload.jti !== 'string') {
|
|
214
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP jti claim is required.', 'DPoP');
|
|
215
|
+
}
|
|
216
|
+
if (typeof payload.iat !== 'number') {
|
|
217
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP iat claim is required.', 'DPoP');
|
|
218
|
+
}
|
|
219
|
+
const nowSeconds = Math.floor(options.ports.clock.now().getTime() / 1000);
|
|
220
|
+
if (Math.abs(payload.iat - nowSeconds) > skew) {
|
|
221
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP iat claim is outside the allowed skew.', 'DPoP');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// RFC 9449 §4.3: bind the proof to the access token (BR39d-D7).
|
|
225
|
+
if (payload.ath !== (await sha256Base64url(options.accessToken))) {
|
|
226
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP ath claim does not match the access token.', 'DPoP');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (options.ports.dpopReplay) {
|
|
230
|
+
const expiresAt = options.ports.clock.addSeconds(options.ports.clock.now(), skew);
|
|
231
|
+
const recorded = await options.ports.dpopReplay.recordDpopJti(payload.jti, expiresAt);
|
|
232
|
+
if (!recorded) {
|
|
233
|
+
throw new ServiceAuthError(401, 'invalid_dpop_proof', 'DPoP proof jti was already used.', 'DPoP');
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return calculateJwkThumbprint(publicJwk);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const serviceAuthErrorResponse = (c: Context, error: ServiceAuthError): Response => {
|
|
241
|
+
c.header('WWW-Authenticate', buildWwwAuthenticate(error));
|
|
242
|
+
return c.json({ error: { code: error.code, message: error.message } }, error.status);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const buildWwwAuthenticate = (error: ServiceAuthError): string => {
|
|
246
|
+
const params = [`error="${error.code}"`, `error_description="${error.message}"`];
|
|
247
|
+
return `${error.scheme} ${params.join(', ')}`;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const trimTrailingSlash = (value: string): string => value.replace(/\/+$/u, '');
|
|
@@ -55,8 +55,23 @@ export interface DpopProofRecord {
|
|
|
55
55
|
createdAt: Date;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
export interface ServiceClientRecord {
|
|
59
|
+
id: string;
|
|
60
|
+
clientId: string;
|
|
61
|
+
clientSecretHash: string;
|
|
62
|
+
displayName: string | null;
|
|
63
|
+
allowedScopes: string[];
|
|
64
|
+
resourceIndicators: string[];
|
|
65
|
+
dpopBoundAccessTokens: boolean;
|
|
66
|
+
tenantId: string | null;
|
|
67
|
+
secretRotatedAt: Date | null;
|
|
68
|
+
createdAt: Date;
|
|
69
|
+
revokedAt: Date | null;
|
|
70
|
+
}
|
|
71
|
+
|
|
58
72
|
export interface OauthStateStorePort {
|
|
59
73
|
findClient(clientId: string): Promise<OauthClientRecord | null>;
|
|
74
|
+
findServiceClient?(clientId: string): Promise<ServiceClientRecord | null>;
|
|
60
75
|
saveAuthCode(code: string, payload: AuthCodePayload, ttlSec: number): Promise<void>;
|
|
61
76
|
consumeAuthCode(code: string): Promise<AuthCodePayload | null>;
|
|
62
77
|
saveTokenMeta(jti: string, meta: TokenMeta, ttlSec: number): Promise<void>;
|
|
@@ -5,7 +5,9 @@ import { createJwksService } from './jwks-service.js';
|
|
|
5
5
|
import { oauthJsonError } from './http-utils.js';
|
|
6
6
|
import { sha256Base64url } from './crypto-utils.js';
|
|
7
7
|
import { OAuthDpopProofError, verifyOAuthDpopProof } from './dpop.js';
|
|
8
|
-
import type { AuthCodePayload, OauthClientRecord, TokenMeta } from './state-store-types.js';
|
|
8
|
+
import type { AuthCodePayload, OauthClientRecord, ServiceClientRecord, TokenMeta } from './state-store-types.js';
|
|
9
|
+
|
|
10
|
+
const DEFAULT_SERVICE_ACCESS_TOKEN_TTL_SECONDS = 900;
|
|
9
11
|
|
|
10
12
|
export interface OAuthTokenHandlerOptions {
|
|
11
13
|
accessTokenTtlSeconds?: number;
|
|
@@ -13,6 +15,7 @@ export interface OAuthTokenHandlerOptions {
|
|
|
13
15
|
idTokenTtlSeconds?: number;
|
|
14
16
|
issuer: string;
|
|
15
17
|
ports: AuthHonoPorts;
|
|
18
|
+
serviceAccessTokenTtlSeconds?: number;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
interface ClientAuthentication {
|
|
@@ -20,12 +23,26 @@ interface ClientAuthentication {
|
|
|
20
23
|
secret?: string;
|
|
21
24
|
}
|
|
22
25
|
|
|
26
|
+
interface ServiceClientAuthentication {
|
|
27
|
+
client: ServiceClientRecord;
|
|
28
|
+
secret: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
export const createOAuthTokenHandler =
|
|
24
32
|
(options: OAuthTokenHandlerOptions) =>
|
|
25
33
|
async (c: Context): Promise<Response> => {
|
|
26
34
|
const form = new URLSearchParams(await c.req.text());
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
const grantType = form.get('grant_type');
|
|
36
|
+
if (grantType === 'client_credentials') {
|
|
37
|
+
return handleClientCredentials(c, form, options);
|
|
38
|
+
}
|
|
39
|
+
if (grantType !== 'authorization_code') {
|
|
40
|
+
return oauthJsonError(
|
|
41
|
+
c,
|
|
42
|
+
400,
|
|
43
|
+
'unsupported_grant_type',
|
|
44
|
+
'Only authorization_code and client_credentials grants are supported.'
|
|
45
|
+
);
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
const auth = await authenticateClient(c, form, options.ports);
|
|
@@ -131,6 +148,160 @@ const resolveDpopJkt = async (
|
|
|
131
148
|
}
|
|
132
149
|
};
|
|
133
150
|
|
|
151
|
+
const handleClientCredentials = async (
|
|
152
|
+
c: Context,
|
|
153
|
+
form: URLSearchParams,
|
|
154
|
+
options: OAuthTokenHandlerOptions
|
|
155
|
+
): Promise<Response> => {
|
|
156
|
+
const findServiceClient = options.ports.oauthStateStore.findServiceClient;
|
|
157
|
+
if (!findServiceClient) {
|
|
158
|
+
return oauthJsonError(c, 400, 'unsupported_grant_type', 'The client_credentials grant is not supported.');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const auth = await authenticateServiceClient(c, form, options.ports, findServiceClient);
|
|
162
|
+
if (auth instanceof Response) return auth;
|
|
163
|
+
|
|
164
|
+
const scope = resolveServiceScope(c, form, auth.client);
|
|
165
|
+
if (scope instanceof Response) return scope;
|
|
166
|
+
|
|
167
|
+
const resource = resolveResourceIndicator(c, form, auth.client);
|
|
168
|
+
if (resource instanceof Response) return resource;
|
|
169
|
+
|
|
170
|
+
const dpopJkt = await resolveServiceDpopJkt(c, options, auth.client);
|
|
171
|
+
if (dpopJkt instanceof Response) return dpopJkt;
|
|
172
|
+
|
|
173
|
+
const tokens = await issueServiceToken(options, auth.client, scope, resource, dpopJkt);
|
|
174
|
+
return c.json(tokens);
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const authenticateServiceClient = async (
|
|
178
|
+
c: Context,
|
|
179
|
+
form: URLSearchParams,
|
|
180
|
+
ports: AuthHonoPorts,
|
|
181
|
+
findServiceClient: NonNullable<AuthHonoPorts['oauthStateStore']['findServiceClient']>
|
|
182
|
+
): Promise<ServiceClientAuthentication | Response> => {
|
|
183
|
+
const credentials = parseClientCredentials(c.req.header('authorization'), form);
|
|
184
|
+
if (!credentials.clientId || !credentials.secret) {
|
|
185
|
+
return oauthJsonError(c, 401, 'invalid_client', 'Client authentication is required.');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const client = await findServiceClient(credentials.clientId);
|
|
189
|
+
if (!client) return oauthJsonError(c, 401, 'invalid_client', 'Client authentication failed.');
|
|
190
|
+
|
|
191
|
+
const secretHash = await ports.tokens.hashSecret(credentials.secret);
|
|
192
|
+
if (secretHash !== client.clientSecretHash) {
|
|
193
|
+
return oauthJsonError(c, 401, 'invalid_client', 'Client authentication failed.');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return { client, secret: credentials.secret };
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const resolveServiceScope = (
|
|
200
|
+
c: Context,
|
|
201
|
+
form: URLSearchParams,
|
|
202
|
+
client: ServiceClientRecord
|
|
203
|
+
): string | Response => {
|
|
204
|
+
const requested = (form.get('scope') ?? '').split(/\s+/).filter(Boolean);
|
|
205
|
+
if (requested.length === 0) {
|
|
206
|
+
return client.allowedScopes.join(' ');
|
|
207
|
+
}
|
|
208
|
+
const allowed = new Set(client.allowedScopes);
|
|
209
|
+
const unauthorized = requested.filter((scope) => !allowed.has(scope));
|
|
210
|
+
if (unauthorized.length > 0) {
|
|
211
|
+
return oauthJsonError(c, 400, 'invalid_scope', `Scope not allowed: ${unauthorized.join(' ')}.`);
|
|
212
|
+
}
|
|
213
|
+
return requested.join(' ');
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const resolveResourceIndicator = (
|
|
217
|
+
c: Context,
|
|
218
|
+
form: URLSearchParams,
|
|
219
|
+
client: ServiceClientRecord
|
|
220
|
+
): string | Response => {
|
|
221
|
+
const requested = form.get('resource');
|
|
222
|
+
const indicators = client.resourceIndicators;
|
|
223
|
+
|
|
224
|
+
if (requested) {
|
|
225
|
+
if (!indicators.includes(requested)) {
|
|
226
|
+
return oauthJsonError(c, 400, 'invalid_target', 'Requested resource is not allowed for this client.');
|
|
227
|
+
}
|
|
228
|
+
return requested;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (indicators.length === 1) {
|
|
232
|
+
return indicators[0];
|
|
233
|
+
}
|
|
234
|
+
if (indicators.length === 0) {
|
|
235
|
+
return oauthJsonError(c, 400, 'invalid_target', 'A resource indicator is required for this client.');
|
|
236
|
+
}
|
|
237
|
+
return oauthJsonError(c, 400, 'invalid_target', 'A resource indicator must be specified when multiple are allowed.');
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const resolveServiceDpopJkt = async (
|
|
241
|
+
c: Context,
|
|
242
|
+
options: OAuthTokenHandlerOptions,
|
|
243
|
+
client: ServiceClientRecord
|
|
244
|
+
): Promise<string | null | Response> => {
|
|
245
|
+
if (!client.dpopBoundAccessTokens) return null;
|
|
246
|
+
|
|
247
|
+
const proof = c.req.header('dpop');
|
|
248
|
+
if (!proof) return oauthJsonError(c, 400, 'invalid_dpop_proof', 'DPoP proof is required.');
|
|
249
|
+
|
|
250
|
+
try {
|
|
251
|
+
const verified = await verifyOAuthDpopProof({
|
|
252
|
+
htm: 'POST',
|
|
253
|
+
htu: c.req.url,
|
|
254
|
+
iatSkewSeconds: options.dpopIatSkewSeconds,
|
|
255
|
+
ports: options.ports,
|
|
256
|
+
proof,
|
|
257
|
+
});
|
|
258
|
+
return verified.jkt;
|
|
259
|
+
} catch (error) {
|
|
260
|
+
if (error instanceof OAuthDpopProofError) {
|
|
261
|
+
return oauthJsonError(c, 400, 'invalid_dpop_proof', error.message);
|
|
262
|
+
}
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const issueServiceToken = async (
|
|
268
|
+
options: OAuthTokenHandlerOptions,
|
|
269
|
+
client: ServiceClientRecord,
|
|
270
|
+
scope: string,
|
|
271
|
+
resource: string,
|
|
272
|
+
dpopJkt: string | null
|
|
273
|
+
) => {
|
|
274
|
+
const ttlSeconds = options.serviceAccessTokenTtlSeconds ?? DEFAULT_SERVICE_ACCESS_TOKEN_TTL_SECONDS;
|
|
275
|
+
const now = options.ports.clock.now();
|
|
276
|
+
const expiresAt = options.ports.clock.addSeconds(now, ttlSeconds);
|
|
277
|
+
const cnf = dpopJkt ? { jkt: dpopJkt } : undefined;
|
|
278
|
+
const jwks = createJwksService({ clock: options.ports.clock, jwksPort: options.ports.jwks });
|
|
279
|
+
const accessJti = options.ports.random.uuid();
|
|
280
|
+
const accessToken = await jwks.signJwt(
|
|
281
|
+
{
|
|
282
|
+
client_id: client.clientId,
|
|
283
|
+
...(cnf ? { cnf } : {}),
|
|
284
|
+
scope,
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
audience: resource,
|
|
288
|
+
expiresAt,
|
|
289
|
+
issuer: trimTrailingSlash(options.issuer),
|
|
290
|
+
jti: accessJti,
|
|
291
|
+
subject: client.clientId,
|
|
292
|
+
type: 'JWT',
|
|
293
|
+
}
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
// Service tokens are stateless (BR39d-D5): no saveTokenMeta, no oauth_tokens row.
|
|
297
|
+
return {
|
|
298
|
+
access_token: accessToken,
|
|
299
|
+
expires_in: ttlSeconds,
|
|
300
|
+
scope,
|
|
301
|
+
token_type: dpopJkt ? 'DPoP' : 'Bearer',
|
|
302
|
+
};
|
|
303
|
+
};
|
|
304
|
+
|
|
134
305
|
const issueTokens = async (
|
|
135
306
|
options: OAuthTokenHandlerOptions,
|
|
136
307
|
client: OauthClientRecord,
|
|
@@ -20,7 +20,7 @@ export const createWellKnownRouter = (options: CreateWellKnownRouterOptions): Ho
|
|
|
20
20
|
claims_supported: ['sub', 'aud', 'iss', 'exp', 'iat', 'nonce', 'auth_time', 'acr', 'email', 'email_verified', 'name'],
|
|
21
21
|
code_challenge_methods_supported: ['S256'],
|
|
22
22
|
dpop_signing_alg_values_supported: ['EdDSA'],
|
|
23
|
-
grant_types_supported: ['authorization_code'],
|
|
23
|
+
grant_types_supported: ['authorization_code', 'client_credentials'],
|
|
24
24
|
id_token_signing_alg_values_supported: ['EdDSA'],
|
|
25
25
|
introspection_endpoint: `${issuer}${oauthPrefix}/introspect`,
|
|
26
26
|
issuer,
|
|
@@ -30,7 +30,7 @@ export const createWellKnownRouter = (options: CreateWellKnownRouterOptions): Ho
|
|
|
30
30
|
scopes_supported: ['openid', 'profile', 'email'],
|
|
31
31
|
subject_types_supported: ['public'],
|
|
32
32
|
token_endpoint: `${issuer}${oauthPrefix}/token`,
|
|
33
|
-
token_endpoint_auth_methods_supported: ['client_secret_basic', 'none'],
|
|
33
|
+
token_endpoint_auth_methods_supported: ['client_secret_basic', 'client_secret_post', 'none'],
|
|
34
34
|
userinfo_endpoint: `${issuer}${oauthPrefix}/userinfo`,
|
|
35
35
|
})
|
|
36
36
|
);
|