@maronn-openid-connect/core 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 +21 -0
- package/README.md +145 -0
- package/dist/access-token-issuer.d.ts +14 -0
- package/dist/access-token-issuer.d.ts.map +1 -0
- package/dist/access-token-issuer.js +32 -0
- package/dist/access-token-issuer.js.map +1 -0
- package/dist/access-token.d.ts +19 -0
- package/dist/access-token.d.ts.map +1 -0
- package/dist/access-token.js +46 -0
- package/dist/access-token.js.map +1 -0
- package/dist/auth-transaction.d.ts +86 -0
- package/dist/auth-transaction.d.ts.map +1 -0
- package/dist/auth-transaction.js +187 -0
- package/dist/auth-transaction.js.map +1 -0
- package/dist/authorization-code-grant.d.ts +15 -0
- package/dist/authorization-code-grant.d.ts.map +1 -0
- package/dist/authorization-code-grant.js +109 -0
- package/dist/authorization-code-grant.js.map +1 -0
- package/dist/authorization-code.d.ts +28 -0
- package/dist/authorization-code.d.ts.map +1 -0
- package/dist/authorization-code.js +41 -0
- package/dist/authorization-code.js.map +1 -0
- package/dist/authorization-request.d.ts +128 -0
- package/dist/authorization-request.d.ts.map +1 -0
- package/dist/authorization-request.js +457 -0
- package/dist/authorization-request.js.map +1 -0
- package/dist/client-auth.d.ts +16 -0
- package/dist/client-auth.d.ts.map +1 -0
- package/dist/client-auth.js +116 -0
- package/dist/client-auth.js.map +1 -0
- package/dist/crypto-utils.d.ts +18 -0
- package/dist/crypto-utils.d.ts.map +1 -0
- package/dist/crypto-utils.js +197 -0
- package/dist/crypto-utils.js.map +1 -0
- package/dist/discovery.d.ts +56 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +133 -0
- package/dist/discovery.js.map +1 -0
- package/dist/error-utils.d.ts +2 -0
- package/dist/error-utils.d.ts.map +1 -0
- package/dist/error-utils.js +13 -0
- package/dist/error-utils.js.map +1 -0
- package/dist/id-token.d.ts +39 -0
- package/dist/id-token.d.ts.map +1 -0
- package/dist/id-token.js +193 -0
- package/dist/id-token.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/introspection.d.ts +66 -0
- package/dist/introspection.d.ts.map +1 -0
- package/dist/introspection.js +139 -0
- package/dist/introspection.js.map +1 -0
- package/dist/jwks.d.ts +29 -0
- package/dist/jwks.d.ts.map +1 -0
- package/dist/jwks.js +36 -0
- package/dist/jwks.js.map +1 -0
- package/dist/loopback.d.ts +2 -0
- package/dist/loopback.d.ts.map +1 -0
- package/dist/loopback.js +6 -0
- package/dist/loopback.js.map +1 -0
- package/dist/refresh-token-grant.d.ts +14 -0
- package/dist/refresh-token-grant.d.ts.map +1 -0
- package/dist/refresh-token-grant.js +87 -0
- package/dist/refresh-token-grant.js.map +1 -0
- package/dist/request-object.d.ts +11 -0
- package/dist/request-object.d.ts.map +1 -0
- package/dist/request-object.js +92 -0
- package/dist/request-object.js.map +1 -0
- package/dist/revocation.d.ts +51 -0
- package/dist/revocation.d.ts.map +1 -0
- package/dist/revocation.js +93 -0
- package/dist/revocation.js.map +1 -0
- package/dist/signing-key.d.ts +21 -0
- package/dist/signing-key.d.ts.map +1 -0
- package/dist/signing-key.js +99 -0
- package/dist/signing-key.js.map +1 -0
- package/dist/token-error.d.ts +16 -0
- package/dist/token-error.d.ts.map +1 -0
- package/dist/token-error.js +31 -0
- package/dist/token-error.js.map +1 -0
- package/dist/token-request.d.ts +111 -0
- package/dist/token-request.d.ts.map +1 -0
- package/dist/token-request.js +44 -0
- package/dist/token-request.js.map +1 -0
- package/dist/token-response.d.ts +111 -0
- package/dist/token-response.d.ts.map +1 -0
- package/dist/token-response.js +173 -0
- package/dist/token-response.js.map +1 -0
- package/dist/userinfo.d.ts +98 -0
- package/dist/userinfo.d.ts.map +1 -0
- package/dist/userinfo.js +188 -0
- package/dist/userinfo.js.map +1 -0
- package/package.json +52 -0
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,145 @@
|
|
|
1
|
+
# @maronn-openid-connect/core
|
|
2
|
+
|
|
3
|
+
OpenID Connect Core 1.0 / OAuth 2.1 に準拠した OpenID Provider のコアロジックを提供するパッケージ。
|
|
4
|
+
|
|
5
|
+
「最新の OIDC/OAuth 仕様を素早く・忠実に・どこでも動く形で検証する」ための PoC 向けライブラリであり、Keycloak のような構築コストや IdaaS の契約なしに、自分の要件が仕様で実現できるかを検証するブリッジとして使う。検証後は本格的な IdaaS / OSS への移行を想定している。
|
|
6
|
+
|
|
7
|
+
## 特徴
|
|
8
|
+
|
|
9
|
+
- **外部依存ゼロ**: production の依存関係(dependencies)は空。内部実装のみで完結する
|
|
10
|
+
- **Web 標準 API のみ**: Web Crypto API / Fetch API 等の Web 標準のみを使用し、Node.js / エッジランタイム等 JavaScript が動く環境で動作する
|
|
11
|
+
- **純関数ベース**: HTTP の配線(ルーティング・リクエスト解析・レスポンス生成)は呼び出し側の責務。core はバリデーション・トークン生成などのロジックだけを提供する
|
|
12
|
+
- **ストレージ非依存**: クライアント情報・認可コード・トークン等の永続化は resolver / store インターフェースとして注入する。DB / KV / インメモリなど任意の実装を差し込める
|
|
13
|
+
|
|
14
|
+
## インストール
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @maronn-openid-connect/core
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
HTTP 配線込みの OP を手早く立てたい場合は、[`@maronn-openid-connect/cli`](../cli) で Hono / Express / Fastify / Next.js 向けの実装コードを生成できる。core を直接使うのは、生成コードでは表現できない高度な組み込みユースケース向け。
|
|
21
|
+
|
|
22
|
+
## 準拠仕様
|
|
23
|
+
|
|
24
|
+
- OpenID Connect Core 1.0(Authorization Code Flow)
|
|
25
|
+
- OpenID Connect Discovery 1.0
|
|
26
|
+
- OAuth 2.1(PKCE S256 必須、refresh token は absolute lifetime で失効)
|
|
27
|
+
- RFC 7662 Token Introspection
|
|
28
|
+
- RFC 7009 Token Revocation
|
|
29
|
+
- RFC 9068 JWT Access Token(`jwt` 形式選択時)
|
|
30
|
+
- OIDC Core 1.0 §6.1 Request Object(by value・署名付き JWS。`request_uri` は非対応として仕様通り `request_uri_not_supported` を返す)
|
|
31
|
+
|
|
32
|
+
## 提供機能(API 概要)
|
|
33
|
+
|
|
34
|
+
すべて `@maronn-openid-connect/core` からエクスポートされる。
|
|
35
|
+
|
|
36
|
+
### 認可エンドポイント
|
|
37
|
+
|
|
38
|
+
| API | 役割 |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `validateAuthorizationRequest` | 認可リクエストの検証(OIDC Core 1.0 §3.1.2 / OAuth 2.1)。`response_type=code`、PKCE(S256)、`scope` / `state` / `nonce` / `prompt` / `display` / `max_age` / `ui_locales` / `acr_values` / `login_hint` / `id_token_hint` / `claims` / `request` パラメータを処理する。下記ステップ関数を同じ順序で呼び出す合成関数 |
|
|
41
|
+
| 認可リクエスト検証のステップ関数 | `resolveClientForAuthorization` / `resolveRequestObjectParams` / `resolveAuthorizationRedirectUri` / `rejectUnsupportedRequestParams` / `validateRequestObjectConsistency` / `validateResponseType` / `validateAuthorizationScope` / `validateAuthorizationCodePkce` / `validatePromptParameter` / `applyOfflineAccessPolicy` / `validateDisplayParameter` / `resolveMaxAge` / `parseAudienceParameter` / `parseClaimsRequestParameter`。機能単位に分割されており、CLI 生成コードはこれらを個別に呼び出す。検証ステップを消したり独自処理を足したりできる |
|
|
42
|
+
| `validateRegisteredRedirectUris` | 登録 redirect_uri の妥当性検証(完全一致・fragment 拒否) |
|
|
43
|
+
| `parseRequestObject` | Request Object(署名付き JWS)のパースと署名検証(OIDC Core 1.0 §6.1) |
|
|
44
|
+
| `createAuthorizationCode` | 認可コードデータの生成(保存は呼び出し側の責務。OAuth 2.1 §4.1.2) |
|
|
45
|
+
| `AuthorizationError` / `AuthorizationErrorCode` | 認可エンドポイントのエラー表現 |
|
|
46
|
+
|
|
47
|
+
### 認証トランザクション(ログイン・同意画面)
|
|
48
|
+
|
|
49
|
+
| API | 役割 |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `createAuthTransaction` / `getAuthTransaction` | 認可リクエスト受信〜認可コード発行までのコンテキストを KV ストアに保存・復元する(Auth Transaction ID 方式) |
|
|
52
|
+
| `validateCsrfToken` | ログイン / 同意フォームの CSRF トークン検証 |
|
|
53
|
+
| `handleLoginFailure` / `completeAuthTransaction` | ログイン失敗処理・トランザクション完了(認可レスポンス生成) |
|
|
54
|
+
| `checkPromptNone` | `prompt=none` の検証(`login_required` / `consent_required` / `interaction_required`。OIDC Core 1.0 §3.1.2.1)。下記ステップ関数を同じ順序で呼び出す合成関数 |
|
|
55
|
+
| `prompt=none` のステップ関数 | `resolvePromptNoneSession`(アクティブセッションの解決) / `validatePromptNoneIdTokenHint`(`id_token_hint` の subject 一致) / `validatePromptNoneConsent`(同意済みスコープの確認)。CLI 生成コードはこれらを個別に呼び出す |
|
|
56
|
+
| `requiresReauthentication` | `prompt=login` / `max_age` による再認証要否の判定(OIDC Core 1.0 §3.1.2.3) |
|
|
57
|
+
|
|
58
|
+
`prompt` は `none` / `login` / `consent` / `select_account` を受理し、`none` と他値の併用は仕様通り拒否する。
|
|
59
|
+
|
|
60
|
+
### トークンエンドポイント
|
|
61
|
+
|
|
62
|
+
| API | 役割 |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `authenticateClient` | クライアント認証(`client_secret_basic` / `client_secret_post` / public client の `none`。OAuth 2.1 §2.3)。下記ステップ関数を同じ順序で呼び出す合成関数 |
|
|
65
|
+
| クライアント認証のステップ関数 | `extractClientCredentials`(提示された資格情報と使用方式の抽出) / `resolveAuthenticatedTokenClient`(登録クライアントの解決) / `validateClientAuthMethod`(登録 `token_endpoint_auth_method` との一致検証) / `verifyClientSecret`(定数時間比較)。CLI 生成コードはこれらを個別に呼び出すため、`private_key_jwt` などの独自方式へ差し替えやすい |
|
|
66
|
+
| `validateTokenRequest` | grant_type 検証を含むトークンリクエストのフル検証。下記ステップ関数と grant 別関数を同じ順序で呼び出す合成関数 |
|
|
67
|
+
| トークンリクエスト検証のステップ関数 | `validateGrantTypeSupported`(OP 全体での grant_type サポート判定) / `resolveAuthenticatedTokenClient`(認証済みクライアントの解決) / `validateClientGrantType`(クライアント単位の grant_type 認可)。CLI 生成コードはこれらを個別に呼び出す |
|
|
68
|
+
| authorization_code のステップ関数 | `resolveAuthorizationCode` / `validateAuthorizationCodeUnused` / `validateAuthorizationCodeClient` / `validateAuthorizationCodeExpiration` / `validateAuthorizationCodeRedirectUri` / `verifyAuthorizationCodePkce` / `consumeAuthorizationCode` / `buildValidatedAuthorizationCodeRequest` |
|
|
69
|
+
| refresh_token のステップ関数 | `resolveRefreshToken` / `validateRefreshTokenUnused` / `validateRefreshTokenClient` / `validateRefreshTokenExpiration` / `validateRefreshTokenIdleTimeout` / `validateRefreshTokenScope` / `buildValidatedRefreshTokenRequest` |
|
|
70
|
+
| `validateAuthorizationCodeGrant` / `validateRefreshTokenGrant` | 上記 grant 別ステップを安全な順序で呼ぶ後方互換の合成関数。CLI 生成コードは合成関数ではなく各ステップを明示的に呼び出す |
|
|
71
|
+
| `generateTokenResponse` | トークンレスポンス生成(アクセストークン・ID トークン・リフレッシュトークン)。下記ステップ関数を同じ順序で呼び出す合成関数 |
|
|
72
|
+
| トークンレスポンス生成のステップ関数 | `buildAccessTokenPayload`(RFC 9068 の payload 構築) / `computeAtHash`(OIDC Core 1.0 §3.1.3.6) / `resolveAcrAmr`(`acr` / `amr` の解決) / `buildIdTokenPayload`(ID Token クレームの構築) / `generateIdToken`(署名)。CLI 生成コードはこれらを個別に呼び出すため、ID Token へ独自クレームを足す・発行処理を差し替えるといった改造がしやすい |
|
|
73
|
+
| `buildAccessTokenAudience` / `buildIdTokenAudience` | audience の構築 |
|
|
74
|
+
| `TokenError` / `TokenErrorCode` | トークンエンドポイントのエラー表現(OAuth 2.1 §3.2.3) |
|
|
75
|
+
|
|
76
|
+
- ID トークンは RS256 で署名され、`iss` / `sub` / `aud` / `exp` / `iat` に加え、条件に応じて `auth_time` / `nonce` / `at_hash` / `acr` / `amr` を含む。`acr` / `amr` は `AcrResolver` を注入して決定する
|
|
77
|
+
- アクセストークンは `createJwtAccessTokenIssuer`(RFC 9068 準拠 JWT)と `createOpaqueAccessTokenIssuer`(不透明文字列。ストア検証前提で Introspection / Revocation と相性が良い)を切り替えられる
|
|
78
|
+
- リフレッシュトークンは rotation 前提で、absolute lifetime(初回発行時刻起点)でのみ失効する(OAuth 2.1 §6.1)
|
|
79
|
+
|
|
80
|
+
### UserInfo エンドポイント
|
|
81
|
+
|
|
82
|
+
| API | 役割 |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `handleUserInfoRequest` | アクセストークン検証とクレーム応答(OIDC Core 1.0 §5.3)。下記ステップ関数を同じ順序で呼び出す合成関数 |
|
|
85
|
+
| UserInfo のステップ関数 | `resolveUserInfoAccessToken` / `validateUserInfoTokenExpiration` / `validateUserInfoScope` / `validateUserInfoAudience` / `resolveUserInfoClaims` / `filterClaimsByScope` / `applyRequestedClaims`。CLI 生成コードはこれらを個別に呼び出す |
|
|
86
|
+
| `filterClaimsByScope` / `SCOPE_CLAIMS_MAP` | scope(`profile` / `email` / `address` / `phone`)に応じた標準クレームのフィルタリング(OIDC Core 1.0 §5.4) |
|
|
87
|
+
| `generateUserInfoJwt` | 署名付き UserInfo レスポンス(JWT)の生成 |
|
|
88
|
+
| `UserInfoError` / `UserInfoErrorCode` | `invalid_token` / `insufficient_scope` エラー表現 |
|
|
89
|
+
|
|
90
|
+
`claims` リクエストパラメータ(OIDC Core 1.0 §5.5)による個別クレーム要求にも対応する。
|
|
91
|
+
|
|
92
|
+
### Discovery / JWKS
|
|
93
|
+
|
|
94
|
+
| API | 役割 |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `buildProviderMetadata` | OpenID Provider Metadata の生成(OpenID Connect Discovery 1.0) |
|
|
97
|
+
| `exportPublicJwk` / `exportJwks` / `signingKeysToJwkSet` | 公開鍵の JWK / JWK Set 化(秘密鍵パラメータは型レベルで排除) |
|
|
98
|
+
|
|
99
|
+
### 署名鍵管理
|
|
100
|
+
|
|
101
|
+
| API | 役割 |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `createCachedSigningKeyProvider` | 署名鍵プロバイダーのキャッシュラッパー(TTL 付きで鍵ローテーションに追随) |
|
|
104
|
+
| `getRegisteredSigningKeys` / `selectSigningKeyByAlg` | 登録済み鍵一覧の取得・アルゴリズム別の鍵選択 |
|
|
105
|
+
| `assertHasRs256Key` / `assertKeyStrength` / `assertKidStrategyConsistent` | RS256 鍵の存在・鍵強度・kid 戦略の整合性チェック |
|
|
106
|
+
|
|
107
|
+
鍵は `SigningKeyProvider` インターフェース(`getSigningKey` / 任意の `getSigningKeys`)として注入し、ローテーション済み鍵や複数アルゴリズムの鍵も JWKS で広告できる。
|
|
108
|
+
|
|
109
|
+
### Introspection / Revocation
|
|
110
|
+
|
|
111
|
+
| API | 役割 |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `handleIntrospectionRequest` | RFC 7662 準拠のトークン照会(クライアント認証必須、`active: false` 応答は最小限)。下記ステップ関数を同じ順序で呼び出す合成関数 |
|
|
114
|
+
| Introspection のステップ関数 | `requireIntrospectionToken` / `requireIntrospectionClient` / `resolveIntrospectionToken` / `isIntrospectionTokenActive` / `buildIntrospectionResponse` / `INACTIVE_INTROSPECTION_RESPONSE` |
|
|
115
|
+
| `handleRevocationRequest` | RFC 7009 準拠のトークン失効(他クライアントのトークン指定は `invalid_grant`、refresh 失効時は同一 grant のアクセストークンも cascade 失効)。下記ステップ関数を同じ順序で呼び出す合成関数 |
|
|
116
|
+
| Revocation のステップ関数 | `requireRevocationToken` / `requireRevocationClient` / `resolveRevocationTarget` / `validateRevocationTokenClient` / `revokeResolvedToken` / `revokeGrantAccessTokens` |
|
|
117
|
+
|
|
118
|
+
### ユーティリティ
|
|
119
|
+
|
|
120
|
+
| API | 役割 |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `generateRandomString` | CSPRNG ベースのランダム文字列生成 |
|
|
123
|
+
| `validateIdTokenHint` | `id_token_hint` の署名・クレーム検証(OIDC Core 1.0 §3.1.2.2) |
|
|
124
|
+
| `sanitizeErrorDescription` | `error_description` の RFC 6749 §5.2 準拠サニタイズ |
|
|
125
|
+
| `extractAlgorithmParamsFromJwk` / `getJwaAlgorithm` | JWK ⇔ Web Crypto アルゴリズムパラメータの変換 |
|
|
126
|
+
|
|
127
|
+
## 設計方針
|
|
128
|
+
|
|
129
|
+
core は「検証・生成ロジック」と「HTTP / ストレージ」を分離している。
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
HTTP リクエスト解析 ← 利用者(または CLI 生成コード)
|
|
133
|
+
↓ パラメータ(Record<string, string>)
|
|
134
|
+
core の純関数 ← このパッケージ
|
|
135
|
+
↓ resolver / store 呼び出し
|
|
136
|
+
永続化・クライアント管理 ← 利用者が注入(DB / KV / インメモリ)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
注入インターフェースの例: `ClientResolver`(クライアント情報)、`AuthorizationCodeResolver` / `RefreshTokenResolver` / `AccessTokenResolver`(トークン引き当て)、`SessionResolver` / `ConsentResolver`(セッション・同意状態)、`AuthTransactionStore`(認証トランザクション)、`SigningKeyProvider`(署名鍵)。
|
|
140
|
+
|
|
141
|
+
実際の配線例は [`@maronn-openid-connect/cli`](../cli) が生成するコード、および本リポジトリの `samples/*` を参照。
|
|
142
|
+
|
|
143
|
+
## ライセンス
|
|
144
|
+
|
|
145
|
+
MIT
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AccessTokenPayload } from './access-token.js';
|
|
2
|
+
export type AccessTokenFormat = 'jwt' | 'opaque';
|
|
3
|
+
export interface AccessTokenIssuanceContext {
|
|
4
|
+
payload: AccessTokenPayload;
|
|
5
|
+
privateKey?: CryptoKey;
|
|
6
|
+
keyId?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface AccessTokenIssuer {
|
|
9
|
+
readonly format: AccessTokenFormat;
|
|
10
|
+
issue(ctx: AccessTokenIssuanceContext): Promise<string>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createJwtAccessTokenIssuer(): AccessTokenIssuer;
|
|
13
|
+
export declare function createOpaqueAccessTokenIssuer(byteLength?: number): AccessTokenIssuer;
|
|
14
|
+
//# sourceMappingURL=access-token-issuer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-token-issuer.d.ts","sourceRoot":"","sources":["../src/access-token-issuer.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAOjD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAqBnC,KAAK,CAAC,GAAG,EAAE,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzD;AAGD,wBAAgB,0BAA0B,IAAI,iBAAiB,CAqB9D;AAcD,wBAAgB,6BAA6B,CAAC,UAAU,SAAK,GAAG,iBAAiB,CAUhF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { generateAccessToken } from './access-token.js';
|
|
2
|
+
import { generateRandomString } from './crypto-utils.js';
|
|
3
|
+
export function createJwtAccessTokenIssuer() {
|
|
4
|
+
return {
|
|
5
|
+
format: 'jwt',
|
|
6
|
+
async issue(ctx) {
|
|
7
|
+
if (!ctx.privateKey) {
|
|
8
|
+
throw new Error('JWT access token issuer requires a privateKey');
|
|
9
|
+
}
|
|
10
|
+
const payload = ctx.payload.nbf === undefined
|
|
11
|
+
? { ...ctx.payload, nbf: ctx.payload.iat }
|
|
12
|
+
: ctx.payload;
|
|
13
|
+
return generateAccessToken({
|
|
14
|
+
payload,
|
|
15
|
+
privateKey: ctx.privateKey,
|
|
16
|
+
keyId: ctx.keyId,
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function createOpaqueAccessTokenIssuer(byteLength = 32) {
|
|
22
|
+
if (!Number.isInteger(byteLength) || byteLength <= 0) {
|
|
23
|
+
throw new Error(`Opaque access token byteLength must be a positive integer: got ${byteLength}`);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
format: 'opaque',
|
|
27
|
+
async issue() {
|
|
28
|
+
return generateRandomString(byteLength);
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=access-token-issuer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-token-issuer.js","sourceRoot":"","sources":["../src/access-token-issuer.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAyCzD,MAAM,UAAU,0BAA0B;IACxC,OAAO;QACL,MAAM,EAAE,KAAK;QACb,KAAK,CAAC,KAAK,CAAC,GAAG;YACb,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;YACnE,CAAC;YAID,MAAM,OAAO,GACX,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS;gBAC3B,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC1C,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;YAClB,OAAO,mBAAmB,CAAC;gBACzB,OAAO;gBACP,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,KAAK,EAAE,GAAG,CAAC,KAAK;aACjB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AAcD,MAAM,UAAU,6BAA6B,CAAC,UAAU,GAAG,EAAE;IAC3D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,kEAAkE,UAAU,EAAE,CAAC,CAAC;IAClG,CAAC;IACD,OAAO;QACL,MAAM,EAAE,QAAQ;QAChB,KAAK,CAAC,KAAK;YACT,OAAO,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface AccessTokenPayload {
|
|
2
|
+
iss: string;
|
|
3
|
+
sub: string;
|
|
4
|
+
aud: string[];
|
|
5
|
+
exp: number;
|
|
6
|
+
iat: number;
|
|
7
|
+
nbf?: number;
|
|
8
|
+
jti?: string;
|
|
9
|
+
scope?: string;
|
|
10
|
+
client_id?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface GenerateAccessTokenOptions {
|
|
14
|
+
payload: AccessTokenPayload;
|
|
15
|
+
privateKey: CryptoKey;
|
|
16
|
+
keyId?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function generateAccessToken(options: GenerateAccessTokenOptions): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=access-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-token.d.ts","sourceRoot":"","sources":["../src/access-token.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IAKZ,GAAG,CAAC,EAAE,MAAM,CAAC;IAeb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAKD,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,UAAU,EAAE,SAAS,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA2DD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CA6B9F"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { sign, arrayBufferToBase64Url, stringToArrayBuffer, getJwaAlgorithm } from './crypto-utils.js';
|
|
2
|
+
function validatePayload(payload) {
|
|
3
|
+
if (!payload.iss) {
|
|
4
|
+
throw new Error('Missing required claim: iss');
|
|
5
|
+
}
|
|
6
|
+
if (!payload.sub) {
|
|
7
|
+
throw new Error('Missing required claim: sub');
|
|
8
|
+
}
|
|
9
|
+
if (payload.aud === undefined || payload.aud === null) {
|
|
10
|
+
throw new Error('Missing required claim: aud');
|
|
11
|
+
}
|
|
12
|
+
if (!Array.isArray(payload.aud) || payload.aud.length === 0) {
|
|
13
|
+
throw new Error('Invalid aud claim: must be a non-empty array');
|
|
14
|
+
}
|
|
15
|
+
if (payload.exp === undefined || payload.exp === null) {
|
|
16
|
+
throw new Error('Missing required claim: exp');
|
|
17
|
+
}
|
|
18
|
+
const now = Math.floor(Date.now() / 1000);
|
|
19
|
+
const clockSkewTolerance = 60;
|
|
20
|
+
if (payload.exp < now - clockSkewTolerance) {
|
|
21
|
+
throw new Error('Token expiration time is in the past');
|
|
22
|
+
}
|
|
23
|
+
if (payload.iat === undefined || payload.iat === null) {
|
|
24
|
+
throw new Error('Missing required claim: iat');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function base64UrlEncode(str) {
|
|
28
|
+
return arrayBufferToBase64Url(stringToArrayBuffer(str));
|
|
29
|
+
}
|
|
30
|
+
export async function generateAccessToken(options) {
|
|
31
|
+
const { payload, privateKey, keyId } = options;
|
|
32
|
+
validatePayload(payload);
|
|
33
|
+
const header = {
|
|
34
|
+
alg: getJwaAlgorithm(privateKey),
|
|
35
|
+
typ: 'at+jwt',
|
|
36
|
+
};
|
|
37
|
+
if (keyId) {
|
|
38
|
+
header.kid = keyId;
|
|
39
|
+
}
|
|
40
|
+
const headerB64 = base64UrlEncode(JSON.stringify(header));
|
|
41
|
+
const payloadB64 = base64UrlEncode(JSON.stringify(payload));
|
|
42
|
+
const signingInput = `${headerB64}.${payloadB64}`;
|
|
43
|
+
const signature = await sign(signingInput, privateKey);
|
|
44
|
+
return `${signingInput}.${signature}`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=access-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-token.js","sourceRoot":"","sources":["../src/access-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAiDvG,SAAS,eAAe,CAAC,OAA2B;IAElD,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAID,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAGD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1C,MAAM,kBAAkB,GAAG,EAAE,CAAC;IAC9B,IAAI,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG,kBAAkB,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAKD,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,sBAAsB,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,CAAC;AAYD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAmC;IAC3E,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAG/C,eAAe,CAAC,OAAO,CAAC,CAAC;IAKzB,MAAM,MAAM,GAA2B;QACrC,GAAG,EAAE,eAAe,CAAC,UAAU,CAAC;QAChC,GAAG,EAAE,QAAQ;KACd,CAAC;IAEF,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,GAAG,GAAG,KAAK,CAAC;IACrB,CAAC;IAGD,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAG5D,MAAM,YAAY,GAAG,GAAG,SAAS,IAAI,UAAU,EAAE,CAAC;IAGlD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAEvD,OAAO,GAAG,YAAY,IAAI,SAAS,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { ValidatedAuthorizationRequest } from './authorization-request.js';
|
|
2
|
+
import type { ClaimsParameter } from './userinfo.js';
|
|
3
|
+
export interface SessionInfo {
|
|
4
|
+
subject: string;
|
|
5
|
+
authTime: number;
|
|
6
|
+
}
|
|
7
|
+
export interface SessionResolver {
|
|
8
|
+
resolve(request: Request): Promise<SessionInfo | null>;
|
|
9
|
+
}
|
|
10
|
+
export interface ConsentResolver {
|
|
11
|
+
hasConsent(subject: string, clientId: string, scopes: string[]): Promise<boolean>;
|
|
12
|
+
recordConsent?(subject: string, clientId: string, scopes: string[]): Promise<void>;
|
|
13
|
+
revokeConsent?(subject: string, clientId: string): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare enum AuthTransactionErrorCode {
|
|
16
|
+
TransactionNotFound = "transaction_not_found",
|
|
17
|
+
TransactionExpired = "transaction_expired",
|
|
18
|
+
InvalidCsrfToken = "invalid_csrf_token",
|
|
19
|
+
MaxAttemptsExceeded = "max_attempts_exceeded"
|
|
20
|
+
}
|
|
21
|
+
export declare class AuthTransactionError extends Error {
|
|
22
|
+
readonly code: AuthTransactionErrorCode;
|
|
23
|
+
constructor(code: AuthTransactionErrorCode, message: string);
|
|
24
|
+
get httpStatusCode(): number;
|
|
25
|
+
}
|
|
26
|
+
export interface AuthTransaction {
|
|
27
|
+
clientId: string;
|
|
28
|
+
redirectUri: string;
|
|
29
|
+
redirectUriExplicit: boolean;
|
|
30
|
+
responseType: string;
|
|
31
|
+
scope: string;
|
|
32
|
+
state?: string;
|
|
33
|
+
nonce?: string;
|
|
34
|
+
codeChallenge?: string;
|
|
35
|
+
codeChallengeMethod?: 'S256';
|
|
36
|
+
prompt?: string;
|
|
37
|
+
maxAge?: number;
|
|
38
|
+
acrValues?: string;
|
|
39
|
+
loginHint?: string;
|
|
40
|
+
uiLocales?: string;
|
|
41
|
+
claimsLocales?: string;
|
|
42
|
+
idTokenHint?: string;
|
|
43
|
+
audience?: string[];
|
|
44
|
+
claims?: ClaimsParameter;
|
|
45
|
+
csrfToken: string;
|
|
46
|
+
createdAt: number;
|
|
47
|
+
expiresAt: number;
|
|
48
|
+
failedAttempts: number;
|
|
49
|
+
}
|
|
50
|
+
export interface AuthTransactionStore {
|
|
51
|
+
get(key: string): Promise<AuthTransaction | null>;
|
|
52
|
+
put(key: string, transaction: AuthTransaction, ttlSeconds: number): Promise<void>;
|
|
53
|
+
delete(key: string): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
export interface AuthorizationResponseParams {
|
|
56
|
+
redirectUri: string;
|
|
57
|
+
redirectUriExplicit: boolean;
|
|
58
|
+
state?: string;
|
|
59
|
+
clientId: string;
|
|
60
|
+
scope: string[];
|
|
61
|
+
nonce?: string;
|
|
62
|
+
codeChallenge?: string;
|
|
63
|
+
codeChallengeMethod?: 'S256';
|
|
64
|
+
audience?: string[];
|
|
65
|
+
acrValues?: string;
|
|
66
|
+
claims?: ClaimsParameter;
|
|
67
|
+
}
|
|
68
|
+
export interface LoginFailureResult {
|
|
69
|
+
canRetry: boolean;
|
|
70
|
+
failedAttempts: number;
|
|
71
|
+
maxAttempts: number;
|
|
72
|
+
}
|
|
73
|
+
export declare function createAuthTransaction(validatedRequest: ValidatedAuthorizationRequest, csrfToken: string, ttlMs?: number): AuthTransaction;
|
|
74
|
+
export declare function getAuthTransaction(txnId: string, store: AuthTransactionStore): Promise<AuthTransaction>;
|
|
75
|
+
export declare function validateCsrfToken(transaction: AuthTransaction, csrfToken: string): void;
|
|
76
|
+
export declare function handleLoginFailure(txnId: string, transaction: AuthTransaction, store: AuthTransactionStore, maxAttempts?: number): Promise<LoginFailureResult>;
|
|
77
|
+
export interface PromptNoneOptions {
|
|
78
|
+
verifiedHintSubject?: string;
|
|
79
|
+
}
|
|
80
|
+
export declare function resolvePromptNoneSession(transaction: AuthTransaction, sessionResolver: SessionResolver, request: Request): Promise<SessionInfo>;
|
|
81
|
+
export declare function validatePromptNoneIdTokenHint(transaction: AuthTransaction, session: SessionInfo, verifiedHintSubject: string | undefined): void;
|
|
82
|
+
export declare function validatePromptNoneConsent(transaction: AuthTransaction, session: SessionInfo, consentResolver?: ConsentResolver): Promise<void>;
|
|
83
|
+
export declare function checkPromptNone(transaction: AuthTransaction, sessionResolver: SessionResolver, request: Request, consentResolver?: ConsentResolver, options?: PromptNoneOptions): Promise<SessionInfo>;
|
|
84
|
+
export declare function requiresReauthentication(maxAge: number, authTime: number): boolean;
|
|
85
|
+
export declare function completeAuthTransaction(txnId: string, transaction: AuthTransaction, store: AuthTransactionStore): Promise<AuthorizationResponseParams>;
|
|
86
|
+
//# sourceMappingURL=auth-transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-transaction.d.ts","sourceRoot":"","sources":["../src/auth-transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { AuthorizationError, AuthorizationErrorCode } from './authorization-request.js';
|
|
2
|
+
export var AuthTransactionErrorCode;
|
|
3
|
+
(function (AuthTransactionErrorCode) {
|
|
4
|
+
AuthTransactionErrorCode["TransactionNotFound"] = "transaction_not_found";
|
|
5
|
+
AuthTransactionErrorCode["TransactionExpired"] = "transaction_expired";
|
|
6
|
+
AuthTransactionErrorCode["InvalidCsrfToken"] = "invalid_csrf_token";
|
|
7
|
+
AuthTransactionErrorCode["MaxAttemptsExceeded"] = "max_attempts_exceeded";
|
|
8
|
+
})(AuthTransactionErrorCode || (AuthTransactionErrorCode = {}));
|
|
9
|
+
export class AuthTransactionError extends Error {
|
|
10
|
+
code;
|
|
11
|
+
constructor(code, message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'AuthTransactionError';
|
|
14
|
+
this.code = code;
|
|
15
|
+
}
|
|
16
|
+
get httpStatusCode() {
|
|
17
|
+
switch (this.code) {
|
|
18
|
+
case AuthTransactionErrorCode.TransactionNotFound:
|
|
19
|
+
return 400;
|
|
20
|
+
case AuthTransactionErrorCode.TransactionExpired:
|
|
21
|
+
return 400;
|
|
22
|
+
case AuthTransactionErrorCode.InvalidCsrfToken:
|
|
23
|
+
return 403;
|
|
24
|
+
case AuthTransactionErrorCode.MaxAttemptsExceeded:
|
|
25
|
+
return 429;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const DEFAULT_TTL_MS = 600_000;
|
|
30
|
+
const DEFAULT_MAX_ATTEMPTS = 5;
|
|
31
|
+
const STORE_KEY_PREFIX = 'auth_txn:';
|
|
32
|
+
export function createAuthTransaction(validatedRequest, csrfToken, ttlMs = DEFAULT_TTL_MS) {
|
|
33
|
+
const now = Date.now();
|
|
34
|
+
const transaction = {
|
|
35
|
+
clientId: validatedRequest.clientId,
|
|
36
|
+
redirectUri: validatedRequest.redirectUri,
|
|
37
|
+
redirectUriExplicit: validatedRequest.redirectUriExplicit,
|
|
38
|
+
responseType: validatedRequest.responseType,
|
|
39
|
+
scope: validatedRequest.scope.join(' '),
|
|
40
|
+
csrfToken,
|
|
41
|
+
createdAt: now,
|
|
42
|
+
expiresAt: now + ttlMs,
|
|
43
|
+
failedAttempts: 0,
|
|
44
|
+
};
|
|
45
|
+
if (validatedRequest.state !== undefined) {
|
|
46
|
+
transaction.state = validatedRequest.state;
|
|
47
|
+
}
|
|
48
|
+
if (validatedRequest.nonce !== undefined) {
|
|
49
|
+
transaction.nonce = validatedRequest.nonce;
|
|
50
|
+
}
|
|
51
|
+
if (validatedRequest.codeChallenge !== undefined) {
|
|
52
|
+
transaction.codeChallenge = validatedRequest.codeChallenge;
|
|
53
|
+
}
|
|
54
|
+
if (validatedRequest.codeChallengeMethod !== undefined) {
|
|
55
|
+
transaction.codeChallengeMethod = validatedRequest.codeChallengeMethod;
|
|
56
|
+
}
|
|
57
|
+
if (validatedRequest.prompt !== undefined) {
|
|
58
|
+
transaction.prompt = validatedRequest.prompt.join(' ');
|
|
59
|
+
}
|
|
60
|
+
if (validatedRequest.maxAge !== undefined) {
|
|
61
|
+
transaction.maxAge = validatedRequest.maxAge;
|
|
62
|
+
}
|
|
63
|
+
if (validatedRequest.acrValues !== undefined) {
|
|
64
|
+
transaction.acrValues = validatedRequest.acrValues;
|
|
65
|
+
}
|
|
66
|
+
if (validatedRequest.loginHint !== undefined) {
|
|
67
|
+
transaction.loginHint = validatedRequest.loginHint;
|
|
68
|
+
}
|
|
69
|
+
if (validatedRequest.uiLocales !== undefined) {
|
|
70
|
+
transaction.uiLocales = validatedRequest.uiLocales;
|
|
71
|
+
}
|
|
72
|
+
if (validatedRequest.claimsLocales !== undefined) {
|
|
73
|
+
transaction.claimsLocales = validatedRequest.claimsLocales;
|
|
74
|
+
}
|
|
75
|
+
if (validatedRequest.idTokenHint !== undefined) {
|
|
76
|
+
transaction.idTokenHint = validatedRequest.idTokenHint;
|
|
77
|
+
}
|
|
78
|
+
if (validatedRequest.audience !== undefined) {
|
|
79
|
+
transaction.audience = validatedRequest.audience;
|
|
80
|
+
}
|
|
81
|
+
if (validatedRequest.claims !== undefined) {
|
|
82
|
+
transaction.claims = validatedRequest.claims;
|
|
83
|
+
}
|
|
84
|
+
return transaction;
|
|
85
|
+
}
|
|
86
|
+
export async function getAuthTransaction(txnId, store) {
|
|
87
|
+
const key = `${STORE_KEY_PREFIX}${txnId}`;
|
|
88
|
+
const transaction = await store.get(key);
|
|
89
|
+
if (!transaction) {
|
|
90
|
+
throw new AuthTransactionError(AuthTransactionErrorCode.TransactionNotFound, 'Auth transaction not found. The session may have expired.');
|
|
91
|
+
}
|
|
92
|
+
if (transaction.expiresAt <= Date.now()) {
|
|
93
|
+
throw new AuthTransactionError(AuthTransactionErrorCode.TransactionExpired, 'Auth transaction has expired. Please start the authorization flow again.');
|
|
94
|
+
}
|
|
95
|
+
return transaction;
|
|
96
|
+
}
|
|
97
|
+
export function validateCsrfToken(transaction, csrfToken) {
|
|
98
|
+
if (!csrfToken || csrfToken !== transaction.csrfToken) {
|
|
99
|
+
throw new AuthTransactionError(AuthTransactionErrorCode.InvalidCsrfToken, 'Invalid CSRF token.');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export async function handleLoginFailure(txnId, transaction, store, maxAttempts = DEFAULT_MAX_ATTEMPTS) {
|
|
103
|
+
const key = `${STORE_KEY_PREFIX}${txnId}`;
|
|
104
|
+
transaction.failedAttempts++;
|
|
105
|
+
if (transaction.failedAttempts >= maxAttempts) {
|
|
106
|
+
await store.delete(key);
|
|
107
|
+
return {
|
|
108
|
+
canRetry: false,
|
|
109
|
+
failedAttempts: transaction.failedAttempts,
|
|
110
|
+
maxAttempts,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const remainingTtlMs = transaction.expiresAt - Date.now();
|
|
114
|
+
const remainingTtlSeconds = Math.max(1, Math.ceil(remainingTtlMs / 1000));
|
|
115
|
+
await store.put(key, transaction, remainingTtlSeconds);
|
|
116
|
+
return {
|
|
117
|
+
canRetry: true,
|
|
118
|
+
failedAttempts: transaction.failedAttempts,
|
|
119
|
+
maxAttempts,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export async function resolvePromptNoneSession(transaction, sessionResolver, request) {
|
|
123
|
+
const session = await sessionResolver.resolve(request);
|
|
124
|
+
if (!session) {
|
|
125
|
+
throw new AuthorizationError(AuthorizationErrorCode.LoginRequired, 'No active session found. Silent authentication failed.', transaction.redirectUri, transaction.state);
|
|
126
|
+
}
|
|
127
|
+
return session;
|
|
128
|
+
}
|
|
129
|
+
export function validatePromptNoneIdTokenHint(transaction, session, verifiedHintSubject) {
|
|
130
|
+
if (verifiedHintSubject !== undefined && verifiedHintSubject !== session.subject) {
|
|
131
|
+
throw new AuthorizationError(AuthorizationErrorCode.LoginRequired, 'id_token_hint subject does not match the active session.', transaction.redirectUri, transaction.state);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
export async function validatePromptNoneConsent(transaction, session, consentResolver) {
|
|
135
|
+
if (!consentResolver)
|
|
136
|
+
return;
|
|
137
|
+
const scopes = transaction.scope.split(' ').filter(Boolean);
|
|
138
|
+
const hasConsent = await consentResolver.hasConsent(session.subject, transaction.clientId, scopes);
|
|
139
|
+
if (!hasConsent) {
|
|
140
|
+
throw new AuthorizationError(AuthorizationErrorCode.ConsentRequired, 'Consent has not been granted. Silent authentication cannot show consent UI.', transaction.redirectUri, transaction.state);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
export async function checkPromptNone(transaction, sessionResolver, request, consentResolver, options) {
|
|
144
|
+
const session = await resolvePromptNoneSession(transaction, sessionResolver, request);
|
|
145
|
+
validatePromptNoneIdTokenHint(transaction, session, options?.verifiedHintSubject);
|
|
146
|
+
await validatePromptNoneConsent(transaction, session, consentResolver);
|
|
147
|
+
return session;
|
|
148
|
+
}
|
|
149
|
+
export function requiresReauthentication(maxAge, authTime) {
|
|
150
|
+
if (maxAge <= 0)
|
|
151
|
+
return true;
|
|
152
|
+
const now = Math.floor(Date.now() / 1000);
|
|
153
|
+
return now - authTime > maxAge;
|
|
154
|
+
}
|
|
155
|
+
export async function completeAuthTransaction(txnId, transaction, store) {
|
|
156
|
+
const key = `${STORE_KEY_PREFIX}${txnId}`;
|
|
157
|
+
await store.delete(key);
|
|
158
|
+
const result = {
|
|
159
|
+
redirectUri: transaction.redirectUri,
|
|
160
|
+
redirectUriExplicit: transaction.redirectUriExplicit,
|
|
161
|
+
clientId: transaction.clientId,
|
|
162
|
+
scope: transaction.scope.split(' '),
|
|
163
|
+
};
|
|
164
|
+
if (transaction.state !== undefined) {
|
|
165
|
+
result.state = transaction.state;
|
|
166
|
+
}
|
|
167
|
+
if (transaction.codeChallenge !== undefined) {
|
|
168
|
+
result.codeChallenge = transaction.codeChallenge;
|
|
169
|
+
}
|
|
170
|
+
if (transaction.codeChallengeMethod !== undefined) {
|
|
171
|
+
result.codeChallengeMethod = transaction.codeChallengeMethod;
|
|
172
|
+
}
|
|
173
|
+
if (transaction.nonce !== undefined) {
|
|
174
|
+
result.nonce = transaction.nonce;
|
|
175
|
+
}
|
|
176
|
+
if (transaction.audience !== undefined) {
|
|
177
|
+
result.audience = transaction.audience;
|
|
178
|
+
}
|
|
179
|
+
if (transaction.acrValues !== undefined) {
|
|
180
|
+
result.acrValues = transaction.acrValues;
|
|
181
|
+
}
|
|
182
|
+
if (transaction.claims !== undefined) {
|
|
183
|
+
result.claims = transaction.claims;
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=auth-transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-transaction.js","sourceRoot":"","sources":["../src/auth-transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AuthorizationCodeInfo, AuthorizationCodeResolver, TokenRequestContext, TokenRequestParams, ValidatedAuthorizationCodeRequest } from './token-request.js';
|
|
2
|
+
export interface ResolvedAuthorizationCode {
|
|
3
|
+
code: string;
|
|
4
|
+
authorizationCode: AuthorizationCodeInfo;
|
|
5
|
+
}
|
|
6
|
+
export declare function resolveAuthorizationCode(params: TokenRequestParams, authCodeResolver: AuthorizationCodeResolver): Promise<ResolvedAuthorizationCode>;
|
|
7
|
+
export declare function validateAuthorizationCodeUnused(authorizationCode: AuthorizationCodeInfo, authCodeResolver: AuthorizationCodeResolver): Promise<void>;
|
|
8
|
+
export declare function validateAuthorizationCodeClient(authorizationCode: AuthorizationCodeInfo, authenticatedClientId: string): void;
|
|
9
|
+
export declare function validateAuthorizationCodeExpiration(authorizationCode: AuthorizationCodeInfo, currentTime?: number): void;
|
|
10
|
+
export declare function validateAuthorizationCodeRedirectUri(authorizationCode: AuthorizationCodeInfo, requestRedirectUri: string | undefined): void;
|
|
11
|
+
export declare function verifyAuthorizationCodePkce(authorizationCode: AuthorizationCodeInfo, codeVerifier: string | undefined): Promise<boolean>;
|
|
12
|
+
export declare function consumeAuthorizationCode(code: string, authCodeResolver: AuthorizationCodeResolver): Promise<void>;
|
|
13
|
+
export declare function buildValidatedAuthorizationCodeRequest(code: string, authorizationCode: AuthorizationCodeInfo, authenticatedClientId: string, codeVerified: boolean): ValidatedAuthorizationCodeRequest;
|
|
14
|
+
export declare function validateAuthorizationCodeGrant(context: TokenRequestContext): Promise<ValidatedAuthorizationCodeRequest>;
|
|
15
|
+
//# sourceMappingURL=authorization-code-grant.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization-code-grant.d.ts","sourceRoot":"","sources":["../src/authorization-code-grant.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,iCAAiC,EAClC,MAAM,oBAAoB,CAAC;AAQ5B,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,qBAAqB,CAAC;CAC1C;AAqBD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,kBAAkB,EAC1B,gBAAgB,EAAE,yBAAyB,GAC1C,OAAO,CAAC,yBAAyB,CAAC,CAmBpC;AAQD,wBAAsB,+BAA+B,CACnD,iBAAiB,EAAE,qBAAqB,EACxC,gBAAgB,EAAE,yBAAyB,GAC1C,OAAO,CAAC,IAAI,CAAC,CAYf;AAKD,wBAAgB,+BAA+B,CAC7C,iBAAiB,EAAE,qBAAqB,EACxC,qBAAqB,EAAE,MAAM,GAC5B,IAAI,CAON;AAQD,wBAAgB,mCAAmC,CACjD,iBAAiB,EAAE,qBAAqB,EACxC,WAAW,GAAE,MAAsC,GAClD,IAAI,CAON;AASD,wBAAgB,oCAAoC,CAClD,iBAAiB,EAAE,qBAAqB,EACxC,kBAAkB,EAAE,MAAM,GAAG,SAAS,GACrC,IAAI,CA0BN;AAQD,wBAAsB,2BAA2B,CAC/C,iBAAiB,EAAE,qBAAqB,EACxC,YAAY,EAAE,MAAM,GAAG,SAAS,GAC/B,OAAO,CAAC,OAAO,CAAC,CAqDlB;AAQD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,yBAAyB,GAC1C,OAAO,CAAC,IAAI,CAAC,CAEf;AAKD,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,qBAAqB,EACxC,qBAAqB,EAAE,MAAM,EAC7B,YAAY,EAAE,OAAO,GACpB,iCAAiC,CAcnC;AAuBD,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,iCAAiC,CAAC,CA0B5C"}
|