@jskit-ai/auth-web 0.1.159 → 0.1.161
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/package.json +29 -135
- package/patterns/auth-surface/PATTERN.md +84 -0
- package/patterns/auth-surface/example/.vibe64/bin/preview-identity +5 -0
- package/src/client/index.js +1 -4
- package/src/client/providers/AuthWebClientProvider.js +32 -60
- package/src/client/runtime/authClient.js +79 -0
- package/src/client/runtime/authGuardRuntime.js +28 -7
- package/src/server/AuthWebFeature.js +41 -0
- package/src/server/managedPreviewIdentity.js +344 -0
- package/src/server/services/AuthWebService.js +4 -16
- package/test/clientBoot.test.js +3 -3
- package/test/clientSurface.test.js +6 -16
- package/test/managedPreviewIdentity.test.js +89 -0
- package/test/packageMetadataOwnership.test.js +3 -15
- package/test/provider.test.js +30 -220
- package/test/providerRuntime.test.js +92 -307
- package/src/client/providers/bootAuthClientProvider.js +0 -49
- package/src/server/providers/AuthRouteServiceProvider.js +0 -31
- package/src/server/providers/AuthWebServiceProvider.js +0 -38
- /package/{templates → patterns/auth-surface/example}/src/pages/auth/login.vue +0 -0
- /package/{templates → patterns/auth-surface/example}/src/pages/auth/reset-password.vue +0 -0
- /package/{templates → patterns/auth-surface/example}/src/pages/auth/signout.vue +0 -0
- /package/{templates → patterns/auth-surface/example}/src/runtime/authGuardRuntime.js +0 -0
- /package/{templates → patterns/auth-surface/example}/src/runtime/authHttpClient.js +0 -0
- /package/{templates → patterns/auth-surface/example}/src/runtime/useSignOut.js +0 -0
- /package/{templates → patterns/auth-surface/example}/src/views/auth/LoginView.vue +0 -0
- /package/{templates → patterns/auth-surface/example}/src/views/auth/ResetPasswordView.vue +0 -0
- /package/{templates → patterns/auth-surface/example}/src/views/auth/SignOutView.vue +0 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { createActionProvider } from "@jskit-ai/kernel/server/actions";
|
|
4
|
+
import { createCapabilityRuntime } from "@jskit-ai/kernel/shared/capabilities";
|
|
5
|
+
import { AuthFeature } from "@jskit-ai/auth-core/server/providers/AuthFeature";
|
|
6
|
+
import { HttpProvider } from "@jskit-ai/kernel/server/http";
|
|
7
|
+
import { AuthWebFeature } from "../src/server/AuthWebFeature.js";
|
|
6
8
|
|
|
7
9
|
function createFastifyStub() {
|
|
8
|
-
const routes = [];
|
|
9
|
-
const hooks = [];
|
|
10
10
|
return {
|
|
11
|
-
hooks,
|
|
12
|
-
routes,
|
|
11
|
+
hooks: [],
|
|
12
|
+
routes: [],
|
|
13
13
|
errorHandler: null,
|
|
14
14
|
addHook(name, handler) {
|
|
15
|
-
hooks.push({ name, handler });
|
|
15
|
+
this.hooks.push({ name, handler });
|
|
16
16
|
},
|
|
17
17
|
route(definition) {
|
|
18
|
-
routes.push(definition);
|
|
18
|
+
this.routes.push(definition);
|
|
19
19
|
},
|
|
20
20
|
setErrorHandler(handler) {
|
|
21
21
|
this.errorHandler = handler;
|
|
@@ -43,329 +43,114 @@ function createReplyStub() {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
function createAuthService(events = []) {
|
|
47
|
+
return {
|
|
48
|
+
async register(input) {
|
|
49
|
+
return {
|
|
50
|
+
actor: { displayName: input.displayName, email: input.email },
|
|
51
|
+
session: { access_token: "register-a", refresh_token: "register-r" },
|
|
52
|
+
requiresEmailConfirmation: false
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
async resendRegisterConfirmation() {
|
|
56
|
+
return { ok: true, message: "Confirmation sent." };
|
|
57
|
+
},
|
|
58
|
+
async login() {
|
|
59
|
+
return {
|
|
60
|
+
session: { access_token: "a", refresh_token: "r" },
|
|
61
|
+
actor: { displayName: "Ada", email: "ada@example.com" }
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
async devLoginAs(_request, input) {
|
|
65
|
+
return {
|
|
66
|
+
session: { access_token: "dev-a", refresh_token: "dev-r" },
|
|
67
|
+
actor: { id: input.userId || "7", displayName: "Dev Ada", email: "ada@example.com" }
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
async logout() {
|
|
71
|
+
return { ok: true, clearSession: true };
|
|
72
|
+
},
|
|
73
|
+
async authenticateRequest() {
|
|
74
|
+
return { authenticated: false };
|
|
75
|
+
},
|
|
76
|
+
getCapabilities() {
|
|
77
|
+
return {
|
|
78
|
+
provider: { id: "local", label: "Local" },
|
|
79
|
+
features: {
|
|
80
|
+
password: { login: true, register: true, change: true, methodToggle: false },
|
|
81
|
+
passwordRecovery: { request: true, complete: true, delivery: "dev-log" },
|
|
82
|
+
otp: { login: false },
|
|
83
|
+
oauthLogin: { enabled: false, providers: [], defaultProvider: null },
|
|
84
|
+
emailConfirmation: false,
|
|
85
|
+
profileUpdate: true,
|
|
86
|
+
providerLinking: { start: false, unlink: false },
|
|
87
|
+
securityStatus: true,
|
|
88
|
+
signOutOtherSessions: true,
|
|
89
|
+
appProfileProjection: false,
|
|
90
|
+
devLoginAs: false
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
},
|
|
57
94
|
writeSessionCookies(_reply, session) {
|
|
58
95
|
events.push({ type: "writeSession", session });
|
|
59
96
|
},
|
|
60
97
|
clearSessionCookies() {
|
|
61
98
|
events.push({ type: "clearSession" });
|
|
62
|
-
},
|
|
63
|
-
getOAuthProviderCatalog() {
|
|
64
|
-
return { providers: [], defaultProvider: "" };
|
|
65
99
|
}
|
|
66
100
|
};
|
|
101
|
+
}
|
|
67
102
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (actionId === "auth.login.password") {
|
|
78
|
-
return {
|
|
79
|
-
session: { access_token: "a", refresh_token: "r" },
|
|
80
|
-
actor: { displayName: "Ada" }
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
if (actionId === "auth.dev.loginAs") {
|
|
84
|
-
return {
|
|
85
|
-
session: { access_token: "dev-a", refresh_token: "dev-r" },
|
|
86
|
-
actor: { id: "7", displayName: "Dev Ada", email: "ada@example.com" }
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
if (actionId === "auth.logout") {
|
|
90
|
-
return {
|
|
91
|
-
ok: true,
|
|
92
|
-
clearSession: true
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
return {};
|
|
96
|
-
}
|
|
103
|
+
async function startAuthWeb({ env = {}, authService = null } = {}) {
|
|
104
|
+
const fastify = createFastifyStub();
|
|
105
|
+
const runtime = createCapabilityRuntime({
|
|
106
|
+
inputs: {
|
|
107
|
+
"auth.service": authService || createAuthService(),
|
|
108
|
+
"runtime.env": { NODE_ENV: "test", ...env },
|
|
109
|
+
"runtime.fastify": fastify
|
|
110
|
+
},
|
|
111
|
+
providers: [createActionProvider(), HttpProvider, AuthFeature, AuthWebFeature]
|
|
97
112
|
});
|
|
113
|
+
await runtime.start();
|
|
114
|
+
return { fastify, runtime };
|
|
115
|
+
}
|
|
98
116
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
await app.start({ providers: [MockActionRuntimeProvider, MockAuthProvider, AuthWebServiceProvider, AuthRouteServiceProvider] });
|
|
104
|
-
|
|
105
|
-
const registration = httpRuntime.registerRoutes();
|
|
106
|
-
assert.equal(registration.routeCount > 0, true);
|
|
107
|
-
|
|
117
|
+
test("AuthWebFeature registers direct action-backed login and logout routes", async () => {
|
|
118
|
+
const events = [];
|
|
119
|
+
const { fastify } = await startAuthWeb({ authService: createAuthService(events) });
|
|
108
120
|
const loginRoute = fastify.routes.find((route) => route.method === "POST" && route.url === "/api/login");
|
|
109
|
-
assert.ok(loginRoute);
|
|
110
121
|
const loginReply = createReplyStub();
|
|
111
|
-
await loginRoute.handler({ body: { email: "ada@example.com", password: "
|
|
122
|
+
await loginRoute.handler({ body: { email: "ada@example.com", password: "password value" } }, loginReply);
|
|
112
123
|
assert.equal(loginReply.statusCode, 200);
|
|
113
124
|
assert.equal(loginReply.payload.username, "Ada");
|
|
114
125
|
|
|
115
|
-
const resendConfirmationRoute = fastify.routes.find(
|
|
116
|
-
(route) => route.method === "POST" && route.url === "/api/register/confirmation/resend"
|
|
117
|
-
);
|
|
118
|
-
assert.ok(resendConfirmationRoute);
|
|
119
|
-
const resendConfirmationReply = createReplyStub();
|
|
120
|
-
await resendConfirmationRoute.handler({ body: { email: "ada@example.com" } }, resendConfirmationReply);
|
|
121
|
-
assert.equal(resendConfirmationReply.statusCode, 200);
|
|
122
|
-
assert.equal(resendConfirmationReply.payload.ok, true);
|
|
123
|
-
|
|
124
|
-
const devLoginRoute = fastify.routes.find((route) => route.method === "POST" && route.url === "/api/dev-auth/login-as");
|
|
125
|
-
assert.equal(devLoginRoute, undefined);
|
|
126
|
-
|
|
127
126
|
const logoutRoute = fastify.routes.find((route) => route.method === "POST" && route.url === "/api/logout");
|
|
128
|
-
assert.ok(logoutRoute);
|
|
129
127
|
const logoutReply = createReplyStub();
|
|
130
128
|
await logoutRoute.handler({}, logoutReply);
|
|
131
|
-
assert.
|
|
132
|
-
assert.equal(logoutReply.payload.ok, true);
|
|
133
|
-
|
|
129
|
+
assert.deepEqual(logoutReply.payload, { ok: true });
|
|
134
130
|
assert.equal(events.some((entry) => entry.type === "writeSession"), true);
|
|
135
131
|
assert.equal(events.some((entry) => entry.type === "clearSession"), true);
|
|
136
132
|
});
|
|
137
133
|
|
|
138
|
-
test("
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
getOAuthProviderCatalog() {
|
|
147
|
-
return { providers: [], defaultProvider: "" };
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
app.instance("jskit.env", {
|
|
152
|
-
NODE_ENV: "development",
|
|
153
|
-
AUTH_DEV_BYPASS_ENABLED: "true"
|
|
154
|
-
});
|
|
155
|
-
app.instance("authService", authService);
|
|
156
|
-
app.instance("actionExecutor", {
|
|
157
|
-
async execute({ actionId }) {
|
|
158
|
-
if (actionId === "auth.dev.loginAs") {
|
|
159
|
-
return {
|
|
160
|
-
session: { access_token: "dev-a", refresh_token: "dev-r" },
|
|
161
|
-
actor: { id: "7", displayName: "Dev Ada", email: "ada@example.com" }
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
return {};
|
|
134
|
+
test("AuthWebFeature exposes dev login only when the explicit dev policy enables it", async () => {
|
|
135
|
+
const disabled = await startAuthWeb();
|
|
136
|
+
assert.equal(disabled.fastify.routes.some((route) => route.url === "/api/dev-auth/login-as"), false);
|
|
137
|
+
const enabled = await startAuthWeb({
|
|
138
|
+
env: {
|
|
139
|
+
NODE_ENV: "development",
|
|
140
|
+
AUTH_DEV_BYPASS_ENABLED: "true",
|
|
141
|
+
AUTH_DEV_BYPASS_SECRET: "test-secret"
|
|
165
142
|
}
|
|
166
143
|
});
|
|
167
|
-
|
|
168
|
-
class MockAuthProvider {
|
|
169
|
-
static id = "auth.provider";
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
await app.start({ providers: [MockActionRuntimeProvider, MockAuthProvider, AuthWebServiceProvider, AuthRouteServiceProvider] });
|
|
173
|
-
|
|
174
|
-
const registration = httpRuntime.registerRoutes();
|
|
175
|
-
assert.equal(registration.routeCount > 0, true);
|
|
176
|
-
|
|
177
|
-
const devLoginRoute = fastify.routes.find((route) => route.method === "POST" && route.url === "/api/dev-auth/login-as");
|
|
178
|
-
assert.ok(devLoginRoute);
|
|
179
|
-
const devLoginReply = createReplyStub();
|
|
180
|
-
await devLoginRoute.handler({ body: { userId: "7" } }, devLoginReply);
|
|
181
|
-
assert.equal(devLoginReply.statusCode, 200);
|
|
182
|
-
assert.equal(devLoginReply.payload.userId, "7");
|
|
183
|
-
assert.equal(devLoginReply.payload.username, "Dev Ada");
|
|
144
|
+
assert.equal(enabled.fastify.routes.some((route) => route.url === "/api/dev-auth/login-as"), true);
|
|
184
145
|
});
|
|
185
146
|
|
|
186
|
-
test("auth route provider
|
|
187
|
-
const fastify =
|
|
188
|
-
const app = createApplication();
|
|
189
|
-
const httpRuntime = createHttpRuntime({ app, fastify });
|
|
190
|
-
let authServiceResolutions = 0;
|
|
191
|
-
|
|
192
|
-
app.singleton("authService", () => {
|
|
193
|
-
authServiceResolutions += 1;
|
|
194
|
-
return {
|
|
195
|
-
writeSessionCookies() {},
|
|
196
|
-
clearSessionCookies() {},
|
|
197
|
-
getOAuthProviderCatalog() {
|
|
198
|
-
return { providers: [], defaultProvider: "" };
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
app.instance("actionExecutor", {
|
|
204
|
-
async execute({ actionId }) {
|
|
205
|
-
if (actionId === "auth.login.password") {
|
|
206
|
-
return {
|
|
207
|
-
session: { access_token: "a", refresh_token: "r" },
|
|
208
|
-
actor: { displayName: "Ada" }
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
return {};
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
class MockAuthProvider {
|
|
216
|
-
static id = "auth.provider";
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
await app.start({ providers: [MockActionRuntimeProvider, MockAuthProvider, AuthWebServiceProvider, AuthRouteServiceProvider] });
|
|
220
|
-
assert.equal(authServiceResolutions, 0);
|
|
221
|
-
|
|
222
|
-
const registration = httpRuntime.registerRoutes();
|
|
223
|
-
assert.equal(registration.routeCount > 0, true);
|
|
224
|
-
assert.equal(authServiceResolutions, 0);
|
|
225
|
-
|
|
226
|
-
const loginRoute = fastify.routes.find((route) => route.method === "POST" && route.url === "/api/login");
|
|
227
|
-
assert.ok(loginRoute);
|
|
228
|
-
const loginReply = createReplyStub();
|
|
229
|
-
await loginRoute.handler({ body: { email: "ada@example.com", password: "pass" } }, loginReply);
|
|
230
|
-
assert.equal(loginReply.statusCode, 200);
|
|
231
|
-
assert.equal(authServiceResolutions, 1);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
test("auth session route preserves provider capabilities through response validation", async () => {
|
|
235
|
-
const fastify = createFastifyStub();
|
|
236
|
-
const app = createApplication();
|
|
237
|
-
const httpRuntime = createHttpRuntime({ app, fastify });
|
|
238
|
-
|
|
239
|
-
app.instance("authService", {
|
|
240
|
-
writeSessionCookies() {},
|
|
241
|
-
clearSessionCookies() {},
|
|
242
|
-
getCapabilities() {
|
|
243
|
-
return {
|
|
244
|
-
provider: {
|
|
245
|
-
id: "local",
|
|
246
|
-
label: "Local"
|
|
247
|
-
},
|
|
248
|
-
features: {
|
|
249
|
-
password: {
|
|
250
|
-
login: true,
|
|
251
|
-
register: true,
|
|
252
|
-
change: true,
|
|
253
|
-
methodToggle: false
|
|
254
|
-
},
|
|
255
|
-
passwordRecovery: {
|
|
256
|
-
request: true,
|
|
257
|
-
complete: true,
|
|
258
|
-
delivery: "dev-log"
|
|
259
|
-
},
|
|
260
|
-
otp: {
|
|
261
|
-
login: false
|
|
262
|
-
},
|
|
263
|
-
oauthLogin: {
|
|
264
|
-
enabled: false,
|
|
265
|
-
providers: [],
|
|
266
|
-
defaultProvider: null
|
|
267
|
-
},
|
|
268
|
-
emailConfirmation: false,
|
|
269
|
-
profileUpdate: true,
|
|
270
|
-
providerLinking: {
|
|
271
|
-
start: false,
|
|
272
|
-
unlink: false
|
|
273
|
-
},
|
|
274
|
-
securityStatus: true,
|
|
275
|
-
signOutOtherSessions: true,
|
|
276
|
-
appProfileProjection: false,
|
|
277
|
-
devLoginAs: false
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
app.instance("actionExecutor", {
|
|
283
|
-
async execute({ actionId }) {
|
|
284
|
-
if (actionId === "auth.session.read") {
|
|
285
|
-
return {
|
|
286
|
-
authenticated: false
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
return {};
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
class MockAuthProvider {
|
|
294
|
-
static id = "auth.provider";
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
await app.start({ providers: [MockActionRuntimeProvider, MockAuthProvider, AuthWebServiceProvider, AuthRouteServiceProvider] });
|
|
298
|
-
|
|
299
|
-
const registration = httpRuntime.registerRoutes();
|
|
300
|
-
assert.equal(registration.routeCount > 0, true);
|
|
301
|
-
|
|
147
|
+
test("auth session route returns provider capabilities", async () => {
|
|
148
|
+
const { fastify } = await startAuthWeb();
|
|
302
149
|
const sessionRoute = fastify.routes.find((route) => route.method === "GET" && route.url === "/api/session");
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
assert.equal(
|
|
308
|
-
assert.equal(
|
|
309
|
-
assert.equal(sessionReply.payload.authCapabilities.provider.id, "local");
|
|
310
|
-
assert.equal(sessionReply.payload.authCapabilities.features.password.login, true);
|
|
311
|
-
assert.equal(sessionReply.payload.authCapabilities.features.password.register, true);
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
test("auth session route exposes denial reason when policy clears a rejected authenticated session", async () => {
|
|
315
|
-
const events = [];
|
|
316
|
-
const fastify = createFastifyStub();
|
|
317
|
-
const app = createApplication();
|
|
318
|
-
const httpRuntime = createHttpRuntime({ app, fastify });
|
|
319
|
-
|
|
320
|
-
const authService = {
|
|
321
|
-
writeSessionCookies() {
|
|
322
|
-
events.push({ type: "writeSession" });
|
|
323
|
-
},
|
|
324
|
-
clearSessionCookies() {
|
|
325
|
-
events.push({ type: "clearSession" });
|
|
326
|
-
},
|
|
327
|
-
getOAuthProviderCatalog() {
|
|
328
|
-
return { providers: [], defaultProvider: "" };
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
app.instance("authService", authService);
|
|
333
|
-
app.instance("actionExecutor", {
|
|
334
|
-
async execute({ actionId }) {
|
|
335
|
-
if (actionId === "auth.session.read") {
|
|
336
|
-
return {
|
|
337
|
-
authenticated: false,
|
|
338
|
-
clearSession: true,
|
|
339
|
-
transientFailure: false,
|
|
340
|
-
authDenied: {
|
|
341
|
-
code: "not_allowlisted",
|
|
342
|
-
message: "This account is not allowed to access this application."
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
return {};
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
class MockAuthProvider {
|
|
351
|
-
static id = "auth.provider";
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
await app.start({ providers: [MockActionRuntimeProvider, MockAuthProvider, AuthWebServiceProvider, AuthRouteServiceProvider] });
|
|
355
|
-
|
|
356
|
-
const registration = httpRuntime.registerRoutes();
|
|
357
|
-
assert.equal(registration.routeCount > 0, true);
|
|
358
|
-
|
|
359
|
-
const sessionRoute = fastify.routes.find((route) => route.method === "GET" && route.url === "/api/session");
|
|
360
|
-
assert.ok(sessionRoute);
|
|
361
|
-
const sessionReply = createReplyStub();
|
|
362
|
-
await sessionRoute.handler({}, sessionReply);
|
|
363
|
-
|
|
364
|
-
assert.equal(sessionReply.statusCode, 200);
|
|
365
|
-
assert.equal(sessionReply.payload.authenticated, false);
|
|
366
|
-
assert.deepEqual(sessionReply.payload.authDenied, {
|
|
367
|
-
code: "not_allowlisted",
|
|
368
|
-
message: "This account is not allowed to access this application."
|
|
369
|
-
});
|
|
370
|
-
assert.deepEqual(events, [{ type: "clearSession" }]);
|
|
150
|
+
const reply = createReplyStub();
|
|
151
|
+
await sessionRoute.handler({}, reply);
|
|
152
|
+
assert.equal(reply.statusCode, 200);
|
|
153
|
+
assert.equal(reply.payload.authenticated, false);
|
|
154
|
+
assert.equal(reply.payload.authCapabilities.provider.id, "local");
|
|
155
|
+
assert.equal(reply.payload.authCapabilities.features.password.register, true);
|
|
371
156
|
});
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AUTH_GUARD_RUNTIME_INJECTION_KEY,
|
|
3
|
-
AUTH_OAUTH_LAUNCH_CLIENT_INJECTION_KEY
|
|
4
|
-
} from "../runtime/inject.js";
|
|
5
|
-
import { createBrowserOAuthLaunchClient } from "../runtime/oauthLaunchClient.js";
|
|
6
|
-
import { useAuthStore } from "../stores/useAuthStore.js";
|
|
7
|
-
|
|
8
|
-
const AUTH_OAUTH_LAUNCH_CLIENT_TOKEN = "auth.oauth-launch.client";
|
|
9
|
-
|
|
10
|
-
async function bootAuthClientProvider(app) {
|
|
11
|
-
if (!app || typeof app.make !== "function" || typeof app.has !== "function") {
|
|
12
|
-
throw new Error("AuthWebClientProvider requires application make()/has().");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const authGuardRuntime = app.make("runtime.auth-guard.client");
|
|
16
|
-
const pinia = app.make("jskit.client.pinia");
|
|
17
|
-
if (!pinia) {
|
|
18
|
-
throw new Error("AuthWebClientProvider requires Pinia installed in the client app.");
|
|
19
|
-
}
|
|
20
|
-
const authStore = useAuthStore(pinia);
|
|
21
|
-
authStore.attachRuntime(authGuardRuntime);
|
|
22
|
-
await authStore.initialize();
|
|
23
|
-
|
|
24
|
-
if (app.has("runtime.web-bootstrap.client")) {
|
|
25
|
-
const bootstrapRuntime = app.make("runtime.web-bootstrap.client");
|
|
26
|
-
if (bootstrapRuntime && typeof bootstrapRuntime.refresh === "function") {
|
|
27
|
-
authStore.subscribe(() => {
|
|
28
|
-
void bootstrapRuntime.refresh("auth.state");
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!app.has("jskit.client.vue.app")) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const vueApp = app.make("jskit.client.vue.app");
|
|
38
|
-
if (!vueApp || typeof vueApp.provide !== "function") {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const oauthLaunchClient = app.has(AUTH_OAUTH_LAUNCH_CLIENT_TOKEN)
|
|
43
|
-
? app.make(AUTH_OAUTH_LAUNCH_CLIENT_TOKEN)
|
|
44
|
-
: createBrowserOAuthLaunchClient();
|
|
45
|
-
vueApp.provide(AUTH_GUARD_RUNTIME_INJECTION_KEY, authGuardRuntime);
|
|
46
|
-
vueApp.provide(AUTH_OAUTH_LAUNCH_CLIENT_INJECTION_KEY, oauthLaunchClient);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export { bootAuthClientProvider };
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { AuthController } from "../controllers/AuthController.js";
|
|
2
|
-
import { buildRoutes } from "../routes/authRoutes.js";
|
|
3
|
-
|
|
4
|
-
class AuthRouteServiceProvider {
|
|
5
|
-
static id = "auth.routes";
|
|
6
|
-
|
|
7
|
-
register(app) {
|
|
8
|
-
if (!app || typeof app.has !== "function") {
|
|
9
|
-
throw new Error("AuthRouteServiceProvider requires application has().");
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
boot(app) {
|
|
14
|
-
if (!app || typeof app.make !== "function") {
|
|
15
|
-
throw new Error("AuthRouteServiceProvider requires application make().");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const router = app.make("jskit.http.router");
|
|
19
|
-
const authWebService = app.make("auth.web.service");
|
|
20
|
-
const controller = new AuthController({ service: authWebService });
|
|
21
|
-
const routes = buildRoutes(controller, {
|
|
22
|
-
includeDevLoginAs:
|
|
23
|
-
typeof authWebService?.isDevLoginAsAvailable === "function" ? authWebService.isDevLoginAsAvailable() : false
|
|
24
|
-
});
|
|
25
|
-
for (const route of routes) {
|
|
26
|
-
router.register(route.method, route.path, route, route.handler);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export { AuthRouteServiceProvider };
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { resolveDevAuthPolicyFromEnv } from "@jskit-ai/auth-core/server/devAuth";
|
|
2
|
-
import { AuthWebService } from "../services/AuthWebService.js";
|
|
3
|
-
|
|
4
|
-
function resolveDevAuthBootstrapEnabled(scope) {
|
|
5
|
-
const env =
|
|
6
|
-
scope && typeof scope.has === "function" && scope.has("jskit.env")
|
|
7
|
-
? scope.make("jskit.env")
|
|
8
|
-
: {};
|
|
9
|
-
|
|
10
|
-
const policy = resolveDevAuthPolicyFromEnv(env);
|
|
11
|
-
return policy.enabled && !policy.isProduction;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
class AuthWebServiceProvider {
|
|
15
|
-
static id = "auth.web";
|
|
16
|
-
|
|
17
|
-
static startsAfter = ["runtime.actions"];
|
|
18
|
-
|
|
19
|
-
register(app) {
|
|
20
|
-
if (!app || typeof app.singleton !== "function" || typeof app.has !== "function") {
|
|
21
|
-
throw new Error("AuthWebServiceProvider requires application singleton()/has().");
|
|
22
|
-
}
|
|
23
|
-
if (!app.has("actionExecutor")) {
|
|
24
|
-
throw new Error("AuthWebServiceProvider requires actionExecutor binding.");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
app.singleton("auth.web.service", (scope) => {
|
|
28
|
-
return new AuthWebService({
|
|
29
|
-
getAuthService() {
|
|
30
|
-
return scope.make("authService");
|
|
31
|
-
},
|
|
32
|
-
devAuthBootstrapEnabled: resolveDevAuthBootstrapEnabled(scope)
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export { AuthWebServiceProvider };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|