@maronn-openid-connect/experimental 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 maronnjapan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # @maronn-openid-connect/experimental
2
+
3
+ このディレクトリは試験的に実装したもので、まだ正式にライブラリの機能として提供できていない機能をまとめたものとなります。
4
+
5
+ ## 位置づけ
6
+
7
+ - `@maronn-openid-connect/core` とは**別 package**です。core の通常動作にこのコードが読み込まれることはありません。
8
+ - **API は安定していません。** マイナーリリースでも破壊的に変更されることがあります。本番利用する場合はバージョンを固定してください。
9
+ - CLI で `--enable <feature-id>` を明示したときだけ、生成コードがこの package を利用します。デフォルトでは一切参照されません。
10
+
11
+ ## 提供機能
12
+
13
+ | feature-id | 内容 | 準拠仕様 | import 元 |
14
+ |---|---|---|---|
15
+ | `par` | Pushed Authorization Requests | RFC 9126 | `@maronn-openid-connect/experimental/par` |
16
+ | `token-exchange` | OAuth 2.0 Token Exchange (impersonation) | RFC 8693 | `@maronn-openid-connect/experimental/token-exchange` |
17
+
18
+ 機能ごとに subpath export で提供します。ルート (`.`) からの再エクスポートは提供しません。機能間でコードを共有しないことで、昇格・削除時に他機能へ影響しない構造を保っています。
19
+
20
+ ```bash
21
+ maronn-oidc generate hono --enable par
22
+ pnpm add @maronn-openid-connect/core @maronn-openid-connect/experimental
23
+ ```
24
+
25
+ ```typescript
26
+ import { handlePushedAuthorizationRequest } from '@maronn-openid-connect/experimental/par';
27
+ ```
28
+
29
+ ## core とのバージョン関係
30
+
31
+ `@maronn-openid-connect/core` はこの package の **peerDependency** です(`dependencies` ではありません)。
32
+
33
+ experimental は core のエラークラス(`AuthorizationError` / `TokenError`)を `instanceof` で判定し、resolver / store を生成コードと受け渡しします。そのためアプリ全体で core のインスタンスが 1 つである必要があります。core を `dependencies` として同梱すると、生成コードが読み込む core と experimental が読み込む core が別インスタンスになり、`instanceof` 判定が静かに false になって、本来 `invalid_request` を返すべき場面が 500 になります。peerDependency にしておくと利用者のアプリが持つ core がそのまま使われるため、この事故が起きません。
34
+
35
+ **バージョン番号は揃っている必要はありません。** experimental は core より速く publish されるため、`core 0.1.0` + `experimental 0.5.0` のような組み合わせが正常な状態です。互換性の条件は peer range(`>=0.1.0 <1.0.0`)の下限を満たしていることだけで、experimental が新しい core の API を必要とし始めたときにこの下限が上がります。下限を満たしていない場合は npm ならインストールが `ERESOLVE` で失敗し、pnpm なら `✕ unmet peer @maronn-openid-connect/core` が警告されます。
36
+
37
+ > **`@maronn-openid-connect/experimental@0.0.1` は `@maronn-openid-connect/core@0.0.1` と組み合わせて使えません。**
38
+ > 0.0.1 は core のステップ関数(`extractClientCredentials` など)を import しているのに、
39
+ > それらを export する core がまだ publish されていない状態で公開されました。この組み合わせでは
40
+ > バンドル時に esbuild が `No matching export ... for import "extractClientCredentials"` で落ちます。
41
+ > peer range の下限を `>=0.1.0` へ上げて組み合わせられないようにしてあるので、両方を最新へ更新してください。
42
+
43
+ > リポジトリ側では、core を minor / major で上げるときに experimental も同時にリリースすること、および peer range の下限が「次に publish される core」以上であることを CI で強制しています(`.github/scripts/verify-release-contract.mjs`)。詳細は [RELEASE.md](../../RELEASE.md) の「バージョニング方針」を参照してください。
44
+
45
+ ## 依存方向
46
+
47
+ ```text
48
+ packages/cli ────> @maronn-openid-connect/experimental(生成コードの依存として明示)
49
+ @maronn-openid-connect/experimental ────> @maronn-openid-connect/core(許可)
50
+ packages/core ──X──> packages/experimental(禁止)
51
+ ```
52
+
53
+ ## 昇格条件
54
+
55
+ Experimental 機能が core へ昇格する目安は次のとおりです。
56
+
57
+ 1. 生成 OP の conformance テストが 2 サイクル以上安定していること
58
+ 2. resolver / store 契約への変更要望が収束していること
59
+ 3. その仕様がリポジトリのロードマップ(例: FAPI 2.0 対応)で必須になったこと
60
+
61
+ 昇格するとその機能は `@maronn-openid-connect/core` へ移り、この package からは削除されます。
62
+
63
+ ## 利用者ドキュメント
64
+
65
+ `docs/library-document` の Experimental セクションを参照してください。
@@ -0,0 +1,4 @@
1
+ export { ParError, assertParExpiresInSeconds, authenticateParClient, buildPushedAuthorizationResponse, createPushedAuthorizationRecord, handlePushedAuthorizationRequest, rejectForbiddenParParams, validatePushedAuthorizationParams, type ParErrorCode, type PushedAuthorizationRequestContext, type PushedAuthorizationResponse, } from './par-request.js';
2
+ export { PushedRequestUriError, assertPushedRequestUsed, resolvePushedRequestUri, } from './resolve-request-uri.js';
3
+ export { PAR_REQUEST_URI_PREFIX, type PushedAuthorizationRecord, type PushedAuthorizationRequestStore, } from './store.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/par/index.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,QAAQ,EACR,yBAAyB,EACzB,qBAAqB,EACrB,gCAAgC,EAChC,+BAA+B,EAC/B,gCAAgC,EAChC,wBAAwB,EACxB,iCAAiC,EACjC,KAAK,YAAY,EACjB,KAAK,iCAAiC,EACtC,KAAK,2BAA2B,GACjC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,sBAAsB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,GACrC,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { ParError, assertParExpiresInSeconds, authenticateParClient, buildPushedAuthorizationResponse, createPushedAuthorizationRecord, handlePushedAuthorizationRequest, rejectForbiddenParParams, validatePushedAuthorizationParams, } from './par-request.js';
2
+ export { PushedRequestUriError, assertPushedRequestUsed, resolvePushedRequestUri, } from './resolve-request-uri.js';
3
+ export { PAR_REQUEST_URI_PREFIX, } from './store.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/par/index.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,QAAQ,EACR,yBAAyB,EACzB,qBAAqB,EACrB,gCAAgC,EAChC,+BAA+B,EAC/B,gCAAgC,EAChC,wBAAwB,EACxB,iCAAiC,GAIlC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,sBAAsB,GAGvB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { validateAuthorizationRequest, type ClientResolver, type TokenClientResolver, type ValidateAuthorizationRequestOptions } from '@maronn-openid-connect/core';
2
+ import type { PushedAuthorizationRecord, PushedAuthorizationRequestStore } from './store.js';
3
+ export type ParErrorCode = 'invalid_request' | 'invalid_client' | 'invalid_scope' | 'unauthorized_client' | 'unsupported_response_type';
4
+ export declare class ParError extends Error {
5
+ readonly code: ParErrorCode;
6
+ readonly errorDescription: string;
7
+ constructor(code: ParErrorCode, errorDescription: string);
8
+ get statusCode(): 400 | 401;
9
+ get wwwAuthenticate(): string | undefined;
10
+ }
11
+ export interface PushedAuthorizationResponse {
12
+ requestUri: string;
13
+ expiresIn: number;
14
+ }
15
+ export interface PushedAuthorizationRequestContext {
16
+ params: Record<string, string>;
17
+ authorizationHeader?: string;
18
+ clientResolver: ClientResolver & TokenClientResolver;
19
+ store: PushedAuthorizationRequestStore;
20
+ validationOptions: ValidateAuthorizationRequestOptions;
21
+ expiresInSeconds?: number;
22
+ now?: Date;
23
+ }
24
+ export declare function assertParExpiresInSeconds(seconds: number): void;
25
+ export declare function rejectForbiddenParParams(params: Record<string, string>): void;
26
+ export declare function authenticateParClient(context: {
27
+ params: Record<string, string>;
28
+ authorizationHeader?: string;
29
+ clientResolver: TokenClientResolver;
30
+ }): Promise<string>;
31
+ export declare function validatePushedAuthorizationParams(params: Record<string, string>, clientResolver: ClientResolver, options?: ValidateAuthorizationRequestOptions): Promise<Awaited<ReturnType<typeof validateAuthorizationRequest>>>;
32
+ export declare function createPushedAuthorizationRecord(options: {
33
+ clientId: string;
34
+ params: Record<string, string>;
35
+ store: PushedAuthorizationRequestStore;
36
+ expiresInSeconds?: number;
37
+ now?: Date;
38
+ }): Promise<PushedAuthorizationRecord>;
39
+ export declare function buildPushedAuthorizationResponse(record: PushedAuthorizationRecord): PushedAuthorizationResponse;
40
+ export declare function handlePushedAuthorizationRequest(context: PushedAuthorizationRequestContext): Promise<PushedAuthorizationResponse>;
41
+ //# sourceMappingURL=par-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"par-request.d.ts","sourceRoot":"","sources":["../../src/par/par-request.ts"],"names":[],"mappings":"AAQA,OAAO,EASL,4BAA4B,EAI5B,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,mCAAmC,EACzC,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EACV,yBAAyB,EACzB,+BAA+B,EAChC,MAAM,YAAY,CAAC;AAMpB,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,gBAAgB,GAChB,eAAe,GACf,qBAAqB,GACrB,2BAA2B,CAAC;AAQhC,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;gBAEtB,IAAI,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM;IAUxD,IAAI,UAAU,IAAI,GAAG,GAAG,GAAG,CAE1B;IAGD,IAAI,eAAe,IAAI,MAAM,GAAG,SAAS,CAExC;CACF;AAGD,MAAM,WAAW,2BAA2B;IAE1C,UAAU,EAAE,MAAM,CAAC;IAEnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,iCAAiC;IAEhD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,cAAc,EAAE,cAAc,GAAG,mBAAmB,CAAC;IACrD,KAAK,EAAE,+BAA+B,CAAC;IAEvC,iBAAiB,EAAE,mCAAmC,CAAC;IAEvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAkBD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAU/D;AAUD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAa7E;AAoBD,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IACnD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,mBAAmB,CAAC;CACrC,GAAG,OAAO,CAAC,MAAM,CAAC,CAkClB;AAkCD,wBAAsB,iCAAiC,CACrD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,cAAc,EAAE,cAAc,EAC9B,OAAO,GAAE,mCAAwC,GAChD,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAC,CAAC,CAUnE;AAqBD,wBAAsB,+BAA+B,CAAC,OAAO,EAAE;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,+BAA+B,CAAC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAmBrC;AAGD,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,yBAAyB,GAChC,2BAA2B,CAK7B;AAUD,wBAAsB,gCAAgC,CACpD,OAAO,EAAE,iCAAiC,GACzC,OAAO,CAAC,2BAA2B,CAAC,CAsBtC"}
@@ -0,0 +1,161 @@
1
+ import { AuthorizationError, AuthorizationErrorCode, TokenError, TokenErrorCode, extractClientCredentials, generateRandomString, resolveAuthenticatedTokenClient, sanitizeErrorDescription, validateAuthorizationRequest, validateClientAuthMethod, verifyClientSecret, } from '@maronn-openid-connect/core';
2
+ import { PAR_REQUEST_URI_PREFIX } from './store.js';
3
+ export class ParError extends Error {
4
+ code;
5
+ errorDescription;
6
+ constructor(code, errorDescription) {
7
+ const sanitized = sanitizeErrorDescription(errorDescription);
8
+ super(sanitized);
9
+ this.name = 'ParError';
10
+ this.code = code;
11
+ this.errorDescription = sanitized;
12
+ }
13
+ get statusCode() {
14
+ return this.code === 'invalid_client' ? 401 : 400;
15
+ }
16
+ get wwwAuthenticate() {
17
+ return this.code === 'invalid_client' ? 'Basic realm="Client Authentication"' : undefined;
18
+ }
19
+ }
20
+ const MIN_EXPIRES_IN_SECONDS = 5;
21
+ const MAX_EXPIRES_IN_SECONDS = 600;
22
+ const DEFAULT_EXPIRES_IN_SECONDS = 60;
23
+ const REFERENCE_VALUE_BYTE_LENGTH = 32;
24
+ export function assertParExpiresInSeconds(seconds) {
25
+ const isValid = Number.isInteger(seconds) &&
26
+ seconds >= MIN_EXPIRES_IN_SECONDS &&
27
+ seconds <= MAX_EXPIRES_IN_SECONDS;
28
+ if (!isValid) {
29
+ throw new RangeError(`expiresInSeconds must be an integer between ${MIN_EXPIRES_IN_SECONDS} and ${MAX_EXPIRES_IN_SECONDS} (RFC 9126 §2.2), received ${seconds}`);
30
+ }
31
+ }
32
+ export function rejectForbiddenParParams(params) {
33
+ if (params['request_uri'] !== undefined) {
34
+ throw new ParError('invalid_request', 'request_uri MUST NOT be included in a pushed authorization request');
35
+ }
36
+ if (params['request'] !== undefined) {
37
+ throw new ParError('invalid_request', 'The request parameter (Request Object) is not supported by this pushed authorization request endpoint');
38
+ }
39
+ }
40
+ export async function authenticateParClient(context) {
41
+ const { params, clientResolver } = context;
42
+ const authorizationHeader = context.authorizationHeader ?? '';
43
+ const usesAuthorizationHeader = authorizationHeader.trim().length > 0;
44
+ if (usesAuthorizationHeader && params['client_secret'] !== undefined) {
45
+ throw new ParError('invalid_request', 'Multiple client authentication methods provided. Use either the Authorization header or the request body, not both.');
46
+ }
47
+ const credentialParams = usesAuthorizationHeader
48
+ ? {}
49
+ : { client_id: params['client_id'], client_secret: params['client_secret'] };
50
+ const authenticatedClientId = await runClientAuthentication({
51
+ params: credentialParams,
52
+ authorizationHeader,
53
+ clientResolver,
54
+ });
55
+ const bodyClientId = params['client_id'];
56
+ if (bodyClientId !== undefined && bodyClientId !== authenticatedClientId) {
57
+ throw new ParError('invalid_request', 'client_id does not match the authenticated client');
58
+ }
59
+ return authenticatedClientId;
60
+ }
61
+ async function runClientAuthentication(context) {
62
+ try {
63
+ const presented = extractClientCredentials({
64
+ params: context.params,
65
+ authorizationHeader: context.authorizationHeader,
66
+ });
67
+ const client = await resolveAuthenticatedTokenClient(presented.clientId, context.clientResolver);
68
+ validateClientAuthMethod(client, presented);
69
+ await verifyClientSecret(client, presented.clientSecret);
70
+ return presented.clientId;
71
+ }
72
+ catch (error) {
73
+ throw toParError(error);
74
+ }
75
+ }
76
+ export async function validatePushedAuthorizationParams(params, clientResolver, options = {}) {
77
+ try {
78
+ return await validateAuthorizationRequest(params, clientResolver, options);
79
+ }
80
+ catch (error) {
81
+ throw toParError(error);
82
+ }
83
+ }
84
+ const CLIENT_AUTHENTICATION_PARAMS = ['client_secret', 'client_assertion', 'client_assertion_type'];
85
+ export async function createPushedAuthorizationRecord(options) {
86
+ const expiresInSeconds = options.expiresInSeconds ?? DEFAULT_EXPIRES_IN_SECONDS;
87
+ assertParExpiresInSeconds(expiresInSeconds);
88
+ const storedParams = { ...options.params, client_id: options.clientId };
89
+ for (const name of CLIENT_AUTHENTICATION_PARAMS) {
90
+ delete storedParams[name];
91
+ }
92
+ const createdAt = options.now ?? new Date();
93
+ const record = {
94
+ requestUri: PAR_REQUEST_URI_PREFIX + generateRandomString(REFERENCE_VALUE_BYTE_LENGTH),
95
+ clientId: options.clientId,
96
+ params: storedParams,
97
+ createdAt,
98
+ expiresAt: new Date(createdAt.getTime() + expiresInSeconds * 1000),
99
+ };
100
+ await options.store.save(record);
101
+ return record;
102
+ }
103
+ export function buildPushedAuthorizationResponse(record) {
104
+ return {
105
+ requestUri: record.requestUri,
106
+ expiresIn: Math.round((record.expiresAt.getTime() - record.createdAt.getTime()) / 1000),
107
+ };
108
+ }
109
+ export async function handlePushedAuthorizationRequest(context) {
110
+ rejectForbiddenParParams(context.params);
111
+ const clientId = await authenticateParClient({
112
+ params: context.params,
113
+ authorizationHeader: context.authorizationHeader,
114
+ clientResolver: context.clientResolver,
115
+ });
116
+ const params = { ...context.params, client_id: clientId };
117
+ await validatePushedAuthorizationParams(params, context.clientResolver, context.validationOptions);
118
+ const record = await createPushedAuthorizationRecord({
119
+ clientId,
120
+ params,
121
+ store: context.store,
122
+ expiresInSeconds: context.expiresInSeconds,
123
+ now: context.now,
124
+ });
125
+ return buildPushedAuthorizationResponse(record);
126
+ }
127
+ function toParError(error) {
128
+ if (error instanceof ParError)
129
+ return error;
130
+ if (error instanceof TokenError)
131
+ return new ParError(toParErrorCodeFromToken(error.error), error.errorDescription);
132
+ if (error instanceof AuthorizationError) {
133
+ return new ParError(toParErrorCodeFromAuthorization(error.error), error.errorDescription);
134
+ }
135
+ return error;
136
+ }
137
+ function toParErrorCodeFromToken(code) {
138
+ switch (code) {
139
+ case TokenErrorCode.InvalidClient:
140
+ return 'invalid_client';
141
+ case TokenErrorCode.UnauthorizedClient:
142
+ return 'unauthorized_client';
143
+ case TokenErrorCode.InvalidScope:
144
+ return 'invalid_scope';
145
+ default:
146
+ return 'invalid_request';
147
+ }
148
+ }
149
+ function toParErrorCodeFromAuthorization(code) {
150
+ switch (code) {
151
+ case AuthorizationErrorCode.InvalidScope:
152
+ return 'invalid_scope';
153
+ case AuthorizationErrorCode.UnauthorizedClient:
154
+ return 'unauthorized_client';
155
+ case AuthorizationErrorCode.UnsupportedResponseType:
156
+ return 'unsupported_response_type';
157
+ default:
158
+ return 'invalid_request';
159
+ }
160
+ }
161
+ //# sourceMappingURL=par-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"par-request.js","sourceRoot":"","sources":["../../src/par/par-request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { PushedAuthorizationRequestStore } from './store.js';
2
+ export declare class PushedRequestUriError extends Error {
3
+ readonly code: 'invalid_request_uri' | 'invalid_request';
4
+ readonly errorDescription: string;
5
+ constructor(code: 'invalid_request_uri' | 'invalid_request', errorDescription: string);
6
+ }
7
+ export declare function resolvePushedRequestUri(options: {
8
+ params: Record<string, string>;
9
+ store: PushedAuthorizationRequestStore;
10
+ now?: Date;
11
+ }): Promise<Record<string, string> | null>;
12
+ export declare function assertPushedRequestUsed(params: Record<string, string>): void;
13
+ //# sourceMappingURL=resolve-request-uri.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-request-uri.d.ts","sourceRoot":"","sources":["../../src/par/resolve-request-uri.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAC;AAWlE,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,CAAC;IACzD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;gBAEtB,IAAI,EAAE,qBAAqB,GAAG,iBAAiB,EAAE,gBAAgB,EAAE,MAAM;CAQtF;AAyBD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,KAAK,EAAE,+BAA+B,CAAC;IACvC,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,CA4BzC;AASD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAQ5E"}
@@ -0,0 +1,40 @@
1
+ import { sanitizeErrorDescription } from '@maronn-openid-connect/core';
2
+ import { PAR_REQUEST_URI_PREFIX } from './store.js';
3
+ export class PushedRequestUriError extends Error {
4
+ code;
5
+ errorDescription;
6
+ constructor(code, errorDescription) {
7
+ const sanitized = sanitizeErrorDescription(errorDescription);
8
+ super(sanitized);
9
+ this.name = 'PushedRequestUriError';
10
+ this.code = code;
11
+ this.errorDescription = sanitized;
12
+ }
13
+ }
14
+ const OPAQUE_RESOLUTION_FAILURE_DESCRIPTION = 'The request_uri is invalid, expired, or has already been used';
15
+ export async function resolvePushedRequestUri(options) {
16
+ const requestUri = options.params['request_uri'];
17
+ if (requestUri === undefined || !requestUri.startsWith(PAR_REQUEST_URI_PREFIX)) {
18
+ return null;
19
+ }
20
+ const record = await options.store.consume(requestUri);
21
+ if (record === null) {
22
+ throw new PushedRequestUriError('invalid_request_uri', OPAQUE_RESOLUTION_FAILURE_DESCRIPTION);
23
+ }
24
+ const now = options.now ?? new Date();
25
+ if (record.expiresAt.getTime() < now.getTime()) {
26
+ throw new PushedRequestUriError('invalid_request_uri', OPAQUE_RESOLUTION_FAILURE_DESCRIPTION);
27
+ }
28
+ if (options.params['client_id'] !== record.clientId) {
29
+ throw new PushedRequestUriError('invalid_request_uri', OPAQUE_RESOLUTION_FAILURE_DESCRIPTION);
30
+ }
31
+ const { request_uri: _consumed, ...pushedParams } = record.params;
32
+ return pushedParams;
33
+ }
34
+ export function assertPushedRequestUsed(params) {
35
+ const requestUri = params['request_uri'];
36
+ if (requestUri === undefined || !requestUri.startsWith(PAR_REQUEST_URI_PREFIX)) {
37
+ throw new PushedRequestUriError('invalid_request', 'Pushed authorization requests are required by this authorization server');
38
+ }
39
+ }
40
+ //# sourceMappingURL=resolve-request-uri.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-request-uri.js","sourceRoot":"","sources":["../../src/par/resolve-request-uri.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAYpD,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACrC,IAAI,CAA4C;IAChD,gBAAgB,CAAS;IAElC,YAAY,IAA+C,EAAE,gBAAwB;QAEnF,MAAM,SAAS,GAAG,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;QAC7D,KAAK,CAAC,SAAS,CAAC,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;IACpC,CAAC;CACF;AAQD,MAAM,qCAAqC,GACzC,+DAA+D,CAAC;AAgBlE,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,OAI7C;IACC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACjD,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;QAC/E,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACvD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,qBAAqB,CAAC,qBAAqB,EAAE,qCAAqC,CAAC,CAAC;IAChG,CAAC;IAGD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACtC,IAAI,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;QAC/C,MAAM,IAAI,qBAAqB,CAAC,qBAAqB,EAAE,qCAAqC,CAAC,CAAC;IAChG,CAAC;IAID,IAAI,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpD,MAAM,IAAI,qBAAqB,CAAC,qBAAqB,EAAE,qCAAqC,CAAC,CAAC;IAChG,CAAC;IAID,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;IAClE,OAAO,YAAY,CAAC;AACtB,CAAC;AASD,MAAM,UAAU,uBAAuB,CAAC,MAA8B;IACpE,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;QAC/E,MAAM,IAAI,qBAAqB,CAC7B,iBAAiB,EACjB,yEAAyE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare const PAR_REQUEST_URI_PREFIX = "urn:ietf:params:oauth:request_uri:";
2
+ export interface PushedAuthorizationRecord {
3
+ requestUri: string;
4
+ clientId: string;
5
+ params: Record<string, string>;
6
+ createdAt: Date;
7
+ expiresAt: Date;
8
+ }
9
+ export interface PushedAuthorizationRequestStore {
10
+ save(record: PushedAuthorizationRecord): Promise<void>;
11
+ consume(requestUri: string): Promise<PushedAuthorizationRecord | null>;
12
+ }
13
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/par/store.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,sBAAsB,uCAAuC,CAAC;AAS3E,MAAM,WAAW,yBAAyB;IAExC,UAAU,EAAE,MAAM,CAAC;IAEnB,QAAQ,EAAE,MAAM,CAAC;IAEjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAQD,MAAM,WAAW,+BAA+B;IAE9C,IAAI,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAYvD,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,GAAG,IAAI,CAAC,CAAC;CACxE"}
@@ -0,0 +1,2 @@
1
+ export const PAR_REQUEST_URI_PREFIX = 'urn:ietf:params:oauth:request_uri:';
2
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/par/store.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,sBAAsB,GAAG,oCAAoC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { SUBJECT_TOKEN_INVALID_DESCRIPTION, TOKEN_EXCHANGE_GRANT_TYPE, TOKEN_TYPE_ACCESS_TOKEN, TokenExchangeError, authorizeTokenExchangeClient, buildTokenExchangeResponse, computeExchangedTokenLifetime, parseTokenExchangeParams, processTokenExchangeRequest, resolveExchangeTarget, resolveSubjectToken, validateExchangeScope, type ParsedTokenExchangeParams, type TokenExchangeErrorCode, type TokenExchangeGrant, type TokenExchangeRequestContext, type TokenExchangeResponse, } from './token-exchange-request.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/token-exchange/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,iCAAiC,EACjC,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,0BAA0B,EAC1B,6BAA6B,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,GAC3B,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { SUBJECT_TOKEN_INVALID_DESCRIPTION, TOKEN_EXCHANGE_GRANT_TYPE, TOKEN_TYPE_ACCESS_TOKEN, TokenExchangeError, authorizeTokenExchangeClient, buildTokenExchangeResponse, computeExchangedTokenLifetime, parseTokenExchangeParams, processTokenExchangeRequest, resolveExchangeTarget, resolveSubjectToken, validateExchangeScope, } from './token-exchange-request.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/token-exchange/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,iCAAiC,EACjC,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,0BAA0B,EAC1B,6BAA6B,EAC7B,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,GAMtB,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { type AccessTokenInfo, type AccessTokenResolver, type TokenClientInfo } from '@maronn-openid-connect/core';
2
+ export declare const TOKEN_EXCHANGE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:token-exchange";
3
+ export declare const TOKEN_TYPE_ACCESS_TOKEN = "urn:ietf:params:oauth:token-type:access_token";
4
+ export declare const SUBJECT_TOKEN_INVALID_DESCRIPTION = "The provided subject_token is not valid";
5
+ export type TokenExchangeErrorCode = 'invalid_request' | 'unauthorized_client' | 'invalid_scope' | 'invalid_target';
6
+ export declare class TokenExchangeError extends Error {
7
+ readonly code: TokenExchangeErrorCode;
8
+ readonly errorDescription: string;
9
+ constructor(code: TokenExchangeErrorCode, errorDescription: string);
10
+ get statusCode(): 400;
11
+ }
12
+ export interface ParsedTokenExchangeParams {
13
+ subjectToken: string;
14
+ scope?: string;
15
+ audience?: string;
16
+ resource?: string;
17
+ }
18
+ export interface TokenExchangeGrant {
19
+ subject: string;
20
+ clientId: string;
21
+ scope: string[];
22
+ requestedAudience?: string[];
23
+ expiresIn: number;
24
+ grantId?: string;
25
+ }
26
+ export interface TokenExchangeResponse {
27
+ access_token: string;
28
+ issued_token_type: typeof TOKEN_TYPE_ACCESS_TOKEN;
29
+ token_type: 'Bearer';
30
+ expires_in: number;
31
+ scope: string;
32
+ }
33
+ export interface TokenExchangeRequestContext {
34
+ params: Record<string, string>;
35
+ client: TokenClientInfo;
36
+ accessTokenResolver: AccessTokenResolver;
37
+ allowedTargets: string[];
38
+ configuredExpiresIn: number;
39
+ now?: Date;
40
+ }
41
+ export declare function authorizeTokenExchangeClient(client: TokenClientInfo): void;
42
+ export declare function parseTokenExchangeParams(params: Record<string, string>): ParsedTokenExchangeParams;
43
+ export declare function resolveSubjectToken(options: {
44
+ subjectToken: string;
45
+ accessTokenResolver: AccessTokenResolver;
46
+ now?: Date;
47
+ }): Promise<AccessTokenInfo>;
48
+ export declare function validateExchangeScope(requestedScope: string | undefined, subjectScope: string[]): string[];
49
+ export declare function resolveExchangeTarget(options: {
50
+ audience?: string;
51
+ resource?: string;
52
+ allowedTargets: string[];
53
+ subjectAudience?: string[];
54
+ }): string[] | undefined;
55
+ export declare function computeExchangedTokenLifetime(options: {
56
+ subjectExpiresAt: number;
57
+ configuredExpiresIn: number;
58
+ now?: Date;
59
+ }): number;
60
+ export declare function buildTokenExchangeResponse(options: {
61
+ accessToken: string;
62
+ expiresIn: number;
63
+ scope: string[];
64
+ }): TokenExchangeResponse;
65
+ export declare function processTokenExchangeRequest(context: TokenExchangeRequestContext): Promise<TokenExchangeGrant>;
66
+ //# sourceMappingURL=token-exchange-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-exchange-request.d.ts","sourceRoot":"","sources":["../../src/token-exchange/token-exchange-request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,178 @@
1
+ import { sanitizeErrorDescription, } from '@maronn-openid-connect/core';
2
+ export const TOKEN_EXCHANGE_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange';
3
+ export const TOKEN_TYPE_ACCESS_TOKEN = 'urn:ietf:params:oauth:token-type:access_token';
4
+ export const SUBJECT_TOKEN_INVALID_DESCRIPTION = 'The provided subject_token is not valid';
5
+ export class TokenExchangeError extends Error {
6
+ code;
7
+ errorDescription;
8
+ constructor(code, errorDescription) {
9
+ const sanitized = sanitizeErrorDescription(errorDescription);
10
+ super(sanitized);
11
+ this.name = 'TokenExchangeError';
12
+ this.code = code;
13
+ this.errorDescription = sanitized;
14
+ }
15
+ get statusCode() {
16
+ return 400;
17
+ }
18
+ }
19
+ export function authorizeTokenExchangeClient(client) {
20
+ const grantTypes = client.grantTypes ?? ['authorization_code'];
21
+ if (!grantTypes.includes(TOKEN_EXCHANGE_GRANT_TYPE)) {
22
+ throw new TokenExchangeError('unauthorized_client', 'The client is not authorized to use the token-exchange grant type');
23
+ }
24
+ if (client.tokenEndpointAuthMethod === 'none') {
25
+ throw new TokenExchangeError('unauthorized_client', 'Public clients are not allowed to use the token-exchange grant type');
26
+ }
27
+ }
28
+ export function parseTokenExchangeParams(params) {
29
+ if (params['actor_token'] !== undefined || params['actor_token_type'] !== undefined) {
30
+ throw new TokenExchangeError('invalid_request', 'Delegation is not supported: actor_token and actor_token_type must not be present.');
31
+ }
32
+ const subjectToken = optional(params['subject_token']);
33
+ if (subjectToken === undefined) {
34
+ throw new TokenExchangeError('invalid_request', 'subject_token is required');
35
+ }
36
+ const subjectTokenType = optional(params['subject_token_type']);
37
+ if (subjectTokenType === undefined) {
38
+ throw new TokenExchangeError('invalid_request', 'subject_token_type is required');
39
+ }
40
+ if (subjectTokenType !== TOKEN_TYPE_ACCESS_TOKEN) {
41
+ throw new TokenExchangeError('invalid_request', `Unsupported subject_token_type. Only ${TOKEN_TYPE_ACCESS_TOKEN} is supported.`);
42
+ }
43
+ const requestedTokenType = optional(params['requested_token_type']);
44
+ if (requestedTokenType !== undefined && requestedTokenType !== TOKEN_TYPE_ACCESS_TOKEN) {
45
+ throw new TokenExchangeError('invalid_request', `Unsupported requested_token_type. Only ${TOKEN_TYPE_ACCESS_TOKEN} is supported.`);
46
+ }
47
+ const resource = optional(params['resource']);
48
+ if (resource !== undefined && !isAbsoluteUriWithoutFragment(resource)) {
49
+ throw new TokenExchangeError('invalid_request', 'resource must be an absolute URI without a fragment component');
50
+ }
51
+ return {
52
+ subjectToken,
53
+ scope: optional(params['scope']),
54
+ audience: optional(params['audience']),
55
+ resource,
56
+ };
57
+ }
58
+ export async function resolveSubjectToken(options) {
59
+ const info = await options.accessTokenResolver.findAccessToken(options.subjectToken);
60
+ if (info === null) {
61
+ throw invalidSubjectToken();
62
+ }
63
+ const nowSeconds = toEpochSeconds(options.now);
64
+ if (info.expiresAt <= nowSeconds) {
65
+ throw invalidSubjectToken();
66
+ }
67
+ if (info.nbf !== undefined && info.nbf > nowSeconds) {
68
+ throw invalidSubjectToken();
69
+ }
70
+ return info;
71
+ }
72
+ export function validateExchangeScope(requestedScope, subjectScope) {
73
+ const requested = splitScope(requestedScope);
74
+ if (requested.length === 0) {
75
+ return [...subjectScope];
76
+ }
77
+ for (const value of requested) {
78
+ if (!subjectScope.includes(value)) {
79
+ throw new TokenExchangeError('invalid_scope', 'The requested scope exceeds the scope of the subject_token');
80
+ }
81
+ }
82
+ return requested;
83
+ }
84
+ export function resolveExchangeTarget(options) {
85
+ const { audience, resource, allowedTargets, subjectAudience } = options;
86
+ if (audience === undefined && resource === undefined) {
87
+ return subjectAudience === undefined ? undefined : [...subjectAudience];
88
+ }
89
+ const targets = [];
90
+ for (const requested of [audience, resource]) {
91
+ if (requested === undefined)
92
+ continue;
93
+ if (!allowedTargets.includes(requested)) {
94
+ throw new TokenExchangeError('invalid_target', 'The requested target is not allowed for token exchange');
95
+ }
96
+ targets.push(requested);
97
+ }
98
+ return [...new Set(targets)];
99
+ }
100
+ export function computeExchangedTokenLifetime(options) {
101
+ const { subjectExpiresAt, configuredExpiresIn } = options;
102
+ if (!Number.isInteger(configuredExpiresIn) || configuredExpiresIn <= 0) {
103
+ throw new RangeError(`configuredExpiresIn must be a positive integer, received ${configuredExpiresIn}`);
104
+ }
105
+ const remaining = subjectExpiresAt - toEpochSeconds(options.now);
106
+ if (remaining <= 0) {
107
+ throw invalidSubjectToken();
108
+ }
109
+ return Math.min(configuredExpiresIn, remaining);
110
+ }
111
+ export function buildTokenExchangeResponse(options) {
112
+ return {
113
+ access_token: options.accessToken,
114
+ issued_token_type: TOKEN_TYPE_ACCESS_TOKEN,
115
+ token_type: 'Bearer',
116
+ expires_in: options.expiresIn,
117
+ scope: options.scope.join(' '),
118
+ };
119
+ }
120
+ export async function processTokenExchangeRequest(context) {
121
+ authorizeTokenExchangeClient(context.client);
122
+ const parsed = parseTokenExchangeParams(context.params);
123
+ const subject = await resolveSubjectToken({
124
+ subjectToken: parsed.subjectToken,
125
+ accessTokenResolver: context.accessTokenResolver,
126
+ now: context.now,
127
+ });
128
+ const scope = validateExchangeScope(parsed.scope, subject.scope);
129
+ const requestedAudience = resolveExchangeTarget({
130
+ audience: parsed.audience,
131
+ resource: parsed.resource,
132
+ allowedTargets: context.allowedTargets,
133
+ subjectAudience: subject.audience,
134
+ });
135
+ const expiresIn = computeExchangedTokenLifetime({
136
+ subjectExpiresAt: subject.expiresAt,
137
+ configuredExpiresIn: context.configuredExpiresIn,
138
+ now: context.now,
139
+ });
140
+ return {
141
+ subject: subject.sub,
142
+ clientId: context.client.clientId,
143
+ scope,
144
+ requestedAudience,
145
+ expiresIn,
146
+ grantId: subject.grantId,
147
+ };
148
+ }
149
+ function optional(value) {
150
+ if (value === undefined)
151
+ return undefined;
152
+ const trimmed = value.trim();
153
+ return trimmed.length === 0 ? undefined : trimmed;
154
+ }
155
+ function splitScope(scope) {
156
+ if (scope === undefined)
157
+ return [];
158
+ return [...new Set(scope.split(/\s+/).filter((value) => value.length > 0))];
159
+ }
160
+ function toEpochSeconds(now) {
161
+ return Math.floor((now ?? new Date()).getTime() / 1000);
162
+ }
163
+ function invalidSubjectToken() {
164
+ return new TokenExchangeError('invalid_request', SUBJECT_TOKEN_INVALID_DESCRIPTION);
165
+ }
166
+ function isAbsoluteUriWithoutFragment(value) {
167
+ if (value.includes('#'))
168
+ return false;
169
+ let parsed;
170
+ try {
171
+ parsed = new URL(value);
172
+ }
173
+ catch {
174
+ return false;
175
+ }
176
+ return parsed.protocol.length > 0;
177
+ }
178
+ //# sourceMappingURL=token-exchange-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-exchange-request.js","sourceRoot":"","sources":["../../src/token-exchange/token-exchange-request.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@maronn-openid-connect/experimental",
3
+ "version": "0.0.1",
4
+ "description": "Experimental OAuth/OIDC extensions for maronn-oidc (unstable APIs)",
5
+ "type": "module",
6
+ "exports": {
7
+ "./par": {
8
+ "types": "./dist/par/index.d.ts",
9
+ "import": "./dist/par/index.js"
10
+ },
11
+ "./token-exchange": {
12
+ "types": "./dist/token-exchange/index.d.ts",
13
+ "import": "./dist/token-exchange/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "LICENSE",
19
+ "README.md"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "keywords": [
25
+ "openid-connect",
26
+ "oauth2.1",
27
+ "experimental"
28
+ ],
29
+ "author": "maronnjapan",
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/maronnjapan/maronn-oidc.git",
34
+ "directory": "packages/experimental"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/maronnjapan/maronn-oidc/issues"
38
+ },
39
+ "homepage": "https://github.com/maronnjapan/maronn-oidc/tree/main/packages/experimental#readme",
40
+ "peerDependencies": {
41
+ "@maronn-openid-connect/core": ">=0.0.1 <1.0.0"
42
+ },
43
+ "devDependencies": {
44
+ "@edge-runtime/vm": "^5.0.0",
45
+ "@types/node": "^26.1.2",
46
+ "typescript": "^5.7.2",
47
+ "vitest": "^3.2.6",
48
+ "@maronn-openid-connect/core": "0.0.1"
49
+ },
50
+ "scripts": {
51
+ "build": "tsc",
52
+ "test": "vitest run",
53
+ "test:ci": "vitest run",
54
+ "test:watch": "vitest",
55
+ "typecheck": "tsc --noEmit"
56
+ }
57
+ }