@o3co/create-auth-provider 0.17.0 → 0.18.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -198
- package/main.js +4 -0
- package/package.json +8 -30
- package/README.ja.md +0 -200
- package/dist/cli.d.mts +0 -3
- package/dist/cli.d.mts.map +0 -1
- package/dist/cli.mjs +0 -18
- package/dist/index.d.mts +0 -48
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs +0 -325
- package/dist/internal/template-filter.d.mts +0 -14
- package/dist/internal/template-filter.d.mts.map +0 -1
- package/dist/internal/template-filter.mjs +0 -42
- package/templates/standalone/.dockerignore +0 -23
- package/templates/standalone/.env.example +0 -152
- package/templates/standalone/Dockerfile +0 -125
- package/templates/standalone/Makefile +0 -12
- package/templates/standalone/README.ja.md +0 -912
- package/templates/standalone/README.md +0 -1536
- package/templates/standalone/config/application.conf +0 -351
- package/templates/standalone/config/clients.yaml +0 -4
- package/templates/standalone/config/clients.yaml.example +0 -124
- package/templates/standalone/config/development.conf +0 -17
- package/templates/standalone/config/mailpit.conf +0 -13
- package/templates/standalone/config/production.conf +0 -15
- package/templates/standalone/config/reference.conf +0 -427
- package/templates/standalone/docker-compose.mailpit.yml +0 -39
- package/templates/standalone/docker-compose.production.yml +0 -229
- package/templates/standalone/docker-compose.test.yml +0 -16
- package/templates/standalone/docker-compose.yml +0 -67
- package/templates/standalone/gitignore +0 -23
- package/templates/standalone/package.json +0 -56
- package/templates/standalone/src/__tests__/adapters.test.mts +0 -425
- package/templates/standalone/src/__tests__/admission-lifecycle.test.mts +0 -87
- package/templates/standalone/src/__tests__/all-modules-composition.fixture.mts +0 -1188
- package/templates/standalone/src/__tests__/all-modules-composition.multi.test.mts +0 -285
- package/templates/standalone/src/__tests__/all-modules-composition.test.mts +0 -1154
- package/templates/standalone/src/__tests__/audit-sink.test.mts +0 -355
- package/templates/standalone/src/__tests__/backchannel-peer.fixture.mts +0 -64
- package/templates/standalone/src/__tests__/config-notices.test.mts +0 -157
- package/templates/standalone/src/__tests__/configPath.test.mts +0 -69
- package/templates/standalone/src/__tests__/configured-mfa-mode.fixture.mts +0 -48
- package/templates/standalone/src/__tests__/core-federations.test.mts +0 -252
- package/templates/standalone/src/__tests__/core-sections.test.mts +0 -192
- package/templates/standalone/src/__tests__/device-code-store-client-module.test.mts +0 -95
- package/templates/standalone/src/__tests__/documented-env-overrides.test.mts +0 -1291
- package/templates/standalone/src/__tests__/federation-grants-composition.test.mts +0 -787
- package/templates/standalone/src/__tests__/federation-grants-survive-logout.test.mts +0 -464
- package/templates/standalone/src/__tests__/federation-token-refresh-outage.test.mts +0 -141
- package/templates/standalone/src/__tests__/federation-types.test.mts +0 -239
- package/templates/standalone/src/__tests__/frontchannel-logout-csp.test.mts +0 -168
- package/templates/standalone/src/__tests__/google-session.fixture.mts +0 -318
- package/templates/standalone/src/__tests__/host-routes.test.mts +0 -134
- package/templates/standalone/src/__tests__/library-reference-resolution.smoke.test.mts +0 -29
- package/templates/standalone/src/__tests__/library-references.fixture.mts +0 -188
- package/templates/standalone/src/__tests__/lifecycle-pending-close.test.mts +0 -217
- package/templates/standalone/src/__tests__/listen.test.mts +0 -121
- package/templates/standalone/src/__tests__/logger-projection.test.mts +0 -77
- package/templates/standalone/src/__tests__/logout-session-cookie.test.mts +0 -113
- package/templates/standalone/src/__tests__/mail-sender.test.mts +0 -134
- package/templates/standalone/src/__tests__/mailpit-compose.test.mts +0 -393
- package/templates/standalone/src/__tests__/metrics.test.mts +0 -253
- package/templates/standalone/src/__tests__/mfa-routes-budget.test.mts +0 -122
- package/templates/standalone/src/__tests__/mfa-switch.redis.test.mts +0 -127
- package/templates/standalone/src/__tests__/mfa-switch.test.mts +0 -883
- package/templates/standalone/src/__tests__/own-modules.test.mts +0 -1480
- package/templates/standalone/src/__tests__/post-logout-redirect.test.mts +0 -183
- package/templates/standalone/src/__tests__/redis-assume-noeviction.test.mts +0 -283
- package/templates/standalone/src/__tests__/redis-connection-error-log.test.mts +0 -135
- package/templates/standalone/src/__tests__/redis-rate-limiter-config-survives.test.mts +0 -214
- package/templates/standalone/src/__tests__/redis-stand-in.fixture.mts +0 -98
- package/templates/standalone/src/__tests__/refresh-token-family-client-module.test.mts +0 -249
- package/templates/standalone/src/__tests__/replica-safety.test.mts +0 -657
- package/templates/standalone/src/__tests__/repositories-logger.test.mts +0 -119
- package/templates/standalone/src/__tests__/router-error-answers.test.mts +0 -146
- package/templates/standalone/src/__tests__/scaffold-assets.test.mts +0 -610
- package/templates/standalone/src/__tests__/sections.test.mts +0 -516
- package/templates/standalone/src/__tests__/session-lifecycle.test.mts +0 -213
- package/templates/standalone/src/__tests__/session-logout-invalidates-token.test.mts +0 -305
- package/templates/standalone/src/__tests__/session-logout-lifecycle.test.mts +0 -130
- package/templates/standalone/src/__tests__/session-requirements.test.mts +0 -382
- package/templates/standalone/src/__tests__/shipped-config-notices.test.mts +0 -274
- package/templates/standalone/src/__tests__/shutdown.test.mts +0 -622
- package/templates/standalone/src/__tests__/smoke.test.mts +0 -642
- package/templates/standalone/src/__tests__/startup-log-lines.test.mts +0 -164
- package/templates/standalone/src/__tests__/store-credential.test.mts +0 -314
- package/templates/standalone/src/__tests__/supertest-loopback.test.mts +0 -296
- package/templates/standalone/src/__tests__/three-tier-resolution.test.mts +0 -265
- package/templates/standalone/src/__tests__/two-phase-config.test.mts +0 -605
- package/templates/standalone/src/__tests__/upstream-amr.acceptance.test.mts +0 -385
- package/templates/standalone/src/adapters.mts +0 -162
- package/templates/standalone/src/app.mts +0 -127
- package/templates/standalone/src/bootRefusal.mts +0 -117
- package/templates/standalone/src/buildModules.mts +0 -358
- package/templates/standalone/src/configPath.mts +0 -487
- package/templates/standalone/src/listen.mts +0 -60
- package/templates/standalone/src/logger.mts +0 -80
- package/templates/standalone/src/metrics.mts +0 -167
- package/templates/standalone/src/mfaSwitch.mts +0 -284
- package/templates/standalone/src/modules.mts +0 -705
- package/templates/standalone/src/rootRenames.mts +0 -95
- package/templates/standalone/src/routes.mts +0 -89
- package/templates/standalone/src/sections.mts +0 -378
- package/templates/standalone/src/securityHeaders.mts +0 -36
- package/templates/standalone/src/shutdown.mts +0 -213
- package/templates/standalone/tests/Makefile +0 -5
- package/templates/standalone/tests/index.test.js +0 -283
- package/templates/standalone/tests/package-lock.json +0 -1617
- package/templates/standalone/tests/package.json +0 -16
- package/templates/standalone/tests/vitest.config.mjs +0 -26
- package/templates/standalone/tsconfig.json +0 -31
- package/templates/standalone/vitest.config.mts +0 -31
- package/templates/standalone/vitest.supertest-loopback.mts +0 -278
- package/templates/versions.json +0 -20
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2026 1o1 Co. Ltd.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* The repositories module builds its user repository with the composition's
|
|
19
|
-
* logger: the yaml user builder's `user_repository_in_memory` line reaches the
|
|
20
|
-
* `logger` bootstrap component (the template's pino logger, at its level),
|
|
21
|
-
* not the console.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import fs from "node:fs";
|
|
25
|
-
import os from "node:os";
|
|
26
|
-
import path from "node:path";
|
|
27
|
-
import {
|
|
28
|
-
type BootstrapMap,
|
|
29
|
-
createApp,
|
|
30
|
-
defineModule,
|
|
31
|
-
type Logger,
|
|
32
|
-
type UserRepository,
|
|
33
|
-
} from "@o3co/auth-provider-core";
|
|
34
|
-
import {
|
|
35
|
-
CORE_RELOCATIONS,
|
|
36
|
-
makeValidCoreConfig,
|
|
37
|
-
renamedVariableCaptures,
|
|
38
|
-
} from "@o3co/auth-provider-core/testing";
|
|
39
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
40
|
-
import { repositoriesModuleFor } from "../modules.mjs";
|
|
41
|
-
|
|
42
|
-
const spyLogger = () => {
|
|
43
|
-
const logger = {
|
|
44
|
-
trace: vi.fn(),
|
|
45
|
-
debug: vi.fn(),
|
|
46
|
-
info: vi.fn(),
|
|
47
|
-
warn: vi.fn(),
|
|
48
|
-
error: vi.fn(),
|
|
49
|
-
fatal: vi.fn(),
|
|
50
|
-
child: vi.fn(),
|
|
51
|
-
};
|
|
52
|
-
logger.child.mockReturnValue(logger);
|
|
53
|
-
return logger;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
describe("the repositories module's user repository", () => {
|
|
57
|
-
let dir: string;
|
|
58
|
-
beforeEach(() => {
|
|
59
|
-
dir = fs.mkdtempSync(path.join(os.tmpdir(), "repositories-logger-"));
|
|
60
|
-
});
|
|
61
|
-
afterEach(() => {
|
|
62
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
63
|
-
vi.restoreAllMocks();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("warns user_repository_in_memory on the composition's logger, built through createApp, and not on the console", async () => {
|
|
67
|
-
const usersPath = path.join(dir, "users.yaml");
|
|
68
|
-
fs.writeFileSync(usersPath, 'alice:\n password: "plainpass"\n');
|
|
69
|
-
const clientsPath = path.join(dir, "clients.yaml");
|
|
70
|
-
fs.writeFileSync(clientsPath, "");
|
|
71
|
-
const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
72
|
-
const logger = spyLogger();
|
|
73
|
-
let built: UserRepository | undefined;
|
|
74
|
-
const reader = defineModule({
|
|
75
|
-
name: "test:user-repository-reader",
|
|
76
|
-
requires: ["userRepository"] as const,
|
|
77
|
-
provides: {
|
|
78
|
-
userRepositoryRead: ({ userRepository }: { userRepository: UserRepository }) => {
|
|
79
|
-
built = userRepository;
|
|
80
|
-
return true;
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
lifecycle: { userRepositoryRead: { eager: true } },
|
|
84
|
-
} as never);
|
|
85
|
-
|
|
86
|
-
const repositories = repositoriesModuleFor({ client: "yaml", user: "yaml" });
|
|
87
|
-
const handle = await createApp({
|
|
88
|
-
modules: [repositories, reader],
|
|
89
|
-
bootstrapComponents: {
|
|
90
|
-
config: {
|
|
91
|
-
...makeValidCoreConfig(),
|
|
92
|
-
repositories: {
|
|
93
|
-
client: { yaml: { path: clientsPath } },
|
|
94
|
-
user: { yaml: { path: usersPath }, http: {} },
|
|
95
|
-
},
|
|
96
|
-
// What a resolution with none of the renamed variables set captures.
|
|
97
|
-
"renamed-variables": renamedVariableCaptures({
|
|
98
|
-
modules: [repositories],
|
|
99
|
-
core: CORE_RELOCATIONS,
|
|
100
|
-
env: {},
|
|
101
|
-
}),
|
|
102
|
-
},
|
|
103
|
-
pathResolver: (p: string) => p,
|
|
104
|
-
logger: logger as unknown as Logger,
|
|
105
|
-
} as unknown as BootstrapMap,
|
|
106
|
-
});
|
|
107
|
-
try {
|
|
108
|
-
expect((await built?.authenticate("alice", "plainpass"))?.username).toBe("alice");
|
|
109
|
-
expect(
|
|
110
|
-
logger.warn.mock.calls.filter(([, event]) => event === "user_repository_in_memory"),
|
|
111
|
-
).toEqual([[{ store: "userRepository", adapter: "yaml" }, "user_repository_in_memory"]]);
|
|
112
|
-
expect(
|
|
113
|
-
consoleWarn.mock.calls.filter((args) => args.includes("user_repository_in_memory")),
|
|
114
|
-
).toEqual([]);
|
|
115
|
-
} finally {
|
|
116
|
-
await handle.dispose();
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
});
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2026 1o1 Co. Ltd.
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* The template's composition, booted through core's `createApp` and mounted
|
|
19
|
-
* with no terminal handler of the template's after it — the router alone, as
|
|
20
|
-
* a composition root that copies nothing of `app.mts` mounts it.
|
|
21
|
-
*
|
|
22
|
-
* The router core returns answers a body parser's refusal and any error a
|
|
23
|
-
* route lets through itself. Left to Express's final handler, a host would
|
|
24
|
-
* answer with an HTML page carrying the stack outside production, where V8's
|
|
25
|
-
* JSON error quotes the body it could not parse.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
import { defineModule } from "@o3co/auth-provider-core";
|
|
29
|
-
import { Router } from "express";
|
|
30
|
-
import request from "supertest";
|
|
31
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
32
|
-
import {
|
|
33
|
-
basic,
|
|
34
|
-
type Composition,
|
|
35
|
-
compose,
|
|
36
|
-
JSON_TYPE,
|
|
37
|
-
KIB,
|
|
38
|
-
M2M,
|
|
39
|
-
padJson,
|
|
40
|
-
} from "./all-modules-composition.fixture.mjs";
|
|
41
|
-
|
|
42
|
-
let current: Composition | undefined;
|
|
43
|
-
|
|
44
|
-
afterEach(async () => {
|
|
45
|
-
await current?.handle.dispose();
|
|
46
|
-
current = undefined;
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
/** A route that lets an error through, contributed as a deployment adds one. */
|
|
50
|
-
const throwingRouteModule = defineModule({
|
|
51
|
-
name: "test:throwing-route",
|
|
52
|
-
contributes: {
|
|
53
|
-
routes: [
|
|
54
|
-
() => {
|
|
55
|
-
const router = Router();
|
|
56
|
-
router.get("/", () => {
|
|
57
|
-
throw new Error("a store said something: escaped-error-marker");
|
|
58
|
-
});
|
|
59
|
-
return { id: "test:throwing-route", mountPath: "/throws", handler: router };
|
|
60
|
-
},
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
/** The composition, the router alone mounted. */
|
|
66
|
-
const boot = async (): Promise<Composition> => {
|
|
67
|
-
current = await compose({
|
|
68
|
-
terminalErrorHandler: false,
|
|
69
|
-
extraModules: () => [throwingRouteModule],
|
|
70
|
-
});
|
|
71
|
-
return current;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/** The routes that parse a body, and what each needs to reach its parser. */
|
|
75
|
-
const PARSING_ROUTES = [
|
|
76
|
-
["/oauth/token", { authorization: basic(M2M) }],
|
|
77
|
-
["/oauth/introspect", { authorization: basic(M2M) }],
|
|
78
|
-
["/session/login", {}],
|
|
79
|
-
] as const;
|
|
80
|
-
|
|
81
|
-
const errorLines = (c: Composition) => c.logger.lines.filter((line) => line.level === "error");
|
|
82
|
-
|
|
83
|
-
describe("the composed router, mounted alone, answers a body parser's refusal", () => {
|
|
84
|
-
it.each(PARSING_ROUTES)(
|
|
85
|
-
"%s: malformed JSON is 400 in the envelope, nothing logged",
|
|
86
|
-
async (path, headers) => {
|
|
87
|
-
const c = await boot();
|
|
88
|
-
const res = await request(c.app)
|
|
89
|
-
.post(path)
|
|
90
|
-
.set(headers)
|
|
91
|
-
.set("Content-Type", JSON_TYPE)
|
|
92
|
-
.send('{"password":"body-secret-marker');
|
|
93
|
-
|
|
94
|
-
expect(res.status).toBe(400);
|
|
95
|
-
expect(res.headers["content-type"]).toMatch(/^application\/json/);
|
|
96
|
-
expect(res.body).toEqual({ error: "invalid_request", error_description: "malformed_body" });
|
|
97
|
-
expect(res.text).not.toContain("body-secret-marker");
|
|
98
|
-
expect(res.text).not.toMatch(/ at /);
|
|
99
|
-
expect(errorLines(c)).toEqual([]);
|
|
100
|
-
},
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
it.each(PARSING_ROUTES)(
|
|
104
|
-
"%s: a body over the parser's limit is 413 in the envelope, nothing logged",
|
|
105
|
-
async (path, headers) => {
|
|
106
|
-
const c = await boot();
|
|
107
|
-
const res = await request(c.app)
|
|
108
|
-
.post(path)
|
|
109
|
-
.set(headers)
|
|
110
|
-
.set("Content-Type", JSON_TYPE)
|
|
111
|
-
.send(padJson(200 * KIB));
|
|
112
|
-
|
|
113
|
-
expect(res.status).toBe(413);
|
|
114
|
-
expect(res.headers["content-type"]).toMatch(/^application\/json/);
|
|
115
|
-
expect(res.body).toEqual({ error: "invalid_request", error_description: "body_too_large" });
|
|
116
|
-
expect(errorLines(c)).toEqual([]);
|
|
117
|
-
},
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe("the composed router, mounted alone, answers an error a route let through", () => {
|
|
122
|
-
it("is 500 server_error in the envelope, logged once at error", async () => {
|
|
123
|
-
const c = await boot();
|
|
124
|
-
const res = await request(c.app).get("/throws");
|
|
125
|
-
|
|
126
|
-
expect(res.status).toBe(500);
|
|
127
|
-
expect(res.headers["content-type"]).toMatch(/^application\/json/);
|
|
128
|
-
expect(res.body).toEqual({ error: "server_error", error_description: "unexpected_error" });
|
|
129
|
-
expect(res.text).not.toContain("escaped-error-marker");
|
|
130
|
-
expect(errorLines(c)).toEqual([
|
|
131
|
-
{
|
|
132
|
-
level: "error",
|
|
133
|
-
args: [
|
|
134
|
-
{
|
|
135
|
-
endpoint: "/throws",
|
|
136
|
-
err: expect.objectContaining({
|
|
137
|
-
name: "Error",
|
|
138
|
-
detail: "a store said something: escaped-error-marker",
|
|
139
|
-
}),
|
|
140
|
-
},
|
|
141
|
-
"unhandled_request_error",
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
]);
|
|
145
|
-
});
|
|
146
|
-
});
|