@spinajs/rbac-http-token 2.0.513 → 2.0.515
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 +62 -6
- package/lib/cjs/actions.d.ts +43 -7
- package/lib/cjs/actions.d.ts.map +1 -1
- package/lib/cjs/actions.js +95 -16
- package/lib/cjs/actions.js.map +1 -1
- package/lib/cjs/cli/CreateToken.js +1 -1
- package/lib/cjs/cli/CreateToken.js.map +1 -1
- package/lib/cjs/cli/GrantTokenRole.js +1 -1
- package/lib/cjs/cli/GrantTokenRole.js.map +1 -1
- package/lib/cjs/config/rbac-http-token.d.ts +17 -0
- package/lib/cjs/config/rbac-http-token.d.ts.map +1 -1
- package/lib/cjs/config/rbac-http-token.js +17 -0
- package/lib/cjs/config/rbac-http-token.js.map +1 -1
- package/lib/cjs/controllers/AccessTokenController.d.ts +38 -5
- package/lib/cjs/controllers/AccessTokenController.d.ts.map +1 -1
- package/lib/cjs/controllers/AccessTokenController.js +60 -6
- package/lib/cjs/controllers/AccessTokenController.js.map +1 -1
- package/lib/cjs/dto/create-token-dto.d.ts +7 -0
- package/lib/cjs/dto/create-token-dto.d.ts.map +1 -1
- package/lib/cjs/dto/create-token-dto.js +7 -1
- package/lib/cjs/dto/create-token-dto.js.map +1 -1
- package/lib/cjs/index.d.ts +3 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +3 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/interfaces.d.ts +58 -0
- package/lib/cjs/interfaces.d.ts.map +1 -1
- package/lib/cjs/interfaces.js +41 -1
- package/lib/cjs/interfaces.js.map +1 -1
- package/lib/cjs/middlewares.d.ts +5 -0
- package/lib/cjs/middlewares.d.ts.map +1 -1
- package/lib/cjs/middlewares.js +11 -1
- package/lib/cjs/middlewares.js.map +1 -1
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts +6 -0
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts.map +1 -0
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js +24 -0
- package/lib/cjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js.map +1 -0
- package/lib/cjs/models/AccessToken.d.ts +6 -0
- package/lib/cjs/models/AccessToken.d.ts.map +1 -1
- package/lib/cjs/models/AccessToken.js.map +1 -1
- package/lib/cjs/role-policy.d.ts +28 -0
- package/lib/cjs/role-policy.d.ts.map +1 -0
- package/lib/cjs/role-policy.js +52 -0
- package/lib/cjs/role-policy.js.map +1 -0
- package/lib/mjs/actions.d.ts +43 -7
- package/lib/mjs/actions.d.ts.map +1 -1
- package/lib/mjs/actions.js +94 -17
- package/lib/mjs/actions.js.map +1 -1
- package/lib/mjs/cli/CreateToken.js +1 -1
- package/lib/mjs/cli/CreateToken.js.map +1 -1
- package/lib/mjs/cli/GrantTokenRole.js +1 -1
- package/lib/mjs/cli/GrantTokenRole.js.map +1 -1
- package/lib/mjs/config/rbac-http-token.d.ts +17 -0
- package/lib/mjs/config/rbac-http-token.d.ts.map +1 -1
- package/lib/mjs/config/rbac-http-token.js +17 -0
- package/lib/mjs/config/rbac-http-token.js.map +1 -1
- package/lib/mjs/controllers/AccessTokenController.d.ts +38 -5
- package/lib/mjs/controllers/AccessTokenController.d.ts.map +1 -1
- package/lib/mjs/controllers/AccessTokenController.js +62 -8
- package/lib/mjs/controllers/AccessTokenController.js.map +1 -1
- package/lib/mjs/dto/create-token-dto.d.ts +7 -0
- package/lib/mjs/dto/create-token-dto.d.ts.map +1 -1
- package/lib/mjs/dto/create-token-dto.js +7 -1
- package/lib/mjs/dto/create-token-dto.js.map +1 -1
- package/lib/mjs/index.d.ts +3 -0
- package/lib/mjs/index.d.ts.map +1 -1
- package/lib/mjs/index.js +3 -0
- package/lib/mjs/index.js.map +1 -1
- package/lib/mjs/interfaces.d.ts +58 -0
- package/lib/mjs/interfaces.d.ts.map +1 -1
- package/lib/mjs/interfaces.js +39 -0
- package/lib/mjs/interfaces.js.map +1 -1
- package/lib/mjs/middlewares.d.ts +5 -0
- package/lib/mjs/middlewares.d.ts.map +1 -1
- package/lib/mjs/middlewares.js +11 -1
- package/lib/mjs/middlewares.js.map +1 -1
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts +6 -0
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.d.ts.map +1 -0
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js +21 -0
- package/lib/mjs/migrations/RbacHttpTokenProfile_2026_08_21_00_00_00.js.map +1 -0
- package/lib/mjs/models/AccessToken.d.ts +6 -0
- package/lib/mjs/models/AccessToken.d.ts.map +1 -1
- package/lib/mjs/models/AccessToken.js.map +1 -1
- package/lib/mjs/role-policy.d.ts +28 -0
- package/lib/mjs/role-policy.d.ts.map +1 -0
- package/lib/mjs/role-policy.js +48 -0
- package/lib/mjs/role-policy.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -1
- package/lib/tsconfig.mjs.tsbuildinfo +1 -1
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -79,10 +79,62 @@ case-insensitive) or the configured fallback header (`x-api-key` by default).
|
|
|
79
79
|
outlive it, carry the victim's roles, and be invisible to them.
|
|
80
80
|
- A token always keeps at least one role - revoking the last one is refused
|
|
81
81
|
(400 / `E_TOKEN_ROLE_NOT_ALLOWED`). Delete the token to revoke it entirely.
|
|
82
|
-
- A token can never carry a role
|
|
82
|
+
- A token can never carry a role the configured policy disallows for its
|
|
83
|
+
owner, at creation or grant. The shipped default limits that to the owner's
|
|
84
|
+
own roles - see [Token role policy](#token-role-policy).
|
|
83
85
|
- `LastUsedAt` is stamped on use, throttled to one write per
|
|
84
86
|
`rbac.token.lastUsedUpdateInterval` seconds.
|
|
85
87
|
|
|
88
|
+
## Token role policy
|
|
89
|
+
|
|
90
|
+
`AccessTokenRolePolicy.allowedRoles(owner)` decides which roles an owner may
|
|
91
|
+
put on a token. There is exactly one method, but FOUR call sites -
|
|
92
|
+
`createToken`, `grantTokenRole`, `validateToken` and the `GET
|
|
93
|
+
user/tokens/roles` controller route (all through the shared `_allowed_roles`
|
|
94
|
+
helper in `src/actions.ts`) - share it deliberately: creation time and request
|
|
95
|
+
time have to agree on the same answer, or a role a user was allowed to pick
|
|
96
|
+
could be one their token silently loses (or gains) on the very next request.
|
|
97
|
+
|
|
98
|
+
**`owner` is only guaranteed to be a base `User` with `Metadata` populated -
|
|
99
|
+
nothing more.** `GET user/tokens/roles` and `createToken` (from `POST
|
|
100
|
+
user/tokens`) are handed `req.storage.User`, the application's `User`
|
|
101
|
+
subclass with whatever the request pipeline already hydrated onto it, while
|
|
102
|
+
`grantTokenRole` and `validateToken` are handed a base `User` loaded
|
|
103
|
+
independently of any application model override. A policy that reads a field
|
|
104
|
+
an application added to its own `User` subclass will see it on a
|
|
105
|
+
session-authenticated call and not on a token-authenticated one - implement
|
|
106
|
+
against base `User` + `Metadata` only.
|
|
107
|
+
|
|
108
|
+
The shipped default, `OwnRolesTokenRolePolicy`, answers with the owner's own
|
|
109
|
+
`Role` array. That is the behaviour this package had before the seam existed,
|
|
110
|
+
so an application that configures nothing sees no change.
|
|
111
|
+
|
|
112
|
+
To scope tokens more narrowly than "everything the owner can do" - or to allow
|
|
113
|
+
a token to carry a role that is not on the owner's `Role` list at all -
|
|
114
|
+
implement `AccessTokenRolePolicy`, decorate the class with
|
|
115
|
+
`@Injectable(AccessTokenRolePolicy)`, and name it in
|
|
116
|
+
`rbac.token.rolePolicy.service`, the same pattern
|
|
117
|
+
`rbac.token.generation.service` uses for the token generator.
|
|
118
|
+
|
|
119
|
+
Because `validateToken` re-asks the policy on every authenticated request
|
|
120
|
+
instead of trusting the roles stored on the token row, swapping in - or
|
|
121
|
+
tightening - a policy takes effect immediately on every existing token: there
|
|
122
|
+
is nothing to migrate or re-issue. `GET user/tokens/roles` exposes the same
|
|
123
|
+
answer to a caller before they create a token, from the same policy
|
|
124
|
+
`POST user/tokens` validates against, so a client is never offered a role that
|
|
125
|
+
creation would then refuse.
|
|
126
|
+
|
|
127
|
+
`rbac.token.excludedRoles` is a list of role-name patterns for a custom policy
|
|
128
|
+
to consult - it is not read by anything shipped in this package, including the
|
|
129
|
+
default policy. `_role_excluded(role, patterns)`, exported from
|
|
130
|
+
`src/role-policy.ts`, implements the matching: a pattern is either an exact
|
|
131
|
+
role name, or a name ending in `.*`, which matches that prefix and everything
|
|
132
|
+
beneath it - `route.*` matches `route.home` and `route.admin.users`, but not
|
|
133
|
+
`routes.read` (the dot is part of the boundary, so a pattern can never swallow
|
|
134
|
+
an unrelated role that merely starts with the same letters). No other
|
|
135
|
+
wildcard syntax is supported, on purpose - a full glob in a security list
|
|
136
|
+
invites patterns nobody can reason about.
|
|
137
|
+
|
|
86
138
|
## HTTP API (session auth required)
|
|
87
139
|
|
|
88
140
|
All routes live under the `user.tokens` resource and operate on the caller's own
|
|
@@ -90,15 +142,17 @@ tokens only - a foreign uuid simply reads as 404.
|
|
|
90
142
|
|
|
91
143
|
| Route | Description |
|
|
92
144
|
|---|---|
|
|
145
|
+
| `GET user/tokens/roles` | roles the caller may put on a token |
|
|
93
146
|
| `GET user/tokens` | list own tokens |
|
|
94
147
|
| `POST user/tokens` | create (`{ Name, Roles, ExpiresAt? }`), returns plaintext once |
|
|
95
148
|
| `DELETE user/tokens/:uuid` | revoke (delete) a token |
|
|
96
149
|
| `PUT user/tokens/:uuid/roles/:role` | grant role |
|
|
97
150
|
| `DELETE user/tokens/:uuid/roles/:role` | revoke role |
|
|
98
151
|
|
|
99
|
-
Responses: `400` for role refusals (role not
|
|
100
|
-
revoke), `401` without a valid session,
|
|
101
|
-
token-authenticated or impersonated, `404` for a
|
|
152
|
+
Responses: `400` for role refusals (role not allowed for the caller by the
|
|
153
|
+
configured role policy, last role revoke), `401` without a valid session,
|
|
154
|
+
`403` when the request is token-authenticated or impersonated, `404` for a
|
|
155
|
+
token the caller does not own.
|
|
102
156
|
|
|
103
157
|
## CLI
|
|
104
158
|
|
|
@@ -110,8 +164,8 @@ rbac:token-revoke <uuid> <role>
|
|
|
110
164
|
rbac:token-delete-expired # run cyclically from a worker
|
|
111
165
|
```
|
|
112
166
|
|
|
113
|
-
- `-r, --roles` is a comma separated list, and must be
|
|
114
|
-
|
|
167
|
+
- `-r, --roles` is a comma separated list, and must be allowed for the owner
|
|
168
|
+
by the configured role policy (see [Token role policy](#token-role-policy)).
|
|
115
169
|
- `-e, --expires` takes an ISO instant. Omitting the flag entirely means the
|
|
116
170
|
token never expires; an empty or unparsable value is refused rather than
|
|
117
171
|
silently treated as "no expiration".
|
|
@@ -134,6 +188,8 @@ See `src/config/rbac-http-token.ts` - `rbac.token.*`:
|
|
|
134
188
|
| Key | Default | Meaning |
|
|
135
189
|
|---|---|---|
|
|
136
190
|
| `rbac.token.generation.service` | `SecureRandomTokenProvider` | `AccessTokenGenerationProvider` implementation used to generate/hash tokens |
|
|
191
|
+
| `rbac.token.rolePolicy.service` | `OwnRolesTokenRolePolicy` | `AccessTokenRolePolicy` implementation that decides which roles an owner may put on a token (see [Token role policy](#token-role-policy)) |
|
|
192
|
+
| `rbac.token.excludedRoles` | `[]` | role-name patterns (exact, or `prefix.*`) for a custom policy to consult - not read by the shipped default |
|
|
137
193
|
| `rbac.token.prefix` | `spt_` | stable plaintext prefix, lets secret scanners recognise leaked tokens |
|
|
138
194
|
| `rbac.token.length` | `32` | random bytes per token (32 = 256 bit entropy) |
|
|
139
195
|
| `rbac.token.headerName` | `x-api-key` | fallback header checked when no `Authorization: Bearer` is present |
|
package/lib/cjs/actions.d.ts
CHANGED
|
@@ -27,19 +27,53 @@ export declare function _token(token: AccessToken | string): () => Promise<Acces
|
|
|
27
27
|
* populated ( needed for IsBanned checks downstream ).
|
|
28
28
|
*/
|
|
29
29
|
export declare function _owner(user: User | number | string): () => Promise<User>;
|
|
30
|
+
/**
|
|
31
|
+
* Roles the configured {@link AccessTokenRolePolicy} lets `owner` put on a
|
|
32
|
+
* token. Resolved per call rather than cached, so a policy that answers from
|
|
33
|
+
* live state ( the owner's current roles, the application's grants ) is not
|
|
34
|
+
* frozen at boot.
|
|
35
|
+
*
|
|
36
|
+
* Filters the policy's answer down to role names `accesscontrol` actually
|
|
37
|
+
* knows about ( i.e. present in `ac.getGrants()` ). A policy is arbitrary
|
|
38
|
+
* application code and may return a typo'd or stale role name; without this
|
|
39
|
+
* filter such a name would be offered by `GET user/tokens/roles`, accepted by
|
|
40
|
+
* `createToken`/`grantTokenRole` onto a token, and then make every request
|
|
41
|
+
* that token authenticates 500 - `checkRoutePermission` calls
|
|
42
|
+
* `ac.can(roles)[permission](resource)`, and `accesscontrol` throws
|
|
43
|
+
* `AccessControlError` for a role absent from its grants map. A role that
|
|
44
|
+
* grants nothing must never be offered or authorised in the first place.
|
|
45
|
+
*
|
|
46
|
+
* Filters with `Object.hasOwn`, not `Boolean(grants[r])`: `getGrants()` returns a plain
|
|
47
|
+
* object, so `grants['constructor']`, `['toString']`, `['valueOf']`, `['hasOwnProperty']`
|
|
48
|
+
* and `['__proto__']` all resolve truthy through the prototype chain even though no role by
|
|
49
|
+
* that name was ever registered. A policy returning `'constructor'` would otherwise survive
|
|
50
|
+
* this filter, get offered by `GET user/tokens/roles`, and be mintable onto a token.
|
|
51
|
+
*/
|
|
52
|
+
export declare function _allowed_roles(owner: User, profile?: string): Promise<string[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Profiles the configured {@link AccessTokenRolePolicy} lets `owner` pin a
|
|
55
|
+
* token to. Same live-resolution rationale as `_allowed_roles`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function _allowed_profiles(owner: User): Promise<string[]>;
|
|
30
58
|
/**
|
|
31
59
|
* Creates a new access token for a user.
|
|
32
60
|
*
|
|
33
|
-
* Roles must be a non-empty subset of the
|
|
34
|
-
*
|
|
35
|
-
*
|
|
61
|
+
* Roles must be a non-empty subset of the roles the configured
|
|
62
|
+
* {@link AccessTokenRolePolicy} allows the owner to carry ( see
|
|
63
|
+
* `_allowed_roles` above - not necessarily the owner's literal `Role` list ).
|
|
64
|
+
* `expiresAt` null means the token never expires. The plaintext is returned
|
|
65
|
+
* once and never persisted - only its hash is stored.
|
|
36
66
|
*
|
|
37
67
|
* @param user - owner: {@link User} instance, numeric id or uuid
|
|
38
68
|
* @param name - human readable label
|
|
39
|
-
* @param roles - roles carried by the token, subset of the
|
|
69
|
+
* @param roles - roles carried by the token, subset of what the configured
|
|
70
|
+
* {@link AccessTokenRolePolicy} allows the owner
|
|
40
71
|
* @param expiresAt - absolute expiration, or null for a token that never expires
|
|
72
|
+
* @param profile - role the token is pinned to, from what the configured
|
|
73
|
+
* {@link AccessTokenRolePolicy} offers the owner; omitted
|
|
74
|
+
* leaves the token unpinned ( legacy behaviour )
|
|
41
75
|
*/
|
|
42
|
-
export declare function createToken(user: User | number | string, name: string, roles: string[], expiresAt: DateTime | null): Promise<{
|
|
76
|
+
export declare function createToken(user: User | number | string, name: string, roles: string[], expiresAt: DateTime | null, profile?: string): Promise<{
|
|
43
77
|
Token: AccessToken;
|
|
44
78
|
Plaintext: string;
|
|
45
79
|
}>;
|
|
@@ -50,7 +84,8 @@ export declare function createToken(user: User | number | string, name: string,
|
|
|
50
84
|
*/
|
|
51
85
|
export declare function deleteToken(token: AccessToken | string): Promise<void>;
|
|
52
86
|
/**
|
|
53
|
-
* Adds a role to a token. The role must be
|
|
87
|
+
* Adds a role to a token. The role must be allowed for the token owner by the
|
|
88
|
+
* configured {@link AccessTokenRolePolicy}.
|
|
54
89
|
*
|
|
55
90
|
* @param token - {@link AccessToken} instance or its uuid
|
|
56
91
|
* @param role - role name to grant
|
|
@@ -78,7 +113,8 @@ export interface ITokenValidationResult {
|
|
|
78
113
|
User: User;
|
|
79
114
|
Token: AccessToken;
|
|
80
115
|
/**
|
|
81
|
-
* Token roles
|
|
116
|
+
* Token roles the configured {@link AccessTokenRolePolicy} still allows for
|
|
117
|
+
* the owner. Permission checks run with these.
|
|
82
118
|
*/
|
|
83
119
|
EffectiveRoles: string[];
|
|
84
120
|
}
|
package/lib/cjs/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAOrC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD;;;;;;;;;;GAUG;AACH,oBAAY,aAAa;IACvB,iBAAiB,IAAA;IACjB,eAAe,IAAA;IACf,qBAAqB,IAAA;IACrB,wBAAwB,IAAA;CACzB;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,CAM9E;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAYxE;AAeD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOrF;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGtE;AA8BD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC/L;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5E;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAcpG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAmBrG;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;IAEnB;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAyDtF;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC,CAU3D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3F"}
|
package/lib/cjs/actions.js
CHANGED
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.E_TOKEN_CODES = void 0;
|
|
7
7
|
exports._token = _token;
|
|
8
8
|
exports._owner = _owner;
|
|
9
|
+
exports._allowed_roles = _allowed_roles;
|
|
10
|
+
exports._allowed_profiles = _allowed_profiles;
|
|
9
11
|
exports.createToken = createToken;
|
|
10
12
|
exports.deleteToken = deleteToken;
|
|
11
13
|
exports.grantTokenRole = grantTokenRole;
|
|
@@ -20,6 +22,7 @@ const util_1 = require("@spinajs/util");
|
|
|
20
22
|
const configuration_1 = require("@spinajs/configuration");
|
|
21
23
|
const queue_1 = require("@spinajs/queue");
|
|
22
24
|
const exceptions_1 = require("@spinajs/exceptions");
|
|
25
|
+
const di_1 = require("@spinajs/di");
|
|
23
26
|
const AccessToken_js_1 = require("./models/AccessToken.js");
|
|
24
27
|
const interfaces_js_1 = require("./interfaces.js");
|
|
25
28
|
const index_js_1 = require("./events/index.js");
|
|
@@ -78,37 +81,101 @@ function _token_ev(event, ...args) {
|
|
|
78
81
|
};
|
|
79
82
|
}
|
|
80
83
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
84
|
+
* Roles the configured {@link AccessTokenRolePolicy} lets `owner` put on a
|
|
85
|
+
* token. Resolved per call rather than cached, so a policy that answers from
|
|
86
|
+
* live state ( the owner's current roles, the application's grants ) is not
|
|
87
|
+
* frozen at boot.
|
|
88
|
+
*
|
|
89
|
+
* Filters the policy's answer down to role names `accesscontrol` actually
|
|
90
|
+
* knows about ( i.e. present in `ac.getGrants()` ). A policy is arbitrary
|
|
91
|
+
* application code and may return a typo'd or stale role name; without this
|
|
92
|
+
* filter such a name would be offered by `GET user/tokens/roles`, accepted by
|
|
93
|
+
* `createToken`/`grantTokenRole` onto a token, and then make every request
|
|
94
|
+
* that token authenticates 500 - `checkRoutePermission` calls
|
|
95
|
+
* `ac.can(roles)[permission](resource)`, and `accesscontrol` throws
|
|
96
|
+
* `AccessControlError` for a role absent from its grants map. A role that
|
|
97
|
+
* grants nothing must never be offered or authorised in the first place.
|
|
98
|
+
*
|
|
99
|
+
* Filters with `Object.hasOwn`, not `Boolean(grants[r])`: `getGrants()` returns a plain
|
|
100
|
+
* object, so `grants['constructor']`, `['toString']`, `['valueOf']`, `['hasOwnProperty']`
|
|
101
|
+
* and `['__proto__']` all resolve truthy through the prototype chain even though no role by
|
|
102
|
+
* that name was ever registered. A policy returning `'constructor'` would otherwise survive
|
|
103
|
+
* this filter, get offered by `GET user/tokens/roles`, and be mintable onto a token.
|
|
104
|
+
*/
|
|
105
|
+
async function _allowed_roles(owner, profile) {
|
|
106
|
+
const policy = await (0, configuration_1._service)('rbac.token.rolePolicy', interfaces_js_1.AccessTokenRolePolicy)();
|
|
107
|
+
const allowed = await policy.allowedRoles(owner, profile);
|
|
108
|
+
const ac = di_1.DI.get('AccessControl');
|
|
109
|
+
const grants = ac.getGrants();
|
|
110
|
+
return allowed.filter((r) => Object.hasOwn(grants, r));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Profiles the configured {@link AccessTokenRolePolicy} lets `owner` pin a
|
|
114
|
+
* token to. Same live-resolution rationale as `_allowed_roles`.
|
|
115
|
+
*/
|
|
116
|
+
async function _allowed_profiles(owner) {
|
|
117
|
+
const policy = await (0, configuration_1._service)('rbac.token.rolePolicy', interfaces_js_1.AccessTokenRolePolicy)();
|
|
118
|
+
return policy.allowedProfiles(owner);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Ensures `profile` is one the configured policy lets `owner` pin a token to.
|
|
83
122
|
*/
|
|
84
|
-
function
|
|
85
|
-
const
|
|
123
|
+
async function _assert_profile(owner, profile) {
|
|
124
|
+
const allowed = await _allowed_profiles(owner);
|
|
125
|
+
if (!allowed.includes(profile)) {
|
|
126
|
+
throw new exceptions_1.ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, `Owner may not pin a token to profile: ${profile}`, { roles: [profile] });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Ensures every role in `roles` is one the configured policy allows for
|
|
131
|
+
* `owner`. Deliberately not "one the owner literally holds" - a policy may
|
|
132
|
+
* permit roles beyond the owner's own `Role` list, or withhold ones on it;
|
|
133
|
+
* that flexibility is the entire point of the policy seam.
|
|
134
|
+
*
|
|
135
|
+
* With `profile` given the question is asked relative to that profile, which a
|
|
136
|
+
* policy may answer more narrowly than the owner-wide union.
|
|
137
|
+
*/
|
|
138
|
+
async function _assert_roles_subset(owner, roles, profile) {
|
|
139
|
+
const allowed = await _allowed_roles(owner, profile);
|
|
140
|
+
const missing = roles.filter((r) => !allowed.includes(r));
|
|
86
141
|
if (missing.length !== 0) {
|
|
87
|
-
throw new exceptions_1.ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, `Owner
|
|
142
|
+
throw new exceptions_1.ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, `Owner may not put role(s) on a token: ${missing.join(', ')}`, { roles: missing });
|
|
88
143
|
}
|
|
89
144
|
}
|
|
90
145
|
/**
|
|
91
146
|
* Creates a new access token for a user.
|
|
92
147
|
*
|
|
93
|
-
* Roles must be a non-empty subset of the
|
|
94
|
-
*
|
|
95
|
-
*
|
|
148
|
+
* Roles must be a non-empty subset of the roles the configured
|
|
149
|
+
* {@link AccessTokenRolePolicy} allows the owner to carry ( see
|
|
150
|
+
* `_allowed_roles` above - not necessarily the owner's literal `Role` list ).
|
|
151
|
+
* `expiresAt` null means the token never expires. The plaintext is returned
|
|
152
|
+
* once and never persisted - only its hash is stored.
|
|
96
153
|
*
|
|
97
154
|
* @param user - owner: {@link User} instance, numeric id or uuid
|
|
98
155
|
* @param name - human readable label
|
|
99
|
-
* @param roles - roles carried by the token, subset of the
|
|
156
|
+
* @param roles - roles carried by the token, subset of what the configured
|
|
157
|
+
* {@link AccessTokenRolePolicy} allows the owner
|
|
100
158
|
* @param expiresAt - absolute expiration, or null for a token that never expires
|
|
159
|
+
* @param profile - role the token is pinned to, from what the configured
|
|
160
|
+
* {@link AccessTokenRolePolicy} offers the owner; omitted
|
|
161
|
+
* leaves the token unpinned ( legacy behaviour )
|
|
101
162
|
*/
|
|
102
|
-
async function createToken(user, name, roles, expiresAt) {
|
|
163
|
+
async function createToken(user, name, roles, expiresAt, profile) {
|
|
103
164
|
name = (0, util_1._check_arg)((0, util_1._trim)(), (0, util_1._non_empty)(), (0, util_1._max_length)(128))(name, 'name');
|
|
104
165
|
roles = (0, util_1._check_arg)((0, util_1._non_nil)(), (0, util_1._non_empty)())(roles, 'roles');
|
|
105
166
|
const generator = await (0, configuration_1._service)('rbac.token.generation', interfaces_js_1.AccessTokenGenerationProvider)();
|
|
106
167
|
const generated = await generator.generate();
|
|
107
|
-
return (0, util_1._chain)(_owner(user), (0, util_1._tap)(async (u) =>
|
|
168
|
+
return (0, util_1._chain)(_owner(user), (0, util_1._tap)(async (u) => {
|
|
169
|
+
if (profile) {
|
|
170
|
+
await _assert_profile(u, profile);
|
|
171
|
+
}
|
|
172
|
+
await _assert_roles_subset(u, roles, profile);
|
|
173
|
+
}), async (u) => {
|
|
108
174
|
const token = new AccessToken_js_1.AccessToken({
|
|
109
175
|
Name: name,
|
|
110
176
|
Token: generated.Hash,
|
|
111
177
|
Roles: lodash_1.default.uniq(roles),
|
|
178
|
+
Profile: profile ?? undefined,
|
|
112
179
|
// `ExpiresAt` is optional rather than nullable ( see the model ), so a
|
|
113
180
|
// "never expires" token leaves the property unset instead of holding null.
|
|
114
181
|
ExpiresAt: expiresAt ?? undefined,
|
|
@@ -127,7 +194,8 @@ async function deleteToken(token) {
|
|
|
127
194
|
return (0, util_1._chain)(_token(token), (0, util_1._tap)((t) => t.destroy()), _token_ev(index_js_1.AccessTokenDeleted), () => undefined);
|
|
128
195
|
}
|
|
129
196
|
/**
|
|
130
|
-
* Adds a role to a token. The role must be
|
|
197
|
+
* Adds a role to a token. The role must be allowed for the token owner by the
|
|
198
|
+
* configured {@link AccessTokenRolePolicy}.
|
|
131
199
|
*
|
|
132
200
|
* @param token - {@link AccessToken} instance or its uuid
|
|
133
201
|
* @param role - role name to grant
|
|
@@ -136,7 +204,7 @@ async function grantTokenRole(token, role) {
|
|
|
136
204
|
role = (0, util_1._check_arg)((0, util_1._trim)(), (0, util_1._non_empty)())(role, 'role');
|
|
137
205
|
return (0, util_1._chain)(_token(token), (0, util_1._tap)(async (t) => {
|
|
138
206
|
const owner = await _owner(t.user_id)();
|
|
139
|
-
_assert_roles_subset(owner, [role]);
|
|
207
|
+
await _assert_roles_subset(owner, [role], t.Profile);
|
|
140
208
|
t.Roles = lodash_1.default.uniq([...t.Roles, role]);
|
|
141
209
|
await t.update();
|
|
142
210
|
}), _token_ev(index_js_1.AccessTokenRoleGranted, role));
|
|
@@ -213,10 +281,21 @@ async function validateToken(plaintext) {
|
|
|
213
281
|
if (!owner || !owner.IsActive || owner.DeletedAt || owner.IsBanned) {
|
|
214
282
|
throw new exceptions_1.ErrorCode(E_TOKEN_CODES.E_TOKEN_OWNER_INVALID, 'Access token owner is not allowed to authenticate', { token: token.Uuid });
|
|
215
283
|
}
|
|
216
|
-
//
|
|
217
|
-
//
|
|
284
|
+
// a profile token whose owner no longer passes the profile policy (role
|
|
285
|
+
// revoked, policy tightened) authorises nothing - same immediacy rule as
|
|
286
|
+
// the role re-intersection below
|
|
287
|
+
if (token.Profile) {
|
|
288
|
+
const profiles = await _allowed_profiles(owner);
|
|
289
|
+
if (!profiles.includes(token.Profile)) {
|
|
290
|
+
throw new exceptions_1.ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, 'Access token profile is no longer allowed for its owner', { token: token.Uuid });
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// roles are re-checked against the policy on every request rather than
|
|
294
|
+
// trusted from the row: a role the owner loses - or one an application's
|
|
295
|
+
// policy stops allowing - must take effect immediately, without having to
|
|
218
296
|
// hunt down every token that still carries it
|
|
219
|
-
const
|
|
297
|
+
const allowed = await _allowed_roles(owner, token.Profile);
|
|
298
|
+
const effective = token.Roles.filter((r) => allowed.includes(r));
|
|
220
299
|
if (effective.length === 0) {
|
|
221
300
|
throw new exceptions_1.ErrorCode(E_TOKEN_CODES.E_TOKEN_ROLE_NOT_ALLOWED, 'Access token has no effective roles', { token: token.Uuid });
|
|
222
301
|
}
|
package/lib/cjs/actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,7 +50,7 @@ exports.CreateToken = CreateToken = __decorate([
|
|
|
50
50
|
(0, cli_1.Command)('rbac:token-create', 'Creates an access token for a user'),
|
|
51
51
|
(0, cli_1.Argument)('userIdOrUuid', true, 'numeric id or uuid of the owner'),
|
|
52
52
|
(0, cli_1.Option)('-n, --name <name>', true, 'token label'),
|
|
53
|
-
(0, cli_1.Option)('-r, --roles <roles>', true, 'token roles, comma separated, must be
|
|
53
|
+
(0, cli_1.Option)('-r, --roles <roles>', true, 'token roles, comma separated, must be allowed for the owner by the configured role policy'),
|
|
54
54
|
(0, cli_1.Option)('-e, --expires <expires>', false, 'ISO expiration instant; omit for a token that never expires')
|
|
55
55
|
], CreateToken);
|
|
56
56
|
//# sourceMappingURL=CreateToken.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateToken.js","sourceRoot":"","sources":["../../../src/cli/CreateToken.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAA2C;AAC3C,sCAAqE;AACrE,iCAAiC;AAEjC,8CAA4C;AAarC,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,gBAAU;IAIlC,KAAK,CAAC,OAAO,CAAC,YAAoB,EAAE,OAA4B;QACrE,IAAI,CAAC;YACH,wEAAwE;YACxE,0EAA0E;YAC1E,yEAAyE;YACzE,yCAAyC;YACzC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACvH,IAAI,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;gBACpC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,4BAA4B,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9D,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK;iBACxB,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;YAErF,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,IAAA,wBAAW,EAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;YAEtF,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,kBAAkB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACjD,qEAAqE;YACrE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,mDAAmD,SAAS,EAAE,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,+BAAgC,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;CACF,CAAA;;AA7BW;IADT,IAAA,YAAM,EAAC,iBAAiB,CAAC;8BACX,SAAG;wCAAC;sBAFR,WAAW;IALvB,IAAA,aAAO,EAAC,mBAAmB,EAAE,oCAAoC,CAAC;IAClE,IAAA,cAAQ,EAAC,cAAc,EAAE,IAAI,EAAE,iCAAiC,CAAC;IACjE,IAAA,YAAM,EAAC,mBAAmB,EAAE,IAAI,EAAE,aAAa,CAAC;IAChD,IAAA,YAAM,EAAC,qBAAqB,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"CreateToken.js","sourceRoot":"","sources":["../../../src/cli/CreateToken.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAA2C;AAC3C,sCAAqE;AACrE,iCAAiC;AAEjC,8CAA4C;AAarC,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,gBAAU;IAIlC,KAAK,CAAC,OAAO,CAAC,YAAoB,EAAE,OAA4B;QACrE,IAAI,CAAC;YACH,wEAAwE;YACxE,0EAA0E;YAC1E,yEAAyE;YACzE,yCAAyC;YACzC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACvH,IAAI,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;gBACpC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,4BAA4B,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9D,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK;iBACxB,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;iBACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;YAErF,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,IAAA,wBAAW,EAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;YAEtF,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,kBAAkB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACjD,qEAAqE;YACrE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,mDAAmD,SAAS,EAAE,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,+BAAgC,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;CACF,CAAA;;AA7BW;IADT,IAAA,YAAM,EAAC,iBAAiB,CAAC;8BACX,SAAG;wCAAC;sBAFR,WAAW;IALvB,IAAA,aAAO,EAAC,mBAAmB,EAAE,oCAAoC,CAAC;IAClE,IAAA,cAAQ,EAAC,cAAc,EAAE,IAAI,EAAE,iCAAiC,CAAC;IACjE,IAAA,YAAM,EAAC,mBAAmB,EAAE,IAAI,EAAE,aAAa,CAAC;IAChD,IAAA,YAAM,EAAC,qBAAqB,EAAE,IAAI,EAAE,2FAA2F,CAAC;IAChI,IAAA,YAAM,EAAC,yBAAyB,EAAE,KAAK,EAAE,6DAA6D,CAAC;GAC3F,WAAW,CA+BvB"}
|
|
@@ -32,6 +32,6 @@ __decorate([
|
|
|
32
32
|
exports.GrantTokenRole = GrantTokenRole = __decorate([
|
|
33
33
|
(0, cli_1.Command)('rbac:token-grant', 'Grants a role to an access token'),
|
|
34
34
|
(0, cli_1.Argument)('uuid', true, 'token uuid'),
|
|
35
|
-
(0, cli_1.Argument)('role', true, 'role to grant, must be
|
|
35
|
+
(0, cli_1.Argument)('role', true, 'role to grant, must be allowed for the token owner by the configured role policy')
|
|
36
36
|
], GrantTokenRole);
|
|
37
37
|
//# sourceMappingURL=GrantTokenRole.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GrantTokenRole.js","sourceRoot":"","sources":["../../../src/cli/GrantTokenRole.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAA2C;AAC3C,sCAA6D;AAE7D,8CAA+C;AAKxC,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,gBAAU;IAIrC,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,IAAY;QAC7C,IAAI,CAAC;YACH,MAAM,IAAA,2BAAc,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,qBAAqB,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,6BAA6B,IAAI,aAAa,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;CACF,CAAA;;AAVW;IADT,IAAA,YAAM,EAAC,iBAAiB,CAAC;8BACX,SAAG;2CAAC;yBAFR,cAAc;IAH1B,IAAA,aAAO,EAAC,kBAAkB,EAAE,kCAAkC,CAAC;IAC/D,IAAA,cAAQ,EAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC;IACpC,IAAA,cAAQ,EAAC,MAAM,EAAE,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"GrantTokenRole.js","sourceRoot":"","sources":["../../../src/cli/GrantTokenRole.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sCAA2C;AAC3C,sCAA6D;AAE7D,8CAA+C;AAKxC,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,gBAAU;IAIrC,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,IAAY;QAC7C,IAAI,CAAC;YACH,MAAM,IAAA,2BAAc,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,qBAAqB,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,6BAA6B,IAAI,aAAa,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;CACF,CAAA;;AAVW;IADT,IAAA,YAAM,EAAC,iBAAiB,CAAC;8BACX,SAAG;2CAAC;yBAFR,cAAc;IAH1B,IAAA,aAAO,EAAC,kBAAkB,EAAE,kCAAkC,CAAC;IAC/D,IAAA,cAAQ,EAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC;IACpC,IAAA,cAAQ,EAAC,MAAM,EAAE,IAAI,EAAE,kFAAkF,CAAC;GAC9F,cAAc,CAY1B"}
|
|
@@ -30,6 +30,23 @@ declare const rbacHttpToken: {
|
|
|
30
30
|
generation: {
|
|
31
31
|
service: string;
|
|
32
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Decides which roles an owner may put on a token. Swap for your own
|
|
35
|
+
* implementation of AccessTokenRolePolicy registered under this name.
|
|
36
|
+
*/
|
|
37
|
+
rolePolicy: {
|
|
38
|
+
service: string;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Role name patterns for a custom AccessTokenRolePolicy to consult - not
|
|
42
|
+
* read by anything shipped in this package, including the default
|
|
43
|
+
* `OwnRolesTokenRolePolicy`. An exact name, or a name ending in `.*`
|
|
44
|
+
* matching that prefix and everything under it; matching is implemented
|
|
45
|
+
* by `_role_excluded(role, patterns)` in `src/role-policy.ts`. Empty by
|
|
46
|
+
* default: this package has no opinion about which of an application's
|
|
47
|
+
* roles are meaningful to an API caller.
|
|
48
|
+
*/
|
|
49
|
+
excludedRoles: string[];
|
|
33
50
|
/**
|
|
34
51
|
* Stable plaintext prefix - lets secret scanners recognise leaked tokens.
|
|
35
52
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rbac-http-token.d.ts","sourceRoot":"","sources":["../../../src/config/rbac-http-token.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,aAAa;IACjB,MAAM;QACJ,IAAI;YAIF,GAAG;YACH,WAAW;;;IAqBf,KAAK;QAKH,OAAO;YACL,kBAAkB;gBAAI,UAAU;;YAChC,kBAAkB;gBAAI,UAAU;;YAChC,sBAAsB;gBAAI,UAAU;;YACpC,sBAAsB;gBAAI,UAAU;;;;IAGxC,IAAI;QACF,KAAK;YACH;;;eAGG;YACH,UAAU;gBACR,OAAO;;YAGT;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,UAAU;YAEV;;eAEG;YACH,sBAAsB;;QAExB,MAAM;YACJ,IAAI;gBACF,aAAa;oBAAI,YAAY;oBAAS,UAAU;oBAAS,YAAY;oBAAS,YAAY;;;YAa5F,aAAa;gBACX,aAAa;oBAAI,YAAY;oBAAS,UAAU;oBAAS,YAAY;oBAAS,YAAY;;;;;CAIjG,CAAC;eAEa,aAAa"}
|
|
1
|
+
{"version":3,"file":"rbac-http-token.d.ts","sourceRoot":"","sources":["../../../src/config/rbac-http-token.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,aAAa;IACjB,MAAM;QACJ,IAAI;YAIF,GAAG;YACH,WAAW;;;IAqBf,KAAK;QAKH,OAAO;YACL,kBAAkB;gBAAI,UAAU;;YAChC,kBAAkB;gBAAI,UAAU;;YAChC,sBAAsB;gBAAI,UAAU;;YACpC,sBAAsB;gBAAI,UAAU;;;;IAGxC,IAAI;QACF,KAAK;YACH;;;eAGG;YACH,UAAU;gBACR,OAAO;;YAGT;;;eAGG;YACH,UAAU;gBACR,OAAO;;YAGT;;;;;;;;eAQG;YACH,aAAa,EAAQ,MAAM,EAAE;YAE7B;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,MAAM;YAEN;;eAEG;YACH,UAAU;YAEV;;eAEG;YACH,sBAAsB;;QAExB,MAAM;YACJ,IAAI;gBACF,aAAa;oBAAI,YAAY;oBAAS,UAAU;oBAAS,YAAY;oBAAS,YAAY;;;YAa5F,aAAa;gBACX,aAAa;oBAAI,YAAY;oBAAS,UAAU;oBAAS,YAAY;oBAAS,YAAY;;;;;CAIjG,CAAC;eAEa,aAAa"}
|
|
@@ -57,6 +57,23 @@ const rbacHttpToken = {
|
|
|
57
57
|
generation: {
|
|
58
58
|
service: 'SecureRandomTokenProvider',
|
|
59
59
|
},
|
|
60
|
+
/**
|
|
61
|
+
* Decides which roles an owner may put on a token. Swap for your own
|
|
62
|
+
* implementation of AccessTokenRolePolicy registered under this name.
|
|
63
|
+
*/
|
|
64
|
+
rolePolicy: {
|
|
65
|
+
service: 'OwnRolesTokenRolePolicy',
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Role name patterns for a custom AccessTokenRolePolicy to consult - not
|
|
69
|
+
* read by anything shipped in this package, including the default
|
|
70
|
+
* `OwnRolesTokenRolePolicy`. An exact name, or a name ending in `.*`
|
|
71
|
+
* matching that prefix and everything under it; matching is implemented
|
|
72
|
+
* by `_role_excluded(role, patterns)` in `src/role-policy.ts`. Empty by
|
|
73
|
+
* default: this package has no opinion about which of an application's
|
|
74
|
+
* roles are meaningful to an API caller.
|
|
75
|
+
*/
|
|
76
|
+
excludedRoles: [],
|
|
60
77
|
/**
|
|
61
78
|
* Stable plaintext prefix - lets secret scanners recognise leaked tokens.
|
|
62
79
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rbac-http-token.js","sourceRoot":"","sources":["../../../src/config/rbac-http-token.ts"],"names":[],"mappings":";;AAAA,+BAAgD;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC;IACjD,OAAO;QACL,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QAElK,4CAA4C;QAC5C,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;KAC1K,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAG;IACpB,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,8DAA8D;YAC9D,0EAA0E;YAC1E,iEAAiE;YACjE,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;YACpB,WAAW,EAAE,CAAC,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC;YAEpC,0EAA0E;YAC1E,EAAE;YACF,kEAAkE;YAClE,0EAA0E;YAC1E,wEAAwE;YACxE,sEAAsE;YACtE,uEAAuE;YACvE,wEAAwE;YACxE,yEAAyE;YACzE,yEAAyE;YACzE,wEAAwE;YACxE,0EAA0E;YAC1E,wEAAwE;YACxE,kCAAkC;YAClC,EAAE;YACF,wEAAwE;YACxE,yEAAyE;SAC1E;KACF;IACD,KAAK,EAAE;QACL,qEAAqE;QACrE,qEAAqE;QACrE,yEAAyE;QACzE,iEAAiE;QACjE,OAAO,EAAE;YACP,kBAAkB,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YAC3D,kBAAkB,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YAC3D,sBAAsB,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;YAC/D,sBAAsB,EAAE,EAAE,UAAU,EAAE,uBAAuB,EAAE;SAChE;KACF;IACD,IAAI,EAAE;QACJ,KAAK,EAAE;YACL;;;eAGG;YACH,UAAU,EAAE;gBACV,OAAO,EAAE,2BAA2B;aACrC;YAED;;eAEG;YACH,MAAM,EAAE,MAAM;YAEd;;eAEG;YACH,MAAM,EAAE,EAAE;YAEV;;eAEG;YACH,UAAU,EAAE,WAAW;YAEvB;;eAEG;YACH,sBAAsB,EAAE,EAAE;SAC3B;QACD,MAAM,EAAE;YACN,IAAI,EAAE;gBACJ,aAAa,EAAE,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE;aACpG;YAED,yEAAyE;YACzE,EAAE;YACF,wEAAwE;YACxE,uEAAuE;YACvE,wEAAwE;YACxE,wEAAwE;YACxE,wEAAwE;YACxE,wEAAwE;YACxE,uEAAuE;YACvE,+DAA+D;YAC/D,aAAa,EAAE;gBACb,aAAa,EAAE,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,EAAE;aACpG;SACF;KACF;CACF,CAAC;kBAEa,aAAa"}
|
|
1
|
+
{"version":3,"file":"rbac-http-token.js","sourceRoot":"","sources":["../../../src/config/rbac-http-token.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,34 @@ import { CreateTokenDto } from '../dto/create-token-dto.js';
|
|
|
39
39
|
* @tags AccessTokens
|
|
40
40
|
*/
|
|
41
41
|
export declare class AccessTokenController extends BaseController {
|
|
42
|
+
/**
|
|
43
|
+
* Roles that may be put on a new token
|
|
44
|
+
* Answers from the configured AccessTokenRolePolicy - the same source
|
|
45
|
+
* `POST user/tokens` validates against, so a client can never be offered a
|
|
46
|
+
* role the create call would then refuse.
|
|
47
|
+
*
|
|
48
|
+
* With `profile` given the answer is relative to that profile, which a policy
|
|
49
|
+
* may narrow below the owner-wide union - the picker must ask with the profile
|
|
50
|
+
* the user has selected, or it will keep offering roles the pinned create call
|
|
51
|
+
* then refuses. Without the param the answer is what this route always gave.
|
|
52
|
+
* @security cookieAuth
|
|
53
|
+
* @param profile Optional profile ( root role ) the roles are asked for
|
|
54
|
+
* @response 200 Roles the caller may put on a token
|
|
55
|
+
* @response 401 Unauthorized - valid session required
|
|
56
|
+
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
57
|
+
*/
|
|
58
|
+
roles(user: UserModel, profile?: string): Promise<Ok<unknown>>;
|
|
59
|
+
/**
|
|
60
|
+
* Profiles the caller may pin a new token to
|
|
61
|
+
* Answers from the configured AccessTokenRolePolicy - the same source
|
|
62
|
+
* `POST user/tokens` validates `Profile` against. Empty for applications that
|
|
63
|
+
* did not opt into profile tokens: the shipped default policy offers none.
|
|
64
|
+
* @security cookieAuth
|
|
65
|
+
* @response 200 Profiles the caller may pin a token to
|
|
66
|
+
* @response 401 Unauthorized - valid session required
|
|
67
|
+
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
68
|
+
*/
|
|
69
|
+
profiles(user: UserModel): Promise<Ok<unknown>>;
|
|
42
70
|
/**
|
|
43
71
|
* List own access tokens
|
|
44
72
|
* Hashes are never returned - `Token` is `@Hidden()` on the model, so the
|
|
@@ -52,10 +80,14 @@ export declare class AccessTokenController extends BaseController {
|
|
|
52
80
|
/**
|
|
53
81
|
* Create an access token
|
|
54
82
|
* The plaintext appears in this response only and cannot be retrieved again.
|
|
55
|
-
* Roles must be a subset of the
|
|
83
|
+
* Roles must be a subset of what the configured AccessTokenRolePolicy allows
|
|
84
|
+
* the caller - the same set `GET user/tokens/roles` reports. An optional
|
|
85
|
+
* `Profile` pins the token to one of the profiles `GET user/tokens/profiles`
|
|
86
|
+
* reports, and narrows the role check to that profile; omitted, the token is
|
|
87
|
+
* scoped by the union of its roles as before.
|
|
56
88
|
* @security cookieAuth
|
|
57
89
|
* @response 200 Token created, `Plaintext` returned once
|
|
58
|
-
* @response 400 Requested roles are not
|
|
90
|
+
* @response 400 Requested roles or profile are not allowed for the caller by the configured role policy
|
|
59
91
|
* @response 401 Unauthorized - valid session required
|
|
60
92
|
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
61
93
|
*/
|
|
@@ -72,13 +104,14 @@ export declare class AccessTokenController extends BaseController {
|
|
|
72
104
|
delete(user: UserModel, uuid: string): Promise<Ok | NotFound>;
|
|
73
105
|
/**
|
|
74
106
|
* Grant a role to an own token
|
|
75
|
-
* The role must be
|
|
76
|
-
*
|
|
107
|
+
* The role must be allowed for the caller by the configured
|
|
108
|
+
* AccessTokenRolePolicy - a token can never carry more than the policy
|
|
109
|
+
* permits its owner.
|
|
77
110
|
* @security cookieAuth
|
|
78
111
|
* @param uuid Public identifier of the token
|
|
79
112
|
* @param role Role name to grant
|
|
80
113
|
* @response 200 Updated token
|
|
81
|
-
* @response 400 Role is not
|
|
114
|
+
* @response 400 Role is not allowed for the caller by the configured role policy
|
|
82
115
|
* @response 401 Unauthorized - valid session required
|
|
83
116
|
* @response 403 Forbidden - access tokens cannot be used on this route
|
|
84
117
|
* @response 404 No such token for this user
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessTokenController.d.ts","sourceRoot":"","sources":["../../../src/controllers/AccessTokenController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAA4B,QAAQ,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"AccessTokenController.d.ts","sourceRoot":"","sources":["../../../src/controllers/AccessTokenController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAA4B,QAAQ,EAAE,EAAE,EAAmC,MAAM,eAAe,CAAC;AAC5I,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAI5D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAGa,qBAAsB,SAAQ,cAAc;IACvD;;;;;;;;;;;;;;;OAeG;IAGU,KAAK,CAAS,IAAI,EAAE,SAAS,EAAW,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAE3F;IAED;;;;;;;;;OASG;IAGU,QAAQ,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAEnE;IAED;;;;;;;;OAQG;IAGU,IAAI,CAAS,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAG/D;IAED;;;;;;;;;;;;;OAaG;IAGU,MAAM,CAAS,IAAI,EAAE,SAAS,EAAU,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,CASnH;IAED;;;;;;;;OAQG;IAGU,MAAM,CAAS,IAAI,EAAE,SAAS,EAAW,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,GAAG,QAAQ,CAAC,CAQ1F;IAED;;;;;;;;;;;;;OAaG;IAGU,SAAS,CAAS,IAAI,EAAE,SAAS,EAAW,IAAI,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,QAAQ,GAAG,kBAAkB,CAAC,CAYlJ;IAED;;;;;;;;;;;;OAYG;IAGU,UAAU,CAAS,IAAI,EAAE,SAAS,EAAW,IAAI,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,QAAQ,GAAG,kBAAkB,CAAC,CAYnJ;IAED;;;OAGG;IACH,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAE7E;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE5D;IAED;;;;;;;OAOG;IACH,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAMpD;CACF"}
|