@chidchanun/bcp 0.2.4 → 0.2.6
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 +181 -77
- package/docs/README.md +84 -127
- package/docs/api-manifest.json +6 -3
- package/docs/api-reference.md +60 -4
- package/docs/auth-route-guards.md +104 -61
- package/docs/auth-session-store.md +204 -0
- package/docs/authentication.md +128 -44
- package/docs/authorization-security.md +298 -0
- package/docs/docs-web-manifest.json +8 -4
- package/docs/platform-manifest.json +19 -4
- package/docs/releases/0.2.5.md +152 -0
- package/docs/releases/0.2.6.md +194 -0
- package/docs/security.md +55 -1
- package/package.json +1 -1
- package/packages/client/src/auth.ts +36 -0
- package/packages/client/src/server.ts +16 -0
- package/packages/server/src/auth-guard.ts +204 -95
- package/packages/server/src/auth-session-store.ts +318 -0
- package/packages/server/src/auth.ts +443 -50
- package/packages/server/src/authorization.ts +368 -0
- package/packages/server/src/request-security.ts +596 -0
package/docs/authentication.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Authentication
|
|
2
2
|
|
|
3
|
-
BCP Framework 0.
|
|
4
|
-
It builds on the signed JWT cookie/session primitives from `bcp/server` and provides a higher-level API for application authentication.
|
|
3
|
+
BCP Framework `0.2.5 — Authentication Platform v2` extends the server-only `bcp/auth` entrypoint with optional server-side session state, revocation, idle timeout, logout-all, and guest route guards while preserving the existing signed JWT-cookie mode.
|
|
5
4
|
|
|
6
5
|
## Environment
|
|
7
6
|
|
|
@@ -52,13 +51,9 @@ const session =
|
|
|
52
51
|
if (!session) {
|
|
53
52
|
// Not authenticated.
|
|
54
53
|
}
|
|
55
|
-
|
|
56
|
-
console.log(
|
|
57
|
-
session?.user.id
|
|
58
|
-
);
|
|
59
54
|
```
|
|
60
55
|
|
|
61
|
-
`getSession()`
|
|
56
|
+
`getSession()` remains an alias for `auth()`.
|
|
62
57
|
|
|
63
58
|
## Typed auth factory
|
|
64
59
|
|
|
@@ -113,56 +108,150 @@ await appAuth.login(
|
|
|
113
108
|
);
|
|
114
109
|
```
|
|
115
110
|
|
|
116
|
-
|
|
111
|
+
## Stateless mode remains the default
|
|
112
|
+
|
|
113
|
+
Without a server-side store, authentication remains a signed JWT cookie:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
browser cookie
|
|
117
|
+
↓
|
|
118
|
+
HS256 signature + expiry validation
|
|
119
|
+
↓
|
|
120
|
+
authenticated session
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
This is backward-compatible with earlier BCP versions.
|
|
124
|
+
|
|
125
|
+
A stateless JWT cannot normally be invalidated on another device before expiry. Applications that need revocation can enable the `0.2.5` session-store contract.
|
|
126
|
+
|
|
127
|
+
## Revocable sessions
|
|
117
128
|
|
|
118
129
|
```ts
|
|
119
|
-
|
|
120
|
-
|
|
130
|
+
import {
|
|
131
|
+
createAuth,
|
|
132
|
+
createMemoryAuthSessionStore,
|
|
133
|
+
} from "bcp/auth";
|
|
134
|
+
|
|
135
|
+
const store =
|
|
136
|
+
createMemoryAuthSessionStore();
|
|
137
|
+
|
|
138
|
+
export const appAuth =
|
|
139
|
+
createAuth<AppUser>({
|
|
140
|
+
store,
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
With a store configured, authentication requires both a valid signed cookie and an active server-side `sid` record.
|
|
145
|
+
|
|
146
|
+
The built-in memory store is intended for development and tests. Multi-instance production applications should implement `AuthSessionStore` using a shared database or Redis-like service.
|
|
147
|
+
|
|
148
|
+
See [Auth Session Stores](auth-session-store.md).
|
|
149
|
+
|
|
150
|
+
## Logout
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
await appAuth.logout();
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
In stateless mode this expires the browser cookie.
|
|
157
|
+
|
|
158
|
+
When a store is configured, BCP also revokes the current `sid` before expiring the cookie.
|
|
159
|
+
|
|
160
|
+
## Logout from all sessions
|
|
161
|
+
|
|
162
|
+
With a session store:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const revokedCount =
|
|
166
|
+
await appAuth.logoutAll();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
This revokes every stored session for the current user and expires the current browser cookie.
|
|
170
|
+
|
|
171
|
+
`logoutAll()` intentionally requires a server-side store because stateless JWTs held by other devices cannot be centrally invalidated.
|
|
121
172
|
|
|
122
|
-
|
|
123
|
-
|
|
173
|
+
## Explicit revocation
|
|
174
|
+
|
|
175
|
+
A factory configured with a store can revoke a known session:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
await appAuth.revokeSession(
|
|
179
|
+
sid
|
|
124
180
|
);
|
|
125
|
-
|
|
126
|
-
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Or revoke every stored session for a user:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
await appAuth.revokeUserSessions(
|
|
187
|
+
userId
|
|
127
188
|
);
|
|
128
189
|
```
|
|
129
190
|
|
|
130
|
-
|
|
191
|
+
Low-level forms are also exported:
|
|
131
192
|
|
|
132
193
|
```ts
|
|
133
|
-
|
|
194
|
+
import {
|
|
195
|
+
revokeSession,
|
|
196
|
+
revokeUserSessions,
|
|
197
|
+
} from "bcp/auth";
|
|
134
198
|
```
|
|
135
199
|
|
|
136
|
-
|
|
200
|
+
## Idle timeout
|
|
201
|
+
|
|
202
|
+
Server-side session state can enforce inactivity expiration:
|
|
137
203
|
|
|
138
204
|
```ts
|
|
139
|
-
|
|
205
|
+
const appAuth =
|
|
206
|
+
createAuth<AppUser>({
|
|
207
|
+
store,
|
|
208
|
+
idleTimeout:
|
|
209
|
+
60 * 30,
|
|
210
|
+
});
|
|
140
211
|
```
|
|
141
212
|
|
|
142
|
-
|
|
213
|
+
`idleTimeout` is measured in seconds. Each successful `auth()` check updates `lastSeenAt`.
|
|
214
|
+
|
|
215
|
+
If the session has been inactive for at least the configured duration, BCP revokes it and returns `null`.
|
|
216
|
+
|
|
217
|
+
BCP rejects `idleTimeout` when no store is configured so an application cannot accidentally believe it is enforcing server-side inactivity policy when it is not.
|
|
143
218
|
|
|
144
219
|
## Session rotation
|
|
145
220
|
|
|
146
|
-
Each
|
|
221
|
+
Each login receives a unique `sid`. `rotateSession()` keeps the current user/session data but issues a new session identifier, JWT, expiry window, and cookie.
|
|
147
222
|
|
|
148
223
|
```ts
|
|
149
224
|
const rotated =
|
|
150
225
|
await appAuth.rotateSession();
|
|
226
|
+
```
|
|
151
227
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
228
|
+
When a session store is configured, the previous `sid` is revoked as part of rotation.
|
|
229
|
+
|
|
230
|
+
Good rotation points include successful re-authentication, password changes, permission elevation, or other security-sensitive account changes.
|
|
231
|
+
|
|
232
|
+
## Guest-only pages
|
|
233
|
+
|
|
234
|
+
Authentication Platform v2 adds `requireGuest()` / `createGuestGuard()` for routes such as login and registration pages.
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
import {
|
|
238
|
+
createGuestGuard,
|
|
239
|
+
} from "bcp/auth";
|
|
240
|
+
|
|
241
|
+
export const guard =
|
|
242
|
+
createGuestGuard({
|
|
243
|
+
redirectTo:
|
|
244
|
+
"/dashboard",
|
|
245
|
+
});
|
|
157
246
|
```
|
|
158
247
|
|
|
159
|
-
|
|
248
|
+
Anonymous users continue to the page. Authenticated users are redirected with `303` by default.
|
|
160
249
|
|
|
161
|
-
|
|
250
|
+
See [Auth Route Guards](auth-route-guards.md).
|
|
162
251
|
|
|
163
252
|
## Session shape
|
|
164
253
|
|
|
165
|
-
An authenticated session contains the user, optional application
|
|
254
|
+
An authenticated session contains the user, optional application data, and signed JWT claims:
|
|
166
255
|
|
|
167
256
|
```ts
|
|
168
257
|
{
|
|
@@ -176,26 +265,21 @@ An authenticated session contains the user, optional application session data, a
|
|
|
176
265
|
}
|
|
177
266
|
```
|
|
178
267
|
|
|
268
|
+
Server-side session-store metadata is not embedded as application payload data.
|
|
269
|
+
|
|
179
270
|
## Security notes
|
|
180
271
|
|
|
181
|
-
- `bcp/auth` is server-only and must not be imported into
|
|
182
|
-
-
|
|
183
|
-
- Keep `BCP_SESSION_SECRET`
|
|
184
|
-
-
|
|
185
|
-
-
|
|
272
|
+
- `bcp/auth` is server-only and must not be imported into browser/client graphs.
|
|
273
|
+
- JWT cookie payloads are signed, not encrypted. Do not store passwords, password hashes, API secrets, access keys, or private credentials in the auth payload.
|
|
274
|
+
- Keep `BCP_SESSION_SECRET` outside source control and use a strong random value of at least 32 bytes.
|
|
275
|
+
- Use HTTPS in production so Secure cookies travel only over encrypted connections.
|
|
276
|
+
- The memory session store is process-local; use a shared durable store when revocation must work across multiple processes/containers.
|
|
277
|
+
- Authentication establishes identity/session state. Fine-grained authorization remains a route guard, action, API, or application policy concern.
|
|
186
278
|
|
|
187
279
|
## create-bcp-app
|
|
188
280
|
|
|
189
|
-
When `JWT Cookie` authentication is selected, generated applications use `createAuth()` internally and expose helpers from `lib/auth.ts
|
|
190
|
-
|
|
191
|
-
```ts
|
|
192
|
-
import {
|
|
193
|
-
auth,
|
|
194
|
-
getSession,
|
|
195
|
-
login,
|
|
196
|
-
logout,
|
|
197
|
-
rotateSession,
|
|
198
|
-
} from "@/lib/auth";
|
|
199
|
-
```
|
|
281
|
+
When `JWT Cookie` authentication is selected, generated applications use `createAuth()` internally and expose application helpers from `lib/auth.ts`.
|
|
200
282
|
|
|
201
283
|
The generated `authenticateCredentials()` intentionally returns `null` until the application implements its own user lookup and password verification strategy.
|
|
284
|
+
|
|
285
|
+
Generated projects stay stateless by default. Applications can opt into a session store explicitly without changing the public auth entrypoint.
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Authorization & Security v2
|
|
2
|
+
|
|
3
|
+
BCP Framework `0.2.6` adds permission- and policy-based authorization plus request-origin and CSRF protection primitives while keeping the existing authentication APIs backward compatible.
|
|
4
|
+
|
|
5
|
+
## Permission checks
|
|
6
|
+
|
|
7
|
+
Permission helpers are exported from the server-only `bcp/auth` entrypoint.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
hasPermission,
|
|
12
|
+
assertPermission,
|
|
13
|
+
} from "bcp/auth";
|
|
14
|
+
|
|
15
|
+
const user = {
|
|
16
|
+
id: 42,
|
|
17
|
+
permissions: [
|
|
18
|
+
"users.read",
|
|
19
|
+
"users.write",
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
hasPermission(
|
|
24
|
+
user,
|
|
25
|
+
"users.read"
|
|
26
|
+
); // true
|
|
27
|
+
|
|
28
|
+
hasPermission(
|
|
29
|
+
user,
|
|
30
|
+
[
|
|
31
|
+
"users.read",
|
|
32
|
+
"users.delete",
|
|
33
|
+
],
|
|
34
|
+
{
|
|
35
|
+
match: "all",
|
|
36
|
+
}
|
|
37
|
+
); // false
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The default permission field is `permissions`. Override it when an application uses another user shape:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
hasPermission(
|
|
44
|
+
user,
|
|
45
|
+
"billing.read",
|
|
46
|
+
{
|
|
47
|
+
field: "scopes",
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`assertPermission()` throws `AuthorizationError` with status `403` when the requirement is not satisfied.
|
|
53
|
+
|
|
54
|
+
## Permission route guards
|
|
55
|
+
|
|
56
|
+
Protect a route tree with a permission requirement:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import {
|
|
60
|
+
createPermissionGuard,
|
|
61
|
+
} from "bcp/auth";
|
|
62
|
+
|
|
63
|
+
export const guard =
|
|
64
|
+
createPermissionGuard(
|
|
65
|
+
"users.read"
|
|
66
|
+
);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Require every permission:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
export const guard =
|
|
73
|
+
createPermissionGuard(
|
|
74
|
+
[
|
|
75
|
+
"users.read",
|
|
76
|
+
"users.write",
|
|
77
|
+
],
|
|
78
|
+
{
|
|
79
|
+
match: "all",
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
An unauthenticated request follows the normal `requireAuth()` behavior. An authenticated user without the required permission receives `403 Forbidden` by default.
|
|
85
|
+
|
|
86
|
+
A custom permission field and forbidden redirect are supported:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
export const guard =
|
|
90
|
+
createPermissionGuard(
|
|
91
|
+
"admin.access",
|
|
92
|
+
{
|
|
93
|
+
permissionField:
|
|
94
|
+
"scopes",
|
|
95
|
+
forbiddenRedirectTo:
|
|
96
|
+
"/forbidden",
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The lower-level `requirePermission()` helper is available for custom guard logic.
|
|
102
|
+
|
|
103
|
+
## Authorization policies
|
|
104
|
+
|
|
105
|
+
Policies are useful when authorization depends on a resource, ownership, tenant, state, or other application-specific data instead of a flat permission string.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import {
|
|
109
|
+
defineAuthorizationPolicy,
|
|
110
|
+
authorize,
|
|
111
|
+
can,
|
|
112
|
+
} from "bcp/auth";
|
|
113
|
+
|
|
114
|
+
interface User {
|
|
115
|
+
id: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface Project {
|
|
119
|
+
ownerId: number;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const updateProject =
|
|
123
|
+
defineAuthorizationPolicy<
|
|
124
|
+
User,
|
|
125
|
+
Project
|
|
126
|
+
>(
|
|
127
|
+
({
|
|
128
|
+
user,
|
|
129
|
+
resource,
|
|
130
|
+
}) =>
|
|
131
|
+
resource?.ownerId ===
|
|
132
|
+
user.id
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const allowed =
|
|
136
|
+
await can(
|
|
137
|
+
updateProject,
|
|
138
|
+
{
|
|
139
|
+
user,
|
|
140
|
+
resource: project,
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
await authorize(
|
|
145
|
+
updateProject,
|
|
146
|
+
{
|
|
147
|
+
user,
|
|
148
|
+
resource: project,
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`cannot()` is the inverse of `can()`. `authorize()` throws `AuthorizationError` when the policy returns a falsy result.
|
|
154
|
+
|
|
155
|
+
Policies may be synchronous or asynchronous.
|
|
156
|
+
|
|
157
|
+
## Same-origin mutation protection
|
|
158
|
+
|
|
159
|
+
Request-security helpers are exported from `bcp/server`.
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import {
|
|
163
|
+
requireSameOriginRequest,
|
|
164
|
+
} from "bcp/server";
|
|
165
|
+
|
|
166
|
+
export async function POST() {
|
|
167
|
+
await requireSameOriginRequest();
|
|
168
|
+
|
|
169
|
+
// mutation
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
For unsafe HTTP methods BCP checks `Origin` first and then `Referer`. The application request origin is allowed automatically.
|
|
174
|
+
|
|
175
|
+
Additional trusted origins can be declared explicitly:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
await requireSameOriginRequest({
|
|
179
|
+
allowedOrigins: [
|
|
180
|
+
"https://admin.example.com",
|
|
181
|
+
],
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Missing origin information is rejected for unsafe methods by default. Set `allowMissingOrigin: true` only when a trusted non-browser client cannot send either header and another protection is in place.
|
|
186
|
+
|
|
187
|
+
## CSRF tokens
|
|
188
|
+
|
|
189
|
+
BCP provides an HttpOnly double-submit style CSRF cookie plus a signed token returned to server code.
|
|
190
|
+
|
|
191
|
+
Create a token during page rendering or another trusted same-origin response:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
import {
|
|
195
|
+
createCsrfToken,
|
|
196
|
+
} from "bcp/server";
|
|
197
|
+
|
|
198
|
+
const csrfToken =
|
|
199
|
+
await createCsrfToken();
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Pass the returned token to the page/form and submit it back in an application-controlled field or the default header:
|
|
203
|
+
|
|
204
|
+
```text
|
|
205
|
+
X-BCP-CSRF: <token>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Verify a mutation:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import {
|
|
212
|
+
requireCsrfRequest,
|
|
213
|
+
} from "bcp/server";
|
|
214
|
+
|
|
215
|
+
export async function POST() {
|
|
216
|
+
await requireCsrfRequest();
|
|
217
|
+
|
|
218
|
+
// protected mutation
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
When a form token is parsed from `FormData`, pass it explicitly:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
await requireCsrfRequest({
|
|
226
|
+
token:
|
|
227
|
+
String(
|
|
228
|
+
formData.get("csrf") ??
|
|
229
|
+
""
|
|
230
|
+
),
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`requireCsrfRequest()` combines same-origin validation and CSRF token validation for unsafe methods. Safe read requests do not require a token.
|
|
235
|
+
|
|
236
|
+
## CSRF secret
|
|
237
|
+
|
|
238
|
+
The token signer resolves secrets in this order:
|
|
239
|
+
|
|
240
|
+
```text
|
|
241
|
+
explicit options.secret
|
|
242
|
+
BCP_CSRF_SECRET
|
|
243
|
+
BCP_SESSION_SECRET
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Secrets must contain at least 32 UTF-8 bytes.
|
|
247
|
+
|
|
248
|
+
For deployments that want separate authentication and CSRF key rotation, define:
|
|
249
|
+
|
|
250
|
+
```dotenv
|
|
251
|
+
BCP_SESSION_SECRET=...
|
|
252
|
+
BCP_CSRF_SECRET=...
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
The default CSRF cookie is:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
name bcp_csrf
|
|
259
|
+
HttpOnly true
|
|
260
|
+
SameSite Lax
|
|
261
|
+
Secure true in production
|
|
262
|
+
max age 2 hours
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The cookie is signed but the token itself must still be treated as security-sensitive request state. Do not log CSRF tokens.
|
|
266
|
+
|
|
267
|
+
## Lower-level verification
|
|
268
|
+
|
|
269
|
+
The following helpers are available when applications need custom response behavior:
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
isSafeHttpMethod()
|
|
273
|
+
isSameOriginRequest()
|
|
274
|
+
verifyCsrfToken()
|
|
275
|
+
verifyCsrfRequest()
|
|
276
|
+
destroyCsrfToken()
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
`RequestSecurityError` uses status `403` and distinguishes `INVALID_ORIGIN` from `INVALID_CSRF_TOKEN`.
|
|
280
|
+
|
|
281
|
+
## Security model
|
|
282
|
+
|
|
283
|
+
Authorization and CSRF protection solve different problems:
|
|
284
|
+
|
|
285
|
+
```text
|
|
286
|
+
auth() / session
|
|
287
|
+
-> who is this user?
|
|
288
|
+
|
|
289
|
+
permission / policy
|
|
290
|
+
-> may this user perform this operation?
|
|
291
|
+
|
|
292
|
+
origin + CSRF
|
|
293
|
+
-> did this browser mutation come from an allowed application context?
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Applications should still validate all mutation input and enforce authorization on the server. Client-side UI checks are only presentation logic and must not replace server authorization.
|
|
297
|
+
|
|
298
|
+
`bcp/auth` and the request-security helpers in `bcp/server` are server-only surfaces.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"framework": "bcp",
|
|
4
|
-
"versionTarget": "0.2.
|
|
4
|
+
"versionTarget": "0.2.6",
|
|
5
5
|
"releaseState": "unreleased",
|
|
6
6
|
"sections": [
|
|
7
7
|
{
|
|
@@ -35,11 +35,13 @@
|
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"id": "authentication",
|
|
38
|
-
"title": "Authentication",
|
|
39
|
-
"description": "Authentication
|
|
38
|
+
"title": "Authentication & Authorization",
|
|
39
|
+
"description": "Authentication Platform v2, revocable sessions, permission/policy authorization, route guards and CSRF protection.",
|
|
40
40
|
"pages": [
|
|
41
41
|
{ "route": "/docs/authentication", "source": "authentication.md", "title": "Authentication" },
|
|
42
|
+
{ "route": "/docs/auth-session-store", "source": "auth-session-store.md", "title": "Auth Session Stores" },
|
|
42
43
|
{ "route": "/docs/auth-route-guards", "source": "auth-route-guards.md", "title": "Auth Route Guards" },
|
|
44
|
+
{ "route": "/docs/authorization-security", "source": "authorization-security.md", "title": "Authorization & Security v2" },
|
|
43
45
|
{ "route": "/docs/session-auth", "source": "session-auth.md", "title": "JWT Sessions" }
|
|
44
46
|
]
|
|
45
47
|
},
|
|
@@ -105,7 +107,9 @@
|
|
|
105
107
|
}
|
|
106
108
|
],
|
|
107
109
|
"releases": [
|
|
108
|
-
{ "route": "/releases/0.2.
|
|
110
|
+
{ "route": "/releases/0.2.6", "source": "releases/0.2.6.md", "version": "0.2.6", "state": "unreleased" },
|
|
111
|
+
{ "route": "/releases/0.2.5", "source": "releases/0.2.5.md", "version": "0.2.5" },
|
|
112
|
+
{ "route": "/releases/0.2.4", "source": "releases/0.2.4.md", "version": "0.2.4" },
|
|
109
113
|
{ "route": "/releases/0.2.3", "source": "releases/0.2.3.md", "version": "0.2.3" },
|
|
110
114
|
{ "route": "/releases/0.2.2", "source": "releases/0.2.2.md", "version": "0.2.2" },
|
|
111
115
|
{ "route": "/releases/0.2.1", "source": "releases/0.2.1.md", "version": "0.2.1" },
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"framework": "bcp",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.6",
|
|
5
5
|
"releaseState": "unreleased",
|
|
6
|
-
"baseline": "
|
|
6
|
+
"baseline": "authorization-security-v2",
|
|
7
7
|
"runtime": {
|
|
8
8
|
"node": ">=24.11.0",
|
|
9
9
|
"react": "19",
|
|
@@ -47,6 +47,18 @@
|
|
|
47
47
|
"formActions": true,
|
|
48
48
|
"middlewareV2": true,
|
|
49
49
|
"jwtCookieSessions": true,
|
|
50
|
+
"authenticationPlatformV2": true,
|
|
51
|
+
"authSessionStore": true,
|
|
52
|
+
"authSessionRevocation": true,
|
|
53
|
+
"authLogoutAll": true,
|
|
54
|
+
"authIdleTimeout": true,
|
|
55
|
+
"authGuestGuard": true,
|
|
56
|
+
"authorizationSecurityV2": true,
|
|
57
|
+
"permissionAuthorization": true,
|
|
58
|
+
"authorizationPolicies": true,
|
|
59
|
+
"permissionRouteGuards": true,
|
|
60
|
+
"sameOriginProtection": true,
|
|
61
|
+
"csrfProtection": true,
|
|
50
62
|
"databaseMigrations": true,
|
|
51
63
|
"databaseAdapterContract": true,
|
|
52
64
|
"databasePostgresql": true,
|
|
@@ -86,7 +98,7 @@
|
|
|
86
98
|
"s3-compatible"
|
|
87
99
|
],
|
|
88
100
|
"compatibility": {
|
|
89
|
-
"previousBaseline": "0.2.
|
|
101
|
+
"previousBaseline": "0.2.5",
|
|
90
102
|
"intentionalBreakingChangesFromPreviousBaseline": false,
|
|
91
103
|
"migrationGuide": "migration-0.2.md"
|
|
92
104
|
},
|
|
@@ -99,7 +111,10 @@
|
|
|
99
111
|
"apiReference": "api-reference.md",
|
|
100
112
|
"environmentValidation": "environment-validation.md",
|
|
101
113
|
"applicationPackaging": "application-packaging.md",
|
|
114
|
+
"authentication": "authentication.md",
|
|
115
|
+
"authSessionStore": "auth-session-store.md",
|
|
116
|
+
"authorizationSecurity": "authorization-security.md",
|
|
102
117
|
"migrationGuide": "migration-0.2.md",
|
|
103
|
-
"releaseNotes": "releases/0.2.
|
|
118
|
+
"releaseNotes": "releases/0.2.6.md"
|
|
104
119
|
}
|
|
105
120
|
}
|