@o3co/auth.policy-verifier.builtins 0.9.0 → 0.11.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.ja.md +27 -6
- package/README.md +3 -3
- package/package.json +5 -5
package/README.ja.md
CHANGED
|
@@ -16,14 +16,32 @@ npm install @o3co/auth.policy-verifier.builtins
|
|
|
16
16
|
|
|
17
17
|
| 名前 | 読み取り元 | 出力 | コンストラクタ引数 |
|
|
18
18
|
| --- | --- | --- | --- |
|
|
19
|
-
| `PayloadScopeCollector` | `subject.scope
|
|
19
|
+
| `PayloadScopeCollector` | scope クレーム — 既定は `subject.scope`。スペース区切り文字列または文字列の配列 | `ATTR_SCOPES: string[]` | `{ claim?: string }`(#219: Okta なら `"scp"`、Auth0 なら `"permissions"`) |
|
|
20
20
|
| `PayloadSubjectIdCollector` | `subject.sub`、`subject.azp` | `ATTR_USER_ID`、`ATTR_CLIENT_ID` | なし |
|
|
21
21
|
| `StaticPermissionCollector` | — | `ATTR_PERMISSIONS: string[]` | `{ permissions: string[] }` |
|
|
22
22
|
| `StaticRoleCollector` | — | `ATTR_ROLES: Role[]` | `{ roles: Role[] }` |
|
|
23
23
|
| `RequestContextAttributeCollector` | `requestContext` の宣言済みフィールド | 運用者が決めたキー | `{ attributes: Mapping[] }` |
|
|
24
|
+
| `PayloadClaimAttributeCollector` | 検証済み `subject` の宣言済みクレーム | 運用者が決めたキー、または core の 5 キー | `{ attributes: Mapping[] }` (#219) |
|
|
24
25
|
|
|
25
26
|
`StaticPermissionCollector` と `StaticRoleCollector` は、リクエストのコンテキストに関わらず、コンストラクタに渡した値を常に出力します。
|
|
26
27
|
|
|
28
|
+
### PayloadClaimAttributeCollector
|
|
29
|
+
|
|
30
|
+
**検証済み subject** の宣言済みクレームを attribute に昇格させます (#219) — 専用のコレクターを書かずに、外部 IdP のクレームを Rule が読む形へ変える、運用者が宣言する方法です:
|
|
31
|
+
|
|
32
|
+
```hocon
|
|
33
|
+
{ collector = "PayloadClaimAttributeCollector"
|
|
34
|
+
attributes = [
|
|
35
|
+
{ from = "o.rol", to = "roles", type = "string[]" } # Clerk: org のロール。dot path で指定
|
|
36
|
+
{ from = "https://example.com/roles", to = "roles", type = "string[]" } # Auth0: 名前空間付きクレームはパスではなく 1 つのキー
|
|
37
|
+
{ from = "tid", to = "tenantId" }
|
|
38
|
+
] }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
マッピングの形は `RequestContextAttributeCollector` と同じです(`{ from, to?, type? }`、完全一致するキーが dot path より優先、own property のみ)。違うのは読み取り元であり、したがって信頼度です: subject バッグは authenticator が検証したものなので、request-context コレクターが拒否する core の 5 キー — `scopes`、`permissions`、`roles`、`userId`、`clientId` — にもマッピングを着地させて**かまいません**。2 つのコレクターが 1 つのリストキーに書けば union されます。それはデプロイが issuer 由来の 2 つのソースを合成しているということであり、config にそう書かれています。一方、2 つのコレクターが異なる値で書いた*スカラー*キーは `AttributeConflictError` を投げ、すべてのリクエストを deny します — `PayloadSubjectIdCollector` も `userId` / `clientId` を書いている間は、そこへマッピングしないでください。別のパッケージが予約したキー(cedar の `request*`)は引き続き拒否されます。それらは subject ではなくリクエストから導出されるものだからです。そして、マッピングするのは IdP が自身の登録データや管理データから埋めるクレームだけにしてください: ユーザーが編集できるメタデータ(Clerk の `unsafe_metadata`、Auth0 の `user_metadata`)から発行されたクレームは、署名されてはいても信頼できるものではありません。
|
|
42
|
+
|
|
43
|
+
scope クレームについては `PayloadScopeCollector { claim = "scp" }` を優先してください。こちらはスペース区切り文字列の形も読み、`ResourceActionScopeRuleCollector { claim = "scp" }` と組にすることで、どのトークンが scopeless かについて両者の判断が一致します。
|
|
44
|
+
|
|
27
45
|
### RequestContextAttributeCollector
|
|
28
46
|
|
|
29
47
|
`CollectorContext.requestContext` の宣言済みフィールドを attribute に昇格させます:
|
|
@@ -36,7 +54,7 @@ npm install @o3co/auth.policy-verifier.builtins
|
|
|
36
54
|
] }
|
|
37
55
|
```
|
|
38
56
|
|
|
39
|
-
各マッピングは `{ from: string; to?: string; type?: "string" | "number" | "boolean" | "string[]" }` で、`type` の既定は `"string"`
|
|
57
|
+
各マッピングは `{ from: string; to?: string; type?: "string" | "number" | "boolean" | "string[]" }` で、`type` の既定は `"string"` です。`context` 上で完全一致するキーは dot path の走査より優先されます: `"tenant.id"` という文字どおりのフィールドは、`tenant` → `id` より先に読まれます。マッピング定義が不正ならコンストラクタで throw しますが、*値* が使えない場合は throw しません — `requestContext` は呼び出し側が渡すリクエストデータなので、欠落・空文字・宣言した型に合わない値は単に昇格されません。
|
|
40
58
|
|
|
41
59
|
この宣言が信頼境界です — [docs/extending.ja.md](../../docs/extending.ja.md#信頼境界-requestcontext-は呼び出し側のもの) が説明する境界の、既製の守り方がこのコレクターです。`requestContext` は自由形式かつ未検証なので、**宣言していないフィールドは attribute になりません**。dot path は own property のみを辿るため `constructor.name` のような指定は何も読みません。このコレクター自身は語彙を持ち込みません — フィールド名もキー名も運用者が決めるため、[AGENTS.md — Core Vocabulary Scope](../../AGENTS.md#core-vocabulary-scope) の方針を崩さずに実用的なものを提供できます。read-check-write を超える処理(値の導出、外部ストア参照など)が必要な場合は、同節が説明するプロジェクト側の `AttributeCollector` を書いてください。
|
|
42
60
|
|
|
@@ -75,11 +93,13 @@ new HasPermission(permission: string)
|
|
|
75
93
|
|
|
76
94
|
- `ruleType`: `"permission"`、`code`: `"no_permission"`
|
|
77
95
|
- `ATTR_PERMISSIONS`(直接)と `ATTR_ROLES[].permissions`(ロール経由)を確認します。
|
|
78
|
-
-
|
|
96
|
+
- 比較は**大文字・小文字を区別する完全一致**です — `HasScope` が scope に、`DotNotationResourceParser` がリソースに適用しているのと同じ規律で、書かれたものをそのまま比較し、意図を正規化して推測しません。パーサーは大文字・小文字を保持するため、scope ルールにとって `Project:1` と `project:1` が別のリソースであるのとまったく同じく、`Project:1.perm:read` と `project:1.perm:read` は別の permission です。
|
|
97
|
+
- **付与された** permission 内のワイルドカードは尊重されます — 正規化ではなく、書かれたマッチ構造だからです。`*` の前後のリテラル部分は引き続き完全一致で比較されます:
|
|
79
98
|
- `"*"` はすべての permission に一致。
|
|
80
99
|
- `"foo*"` はプレフィックスが `foo` の permission に一致。
|
|
81
100
|
- `"*bar"` はサフィックスが `bar` の permission に一致。
|
|
82
101
|
- `"foo*bar"` は `foo` で始まり `bar` で終わる permission に一致。
|
|
102
|
+
- 付与された permission に `*` が 2 つ以上含まれる場合は決して一致しません(黙って過剰付与するより拒否する方がよいため)。
|
|
83
103
|
|
|
84
104
|
### HasScope
|
|
85
105
|
|
|
@@ -212,9 +232,9 @@ new AttrPairCompare({ a: string, op: "lt" | "le" | "gt" | "ge", b: string, group
|
|
|
212
232
|
| `ResourceActionScopeRuleCollector` | `"<action>:<resource.resourceType>"` | `[HasScope(...)]` |
|
|
213
233
|
|
|
214
234
|
`ResourceActionPermissionRuleCollector` にコンストラクタ引数はありません。
|
|
215
|
-
`ResourceActionScopeRuleCollector` は `{ scopeless?: "deny" | "skip", allowBareScopeRewrite?: boolean }`
|
|
235
|
+
`ResourceActionScopeRuleCollector` は `{ scopeless?: "deny" | "skip", allowBareScopeRewrite?: boolean, claim?: string }` を受け取ります — `claim` はトークンが scope を主張していることを示す claim の名前です(既定 `scope`。`PayloadScopeCollector` が読むもの、例えば `scp` に合わせる)。
|
|
216
236
|
|
|
217
|
-
- `scopeless`(既定 `"deny"`): 既定ではリクエストごとに必ず `HasScope`
|
|
237
|
+
- `scopeless`(既定 `"deny"`): 既定ではリクエストごとに必ず `HasScope` ルールを生成するため、scope claim(`scope`、または `claim` が指す claim)を持たない
|
|
218
238
|
トークンはこのルールに落ちます。`"skip"` は scopeless トークンに対してルールを生成しませんが、ルールが 1 つも集まらない
|
|
219
239
|
リクエストは deny されるため、別のルールグループが認可を担うパイプラインでのみ使ってください。
|
|
220
240
|
- `allowBareScopeRewrite`(既定 `false`): [`HasScope`](#hasscope) へそのまま渡されます。issuer が `{action}:{resourceType}`
|
|
@@ -281,11 +301,12 @@ import { builtinCollectorsModule } from "@o3co/auth.policy-verifier.builtins";
|
|
|
281
301
|
|
|
282
302
|
| レジストリ | 名前 | ファクトリ |
|
|
283
303
|
| --- | --- | --- |
|
|
284
|
-
| `attributeCollector` | `"PayloadScopeCollector"` | `() => new PayloadScopeCollector()` |
|
|
304
|
+
| `attributeCollector` | `"PayloadScopeCollector"` | `(config) => new PayloadScopeCollector(config)` |
|
|
285
305
|
| `attributeCollector` | `"PayloadSubjectIdCollector"` | `() => new PayloadSubjectIdCollector()` |
|
|
286
306
|
| `attributeCollector` | `"StaticPermissionCollector"` | `(config) => new StaticPermissionCollector(config)` |
|
|
287
307
|
| `attributeCollector` | `"StaticRoleCollector"` | `(config) => new StaticRoleCollector(config)` |
|
|
288
308
|
| `attributeCollector` | `"RequestContextAttributeCollector"` | `(config) => new RequestContextAttributeCollector(config)` |
|
|
309
|
+
| `attributeCollector` | `"PayloadClaimAttributeCollector"` | `(config) => new PayloadClaimAttributeCollector(config)` |
|
|
289
310
|
| `ruleCollector` | `"ResourceActionScopeRuleCollector"` | `(config) => new ResourceActionScopeRuleCollector(config)` |
|
|
290
311
|
| `ruleCollector` | `"ResourceActionPermissionRuleCollector"` | `() => new ResourceActionPermissionRuleCollector()` |
|
|
291
312
|
| `resourceParser` | `"DotNotationResourceParser"` | `() => new DotNotationResourceParser()` |
|
package/README.md
CHANGED
|
@@ -232,10 +232,10 @@ All attribute comparison rules follow the same grouping semantics described for
|
|
|
232
232
|
| `ResourceActionScopeRuleCollector` | `"<action>:<resource.resourceType>"` | `[HasScope(...)]` |
|
|
233
233
|
|
|
234
234
|
`ResourceActionPermissionRuleCollector` takes no constructor arguments.
|
|
235
|
-
`ResourceActionScopeRuleCollector` accepts `{ scopeless?: "deny" | "skip", allowBareScopeRewrite?: boolean }
|
|
235
|
+
`ResourceActionScopeRuleCollector` accepts `{ scopeless?: "deny" | "skip", allowBareScopeRewrite?: boolean, claim?: string }` — `claim` names the claim whose presence says the token asserted scopes (default `scope`; set it to what `PayloadScopeCollector` reads, e.g. `scp`).
|
|
236
236
|
|
|
237
|
-
- `scopeless` (default `"deny"`): it emits the `HasScope` rule for every request, so a token carrying no
|
|
238
|
-
claim fails it. `"skip"` emits no rule for a scopeless token — only use it in a pipeline where another rule
|
|
237
|
+
- `scopeless` (default `"deny"`): it emits the `HasScope` rule for every request, so a token carrying no scope
|
|
238
|
+
claim (`scope`, or the claim `claim` names) fails it. `"skip"` emits no rule for a scopeless token — only use it in a pipeline where another rule
|
|
239
239
|
group authorizes the request, since a request that collects no rule at all is denied.
|
|
240
240
|
- `allowBareScopeRewrite` (default `false`): forwarded to [`HasScope`](#hasscope). Set it to `true` only if your
|
|
241
241
|
issuer emits bare resource names (`project`) rather than `{action}:{resourceType}` scopes (`read:project`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@o3co/auth.policy-verifier.builtins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@o3co/auth.policy-verifier.core": "0.
|
|
34
|
+
"@o3co/auth.policy-verifier.core": "0.11.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@types/node": "^26.
|
|
38
|
-
"@vitest/coverage-v8": "^
|
|
39
|
-
"vitest": "^
|
|
37
|
+
"@types/node": "^26.5.1",
|
|
38
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
39
|
+
"vitest": "^5.0.0"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"prebuild": "rimraf dist",
|