@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.
Files changed (114) hide show
  1. package/README.md +2 -198
  2. package/main.js +4 -0
  3. package/package.json +8 -30
  4. package/README.ja.md +0 -200
  5. package/dist/cli.d.mts +0 -3
  6. package/dist/cli.d.mts.map +0 -1
  7. package/dist/cli.mjs +0 -18
  8. package/dist/index.d.mts +0 -48
  9. package/dist/index.d.mts.map +0 -1
  10. package/dist/index.mjs +0 -325
  11. package/dist/internal/template-filter.d.mts +0 -14
  12. package/dist/internal/template-filter.d.mts.map +0 -1
  13. package/dist/internal/template-filter.mjs +0 -42
  14. package/templates/standalone/.dockerignore +0 -23
  15. package/templates/standalone/.env.example +0 -152
  16. package/templates/standalone/Dockerfile +0 -125
  17. package/templates/standalone/Makefile +0 -12
  18. package/templates/standalone/README.ja.md +0 -912
  19. package/templates/standalone/README.md +0 -1536
  20. package/templates/standalone/config/application.conf +0 -351
  21. package/templates/standalone/config/clients.yaml +0 -4
  22. package/templates/standalone/config/clients.yaml.example +0 -124
  23. package/templates/standalone/config/development.conf +0 -17
  24. package/templates/standalone/config/mailpit.conf +0 -13
  25. package/templates/standalone/config/production.conf +0 -15
  26. package/templates/standalone/config/reference.conf +0 -427
  27. package/templates/standalone/docker-compose.mailpit.yml +0 -39
  28. package/templates/standalone/docker-compose.production.yml +0 -229
  29. package/templates/standalone/docker-compose.test.yml +0 -16
  30. package/templates/standalone/docker-compose.yml +0 -67
  31. package/templates/standalone/gitignore +0 -23
  32. package/templates/standalone/package.json +0 -56
  33. package/templates/standalone/src/__tests__/adapters.test.mts +0 -425
  34. package/templates/standalone/src/__tests__/admission-lifecycle.test.mts +0 -87
  35. package/templates/standalone/src/__tests__/all-modules-composition.fixture.mts +0 -1188
  36. package/templates/standalone/src/__tests__/all-modules-composition.multi.test.mts +0 -285
  37. package/templates/standalone/src/__tests__/all-modules-composition.test.mts +0 -1154
  38. package/templates/standalone/src/__tests__/audit-sink.test.mts +0 -355
  39. package/templates/standalone/src/__tests__/backchannel-peer.fixture.mts +0 -64
  40. package/templates/standalone/src/__tests__/config-notices.test.mts +0 -157
  41. package/templates/standalone/src/__tests__/configPath.test.mts +0 -69
  42. package/templates/standalone/src/__tests__/configured-mfa-mode.fixture.mts +0 -48
  43. package/templates/standalone/src/__tests__/core-federations.test.mts +0 -252
  44. package/templates/standalone/src/__tests__/core-sections.test.mts +0 -192
  45. package/templates/standalone/src/__tests__/device-code-store-client-module.test.mts +0 -95
  46. package/templates/standalone/src/__tests__/documented-env-overrides.test.mts +0 -1291
  47. package/templates/standalone/src/__tests__/federation-grants-composition.test.mts +0 -787
  48. package/templates/standalone/src/__tests__/federation-grants-survive-logout.test.mts +0 -464
  49. package/templates/standalone/src/__tests__/federation-token-refresh-outage.test.mts +0 -141
  50. package/templates/standalone/src/__tests__/federation-types.test.mts +0 -239
  51. package/templates/standalone/src/__tests__/frontchannel-logout-csp.test.mts +0 -168
  52. package/templates/standalone/src/__tests__/google-session.fixture.mts +0 -318
  53. package/templates/standalone/src/__tests__/host-routes.test.mts +0 -134
  54. package/templates/standalone/src/__tests__/library-reference-resolution.smoke.test.mts +0 -29
  55. package/templates/standalone/src/__tests__/library-references.fixture.mts +0 -188
  56. package/templates/standalone/src/__tests__/lifecycle-pending-close.test.mts +0 -217
  57. package/templates/standalone/src/__tests__/listen.test.mts +0 -121
  58. package/templates/standalone/src/__tests__/logger-projection.test.mts +0 -77
  59. package/templates/standalone/src/__tests__/logout-session-cookie.test.mts +0 -113
  60. package/templates/standalone/src/__tests__/mail-sender.test.mts +0 -134
  61. package/templates/standalone/src/__tests__/mailpit-compose.test.mts +0 -393
  62. package/templates/standalone/src/__tests__/metrics.test.mts +0 -253
  63. package/templates/standalone/src/__tests__/mfa-routes-budget.test.mts +0 -122
  64. package/templates/standalone/src/__tests__/mfa-switch.redis.test.mts +0 -127
  65. package/templates/standalone/src/__tests__/mfa-switch.test.mts +0 -883
  66. package/templates/standalone/src/__tests__/own-modules.test.mts +0 -1480
  67. package/templates/standalone/src/__tests__/post-logout-redirect.test.mts +0 -183
  68. package/templates/standalone/src/__tests__/redis-assume-noeviction.test.mts +0 -283
  69. package/templates/standalone/src/__tests__/redis-connection-error-log.test.mts +0 -135
  70. package/templates/standalone/src/__tests__/redis-rate-limiter-config-survives.test.mts +0 -214
  71. package/templates/standalone/src/__tests__/redis-stand-in.fixture.mts +0 -98
  72. package/templates/standalone/src/__tests__/refresh-token-family-client-module.test.mts +0 -249
  73. package/templates/standalone/src/__tests__/replica-safety.test.mts +0 -657
  74. package/templates/standalone/src/__tests__/repositories-logger.test.mts +0 -119
  75. package/templates/standalone/src/__tests__/router-error-answers.test.mts +0 -146
  76. package/templates/standalone/src/__tests__/scaffold-assets.test.mts +0 -610
  77. package/templates/standalone/src/__tests__/sections.test.mts +0 -516
  78. package/templates/standalone/src/__tests__/session-lifecycle.test.mts +0 -213
  79. package/templates/standalone/src/__tests__/session-logout-invalidates-token.test.mts +0 -305
  80. package/templates/standalone/src/__tests__/session-logout-lifecycle.test.mts +0 -130
  81. package/templates/standalone/src/__tests__/session-requirements.test.mts +0 -382
  82. package/templates/standalone/src/__tests__/shipped-config-notices.test.mts +0 -274
  83. package/templates/standalone/src/__tests__/shutdown.test.mts +0 -622
  84. package/templates/standalone/src/__tests__/smoke.test.mts +0 -642
  85. package/templates/standalone/src/__tests__/startup-log-lines.test.mts +0 -164
  86. package/templates/standalone/src/__tests__/store-credential.test.mts +0 -314
  87. package/templates/standalone/src/__tests__/supertest-loopback.test.mts +0 -296
  88. package/templates/standalone/src/__tests__/three-tier-resolution.test.mts +0 -265
  89. package/templates/standalone/src/__tests__/two-phase-config.test.mts +0 -605
  90. package/templates/standalone/src/__tests__/upstream-amr.acceptance.test.mts +0 -385
  91. package/templates/standalone/src/adapters.mts +0 -162
  92. package/templates/standalone/src/app.mts +0 -127
  93. package/templates/standalone/src/bootRefusal.mts +0 -117
  94. package/templates/standalone/src/buildModules.mts +0 -358
  95. package/templates/standalone/src/configPath.mts +0 -487
  96. package/templates/standalone/src/listen.mts +0 -60
  97. package/templates/standalone/src/logger.mts +0 -80
  98. package/templates/standalone/src/metrics.mts +0 -167
  99. package/templates/standalone/src/mfaSwitch.mts +0 -284
  100. package/templates/standalone/src/modules.mts +0 -705
  101. package/templates/standalone/src/rootRenames.mts +0 -95
  102. package/templates/standalone/src/routes.mts +0 -89
  103. package/templates/standalone/src/sections.mts +0 -378
  104. package/templates/standalone/src/securityHeaders.mts +0 -36
  105. package/templates/standalone/src/shutdown.mts +0 -213
  106. package/templates/standalone/tests/Makefile +0 -5
  107. package/templates/standalone/tests/index.test.js +0 -283
  108. package/templates/standalone/tests/package-lock.json +0 -1617
  109. package/templates/standalone/tests/package.json +0 -16
  110. package/templates/standalone/tests/vitest.config.mjs +0 -26
  111. package/templates/standalone/tsconfig.json +0 -31
  112. package/templates/standalone/vitest.config.mts +0 -31
  113. package/templates/standalone/vitest.supertest-loopback.mts +0 -278
  114. package/templates/versions.json +0 -20
@@ -1,427 +0,0 @@
1
- # Defaults of the standalone template's own modules (src/modules.mts), each in
2
- # the section named after its module, and of its own `adapters` and
3
- # `mfaMode`, each key with its variable, named after its path, and the MFA
4
- # routes' budget in each rate limiter's section (below `mfaMode`). Layered
5
- # beneath application.conf and {env}.conf: set a deployment's own values
6
- # there, not here. A value either file sets wins over
7
- # the variable bound here, except for HTTP_PORT, HTTP_TRUST_PROXY,
8
- # HTTP_CORS_ALLOWED_ORIGINS and REDIS_CLIENTS_URL / _PASSWORD, which
9
- # application.conf binds again in its last lines, so they win over a value it
10
- # sets above them.
11
-
12
- # `logging`: trace | debug | info | warn | error | fatal | silent. `trace` and
13
- # `debug` carry request-shaped detail; `silent` spares only the audit trail.
14
- logging {
15
- level = "info"
16
- level = ${?LOGGING_LEVEL}
17
- }
18
-
19
- # `http`: the listener, the trusted forwarding hops, the readiness deadline and
20
- # the CORS list.
21
- http {
22
- port = 3000
23
- port = ${?HTTP_PORT}
24
- # Express `trust proxy`: whether X-Forwarded-For may rewrite `req.ip`
25
- # (every IP-keyed rate limit) and X-Forwarded-Proto may rewrite
26
- # `req.protocol`.
27
- #
28
- # Four shapes, all of them Express's own:
29
- #
30
- # false trust nothing. `req.ip` is the socket peer. The default.
31
- # <address list> trust these hops, and only these. An IP literal, a CIDR
32
- # range (10.0.0.0/8, fc00::/7), or a named range
33
- # (loopback, linklocal, uniquelocal). This is the only
34
- # shape that says WHICH hop is trusted, and it is the one
35
- # to reach for. Via env var, comma-separate:
36
- # HTTP_TRUST_PROXY=10.0.0.0/8,192.168.0.0/16
37
- # <hop count> trust that many hops back from the socket peer, e.g. 1
38
- # for exactly one reverse proxy in front of this process.
39
- # true trust every hop, i.e. believe the leftmost
40
- # X-Forwarded-For entry from whoever opened the connection.
41
- # Correct ONLY when nothing but the proxy can route to this
42
- # process; otherwise a client that reaches it directly, or
43
- # through one more hop than you accounted for, forges its
44
- # own `req.ip` and with it any IP-keyed rate-limit identity.
45
- #
46
- # Entries are validated at boot: a hostname, a mistyped keyword or a
47
- # malformed prefix length fails loudly rather than becoming a rule that
48
- # never matches.
49
- #
50
- # An allowlist is a network control, not a cryptographic one. The edge must
51
- # also STRIP inbound X-Forwarded-* headers rather than appending to them,
52
- # and the hop between it and this process must not be reachable by anyone
53
- # able to spoof a source address.
54
- #
55
- # Unrelated to `mtls.trustedProxies`, which shares this vocabulary but
56
- # answers a different question (may this peer forward a client certificate?)
57
- # and is deliberately not derived from this key.
58
- trustProxy = false
59
- trustProxy = ${?HTTP_TRUST_PROXY}
60
- # Per-probe deadline for /readyz and the metrics scrape's probes. Keep it
61
- # below the orchestrator's own probe timeout so an unreachable dependency
62
- # answers 503 rather than letting the probe hang.
63
- readinessTimeoutMs = 1000
64
- readinessTimeoutMs = ${?HTTP_READINESS_TIMEOUT_MS}
65
- # `cors`: the browser origins allowed to read the token, userinfo,
66
- # revocation and discovery/JWKS responses. Empty (the default) means CORS
67
- # is off.
68
- #
69
- # Matching against the `Origin` request header is exact string equality,
70
- # so each entry is a bare origin: scheme, host, and a port only when it is
71
- # not the scheme's default; no trailing slash, no path, no wildcard. https
72
- # is required except for a loopback host (localhost, 127.0.0.0/8, [::1]).
73
- # Each rule is checked at boot.
74
- #
75
- # cors.allowedOrigins = ["https://app.example.com", "http://localhost:5173"]
76
- #
77
- # No credentials are ever allowed: an allowlisted origin can read these
78
- # responses and cannot use the browser's session cookie. This list confers
79
- # no CSRF trust; that is `session.csrf.trustedOrigins`. The variable takes a
80
- # comma-separated list.
81
- cors {
82
- allowedOrigins = []
83
- allowedOrigins = ${?HTTP_CORS_ALLOWED_ORIGINS}
84
- }
85
- }
86
-
87
- # `key-store`: the JWT signing key.
88
- key-store {
89
- provider = "local"
90
- provider = ${?KEY_STORE_PROVIDER}
91
- local {
92
- # The default is asymmetric. HS256 leaves a relying party with two bad
93
- # options: verify nothing (there is no public key to publish, so
94
- # /.well-known/jwks.json has nothing to serve), or hold the shared
95
- # secret, which also lets it mint tokens. EdDSA (Ed25519) publishes a
96
- # real JWKS and keeps signing capability here.
97
- #
98
- # There is no key material default and no fallback: a deployment that
99
- # configures nothing fails at boot naming the keys to set, rather than
100
- # quietly signing with a guessable secret.
101
- #
102
- # openssl genpkey -algorithm ed25519 -out jwt-private.pem
103
- # openssl pkey -in jwt-private.pem -pubout -out jwt-public.pem
104
- #
105
- # HS256 remains selectable (KEY_STORE_LOCAL_ALGORITHM=HS256) for
106
- # deployments that verify in-process and publish no JWKS. It then requires
107
- # KEY_STORE_LOCAL_SECRET with at least 32 bytes (256 bits) of random material
108
- # (`openssl rand -hex 32`). Hex and base64 values are measured decoded, so
109
- # a 32-character hex string is only 16 bytes and is refused.
110
- algorithm = "EdDSA"
111
- algorithm = ${?KEY_STORE_LOCAL_ALGORITHM}
112
- kid = "v0"
113
- kid = ${?KEY_STORE_LOCAL_KID}
114
- secret = ${?KEY_STORE_LOCAL_SECRET}
115
- privateKeyPath = ${?KEY_STORE_LOCAL_PRIVATE_KEY_PATH}
116
- publicKeyPath = ${?KEY_STORE_LOCAL_PUBLIC_KEY_PATH}
117
- privateKey = ${?KEY_STORE_LOCAL_PRIVATE_KEY}
118
- publicKey = ${?KEY_STORE_LOCAL_PUBLIC_KEY}
119
- # Key rotation is shaped per algorithm family. Asymmetric algorithms
120
- # (RS256, ES256, EdDSA) use `previousKeys` (kid, publicKey or
121
- # publicKeyPath, expiresAt); HS256 uses `previousSecrets` (kid, secret,
122
- # expiresAt). The schema is a discriminated union and the key store
123
- # refuses the other family's field, so the wrong shape fails at boot
124
- # rather than being dropped at verification time. Neither is declared
125
- # here: the default algorithm is EdDSA, and an empty
126
- # `previousSecrets = []` under it would be exactly that wrong shape. Add
127
- # the one matching your algorithm in your own layer.
128
- }
129
- }
130
-
131
- # `redis-clients`: the one ioredis socket per replica every Redis-backed store
132
- # shares. More than one replica needs a shared Redis 7.2+ here; localhost
133
- # inside a container is the container itself. The Redis stores that keep
134
- # durable keys refuse to boot unless the server reports maxmemory-policy
135
- # `noeviction`. `assumeNoEviction = true` asserts it for a server that will not
136
- # report it (INFO and CONFIG refused to the connection's user); a policy the
137
- # server does report always decides.
138
- redis-clients {
139
- url = "redis://localhost:6379"
140
- url = ${?REDIS_CLIENTS_URL}
141
- password = ${?REDIS_CLIENTS_PASSWORD}
142
- assumeNoEviction = false
143
- assumeNoEviction = ${?REDIS_CLIENTS_ASSUME_NO_EVICTION}
144
- }
145
-
146
- # `repositories`: the client registry, and the user repository's settings for
147
- # each adapter it may be (`adapters.userRepository`). The two YAML paths are
148
- # cwd-relative.
149
- repositories {
150
- client {
151
- yaml {
152
- path = "./config/clients.yaml"
153
- path = ${?REPOSITORIES_CLIENT_YAML_PATH}
154
- }
155
- }
156
- user {
157
- yaml {
158
- path = "./config/users.yaml"
159
- path = ${?REPOSITORIES_USER_YAML_PATH}
160
- }
161
- # The Store's HTTP endpoints. Every URL here carries what a Store must
162
- # never receive in the clear -- user credentials to the first two, a
163
- # verified federation token and its claims to the link and the lookup, a
164
- # subject's MFA enrollment witness to the last -- so each must be an
165
- # absolute https URL; http:// is accepted only for a loopback host
166
- # (localhost, 127.0.0.0/8, [::1]). Each must be the endpoint that answers:
167
- # no request follows a 3xx. Boot fails otherwise.
168
- http {
169
- authenticateUrl = ${?REPOSITORIES_USER_HTTP_AUTHENTICATE_URL}
170
- authenticateByTokenUrl = ${?REPOSITORIES_USER_HTTP_AUTHENTICATE_BY_TOKEN_URL}
171
- # Optional. With it, a signed-in user can link a second federated
172
- # identity (GET /session/oauth/federation/<name>?link=1) and the Store
173
- # decides; without it, link=1 is refused with `link_unsupported`.
174
- linkFederatedIdentityUrl = ${?REPOSITORIES_USER_HTTP_LINK_FEDERATED_IDENTITY_URL}
175
- # Optional. The Store's identity lookup for federation grants. With it,
176
- # declare what the lookup covers, per registration, in a HOCON layer (a
177
- # list has no environment form):
178
- # federatedIdentityLookupCoverage = [
179
- # { provider = "entra-files", issuer = "...", clientId = "...", requiredClaims = ["tid", "oid"] }
180
- # ]
181
- findSubjectByFederatedIdentityUrl = ${?REPOSITORIES_USER_HTTP_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL}
182
- federatedIdentityLookupCoverage = []
183
- # Optional. The Store's MFA enrollment witness endpoint: with it, the
184
- # provider writes whether a subject has a second factor, which keeps a
185
- # lost factor store from opening a first binding; without it, a boot
186
- # with MFA on warns (`mfa_enrollment_witness_unwritable`). The Store
187
- # must then answer `mfaEnrolled` on both authenticate URLs.
188
- markMfaEnrolledUrl = ${?REPOSITORIES_USER_HTTP_MARK_MFA_ENROLLED_URL}
189
- # Optional. Sent on every Store request as `Authorization: Bearer
190
- # <token>`, so the Store can refuse any caller but this deployment;
191
- # unset, none is sent. A bare token (no "Bearer " prefix) of at least 32
192
- # bytes of key material -- `openssl rand -hex 32`. Boot fails on a weak,
193
- # malformed or blank value. One token goes to every URL above.
194
- bearerToken = ${?REPOSITORIES_USER_HTTP_BEARER_TOKEN}
195
- # Positive integer, milliseconds, <= 2147483647.
196
- timeout = 5000
197
- timeout = ${?REPOSITORIES_USER_HTTP_TIMEOUT}
198
- # Largest upstream response body accepted, in bytes. Positive integer.
199
- maxResponseBytes = 1048576
200
- maxResponseBytes = ${?REPOSITORIES_USER_HTTP_MAX_RESPONSE_BYTES}
201
- }
202
- }
203
- }
204
-
205
- # `standalone-in-memory-code-repository`: the in-process authorization-code
206
- # repository (`adapters.codeRepository = "memory"`), single-replica only. Its
207
- # codes' default lifetime, in positive whole seconds.
208
- standalone-in-memory-code-repository {
209
- defaultExpiresIn = 600
210
- defaultExpiresIn = ${?STANDALONE_IN_MEMORY_CODE_REPOSITORY_DEFAULT_EXPIRES_IN}
211
- }
212
-
213
- # `audit-sink`: each sink's options, under the sink's name, for the sink
214
- # `adapters.auditSink` selects -- `audit-sink { splunk-hec { ... } }` for a sink
215
- # a deployment registers in the audit-sink module (src/modules.mts). The
216
- # template's `logger` and core's `console` take none.
217
- audit-sink {}
218
-
219
- # `adapters`: the composition root's own section -- which adapter fills each
220
- # slot. The template reads it before it chooses its modules, and hands it to
221
- # no module. Each value is what the template ships.
222
- #
223
- # More than one replica needs every shared store on Redis: `memory` forks per
224
- # replica, and `core.deployment.mode = "multi"` refuses each memory store by
225
- # name. Each Redis store shares the one socket `redis-clients` opens.
226
- adapters {
227
- # The rate-limit counters: the OAuth endpoints' and the MFA routes'.
228
- rateLimiter = "memory"
229
- rateLimiter = ${?ADAPTERS_RATE_LIMITER}
230
- # The counter behind /session/login's own attempt limit
231
- # (session.rateLimit.login), and device verification's
232
- # (device-grant.rateLimit) when the device grant is added. `memory` wires
233
- # none: each counts per process, which `core.deployment.mode = "multi"`
234
- # refuses. `redis` needs a server whose maxmemory-policy is `noeviction`.
235
- attemptCounter = "memory"
236
- attemptCounter = ${?ADAPTERS_ATTEMPT_COUNTER}
237
- # The four user-session stores and the subject-level revocation pair. They
238
- # must be on Redis whenever express-session's store is, or a restart leaves
239
- # every browser a session whose user session is gone. `redis` needs a server
240
- # whose maxmemory-policy is `noeviction` once the revocation store is read.
241
- userSessionStores = "memory"
242
- userSessionStores = ${?ADAPTERS_USER_SESSION_STORES}
243
- # The RFC 7009 access-token denylist, which POST /oauth/revoke writes and
244
- # verification reads. On Redis, so a token revoked on one replica is revoked
245
- # on every one; `redis` needs a server whose maxmemory-policy is
246
- # `noeviction`.
247
- accessTokenDenylist = "redis"
248
- accessTokenDenylist = ${?ADAPTERS_ACCESS_TOKEN_DENYLIST}
249
- # The `jti` single-use record behind private_key_jwt client authentication.
250
- # `redis` needs a server whose maxmemory-policy is `noeviction`.
251
- replaySeenSet = "redis"
252
- replaySeenSet = ${?ADAPTERS_REPLAY_SEEN_SET}
253
- # Consent to a client that is not first-party: "none" wires no store and
254
- # such clients are refused at /authorize; "memory" is single-replica only;
255
- # "redis" keeps the consent records and parked requests on the shared
256
- # socket (key namespace REDIS_CONSENT_STORE_KEY_PREFIX).
257
- consentStore = "none"
258
- consentStore = ${?ADAPTERS_CONSENT_STORE}
259
- # The upstream IdP tokens held for a session. "redis" needs its encryption
260
- # key, REDIS_FEDERATION_TOKEN_STORE_ENCRYPTION_KEY.
261
- federationTokenStore = "memory"
262
- federationTokenStore = ${?ADAPTERS_FEDERATION_TOKEN_STORE}
263
- # Federation grants and acquisition's records, read only while
264
- # `federation-grants.enabled`: "none" (the default) wires no store, and an
265
- # enabled feature refuses boot naming the one it lacks; "memory" is
266
- # single-replica only; "redis" is the shared socket. Redis grants need the
267
- # subject boundary in Redis too (`userSessionStores = "redis"`): boot
268
- # refuses the pairing with a memory one.
269
- federationGrantStore = "none"
270
- federationGrantStore = ${?ADAPTERS_FEDERATION_GRANT_STORE}
271
- federationGrantIntentStore = "none"
272
- federationGrantIntentStore = ${?ADAPTERS_FEDERATION_GRANT_INTENT_STORE}
273
- # Where MFA factors ("memory", "redis" or "store") and MFA transactions
274
- # ("memory" or "redis") are kept, for a composition that installs MFA.
275
- mfaFactorStore = "memory"
276
- mfaFactorStore = ${?ADAPTERS_MFA_FACTOR_STORE}
277
- mfaTransactionStore = "memory"
278
- mfaTransactionStore = ${?ADAPTERS_MFA_TRANSACTION_STORE}
279
- # The authorization-code repository ("memory" loses codes on restart and
280
- # across replicas).
281
- codeRepository = "redis"
282
- codeRepository = ${?ADAPTERS_CODE_REPOSITORY}
283
- # The client registry (YAML), and the user repository: the Store's HTTP
284
- # endpoints, or a YAML directory.
285
- clientRepository = "yaml"
286
- clientRepository = ${?ADAPTERS_CLIENT_REPOSITORY}
287
- userRepository = "http"
288
- userRepository = ${?ADAPTERS_USER_REPOSITORY}
289
- # Where the audit trail goes: "logger" writes each event through the pino
290
- # stream every other line takes; core's "console" writes the bare event.
291
- # There is no "none": a name no sink is registered under refuses boot.
292
- auditSink = "logger"
293
- auditSink = ${?ADAPTERS_AUDIT_SINK}
294
- }
295
-
296
- # `mfaMode`: the composition root's own key -- whether the template installs
297
- # MFA. Read before it chooses its modules, and handed to no module, as
298
- # `adapters` is. "required" (the default: every password login has a second
299
- # factor) and "optional" (users with a factor are challenged) install the MFA
300
- # package's modules over the two MFA stores above, declare `mfa` in
301
- # core.sessionRequirements.expected and write `mfa.mode` from this; "off"
302
- # installs nothing of MFA. Anything else is refused before boot. A
303
- # configuration that writes `mfa.mode` itself must write what this says, or
304
- # boot is refused.
305
- #
306
- # With MFA on outside development, it needs its two stores on "redis" (or the
307
- # factors in the "store"), MFA_ENCRYPTION_KEY, an SMTP relay
308
- # (STANDARD_SMTP_MAIL_SENDER_HOST and _FROM) or the deployment's own mail
309
- # sender, and a page served at MFA_PAGE_URL (/mfa unless set); a deployment
310
- # that wants none of it sets MFA_MODE=off.
311
- mfaMode = "required"
312
- mfaMode = ${?MFA_MODE}
313
-
314
- # The MFA routes' budget: the one setting this file writes in sections of
315
- # modules other than the template's own. Every /session/mfa POST is limited
316
- # per client address under the prefix `mfa` (`mfa:ip:<ip>`) by the wired
317
- # limiter alone: the MFA package ships no budget of its own. Both limiters
318
- # carry it, so switching `adapters.rateLimiter` keeps it; written here, beside
319
- # each package's own defaults, the limiter not wired has it as a default
320
- # rather than as a setting nothing reads. Without an entry the limiter's
321
- # `defaultLimit` (60 per 60 s) applies. The MFA lock is separate and unchanged.
322
- core-rate-limiter-memory.limits.mfa { limit = 60, windowSeconds = 300 }
323
- redis-rate-limiter.limits.mfa { limit = 60, windowSeconds = 300 }
324
-
325
- # The old paths of these sections refuse boot naming the new ones: `cors`,
326
- # `oauth.jwt.signingKey`, `refreshTokenFamilyStore.redis`,
327
- # `repositories.code` and `audit.sink`; the old adapter switches
328
- # (`rateLimiter.adapter`, `oauth.code.adapter`, ...) are refused before the
329
- # modules are chosen, and so are the variables renamed with them. What the
330
- # resolution saw of each variable they renamed: each name null, then its value
331
- # when set. Boot refuses an old name set, whether or not its new name is set,
332
- # and removes this section before it parses the configuration.
333
- # Never write it in another layer.
334
- renamed-variables {
335
- LOG_LEVEL = null
336
- LOG_LEVEL = ${?LOG_LEVEL}
337
- LOGGING_LEVEL = null
338
- LOGGING_LEVEL = ${?LOGGING_LEVEL}
339
- CORS_ALLOWED_ORIGINS = null
340
- CORS_ALLOWED_ORIGINS = ${?CORS_ALLOWED_ORIGINS}
341
- HTTP_CORS_ALLOWED_ORIGINS = null
342
- HTTP_CORS_ALLOWED_ORIGINS = ${?HTTP_CORS_ALLOWED_ORIGINS}
343
- OAUTH_JWT_SIGNING_KEY_PROVIDER = null
344
- OAUTH_JWT_SIGNING_KEY_PROVIDER = ${?OAUTH_JWT_SIGNING_KEY_PROVIDER}
345
- KEY_STORE_PROVIDER = null
346
- KEY_STORE_PROVIDER = ${?KEY_STORE_PROVIDER}
347
- OAUTH_JWT_ALGORITHM = null
348
- OAUTH_JWT_ALGORITHM = ${?OAUTH_JWT_ALGORITHM}
349
- KEY_STORE_LOCAL_ALGORITHM = null
350
- KEY_STORE_LOCAL_ALGORITHM = ${?KEY_STORE_LOCAL_ALGORITHM}
351
- OAUTH_JWT_KID = null
352
- OAUTH_JWT_KID = ${?OAUTH_JWT_KID}
353
- KEY_STORE_LOCAL_KID = null
354
- KEY_STORE_LOCAL_KID = ${?KEY_STORE_LOCAL_KID}
355
- OAUTH_JWT_SECRET = null
356
- OAUTH_JWT_SECRET = ${?OAUTH_JWT_SECRET}
357
- KEY_STORE_LOCAL_SECRET = null
358
- KEY_STORE_LOCAL_SECRET = ${?KEY_STORE_LOCAL_SECRET}
359
- OAUTH_JWT_PRIVATE_KEY_PATH = null
360
- OAUTH_JWT_PRIVATE_KEY_PATH = ${?OAUTH_JWT_PRIVATE_KEY_PATH}
361
- KEY_STORE_LOCAL_PRIVATE_KEY_PATH = null
362
- KEY_STORE_LOCAL_PRIVATE_KEY_PATH = ${?KEY_STORE_LOCAL_PRIVATE_KEY_PATH}
363
- OAUTH_JWT_PUBLIC_KEY_PATH = null
364
- OAUTH_JWT_PUBLIC_KEY_PATH = ${?OAUTH_JWT_PUBLIC_KEY_PATH}
365
- KEY_STORE_LOCAL_PUBLIC_KEY_PATH = null
366
- KEY_STORE_LOCAL_PUBLIC_KEY_PATH = ${?KEY_STORE_LOCAL_PUBLIC_KEY_PATH}
367
- OAUTH_JWT_PRIVATE_KEY = null
368
- OAUTH_JWT_PRIVATE_KEY = ${?OAUTH_JWT_PRIVATE_KEY}
369
- KEY_STORE_LOCAL_PRIVATE_KEY = null
370
- KEY_STORE_LOCAL_PRIVATE_KEY = ${?KEY_STORE_LOCAL_PRIVATE_KEY}
371
- OAUTH_JWT_PUBLIC_KEY = null
372
- OAUTH_JWT_PUBLIC_KEY = ${?OAUTH_JWT_PUBLIC_KEY}
373
- KEY_STORE_LOCAL_PUBLIC_KEY = null
374
- KEY_STORE_LOCAL_PUBLIC_KEY = ${?KEY_STORE_LOCAL_PUBLIC_KEY}
375
- REFRESH_TOKEN_FAMILY_STORE_REDIS_URL = null
376
- REFRESH_TOKEN_FAMILY_STORE_REDIS_URL = ${?REFRESH_TOKEN_FAMILY_STORE_REDIS_URL}
377
- REDIS_CLIENTS_URL = null
378
- REDIS_CLIENTS_URL = ${?REDIS_CLIENTS_URL}
379
- REFRESH_TOKEN_FAMILY_STORE_REDIS_PASSWORD = null
380
- REFRESH_TOKEN_FAMILY_STORE_REDIS_PASSWORD = ${?REFRESH_TOKEN_FAMILY_STORE_REDIS_PASSWORD}
381
- REDIS_CLIENTS_PASSWORD = null
382
- REDIS_CLIENTS_PASSWORD = ${?REDIS_CLIENTS_PASSWORD}
383
- CLIENT_PATH = null
384
- CLIENT_PATH = ${?CLIENT_PATH}
385
- REPOSITORIES_CLIENT_YAML_PATH = null
386
- REPOSITORIES_CLIENT_YAML_PATH = ${?REPOSITORIES_CLIENT_YAML_PATH}
387
- CLIENT_USER_PATH = null
388
- CLIENT_USER_PATH = ${?CLIENT_USER_PATH}
389
- REPOSITORIES_USER_YAML_PATH = null
390
- REPOSITORIES_USER_YAML_PATH = ${?REPOSITORIES_USER_YAML_PATH}
391
- CLIENT_USER_AUTHENTICATE_URL = null
392
- CLIENT_USER_AUTHENTICATE_URL = ${?CLIENT_USER_AUTHENTICATE_URL}
393
- REPOSITORIES_USER_HTTP_AUTHENTICATE_URL = null
394
- REPOSITORIES_USER_HTTP_AUTHENTICATE_URL = ${?REPOSITORIES_USER_HTTP_AUTHENTICATE_URL}
395
- CLIENT_USER_AUTHENTICATE_BY_TOKEN_URL = null
396
- CLIENT_USER_AUTHENTICATE_BY_TOKEN_URL = ${?CLIENT_USER_AUTHENTICATE_BY_TOKEN_URL}
397
- REPOSITORIES_USER_HTTP_AUTHENTICATE_BY_TOKEN_URL = null
398
- REPOSITORIES_USER_HTTP_AUTHENTICATE_BY_TOKEN_URL = ${?REPOSITORIES_USER_HTTP_AUTHENTICATE_BY_TOKEN_URL}
399
- CLIENT_USER_LINK_FEDERATED_IDENTITY_URL = null
400
- CLIENT_USER_LINK_FEDERATED_IDENTITY_URL = ${?CLIENT_USER_LINK_FEDERATED_IDENTITY_URL}
401
- REPOSITORIES_USER_HTTP_LINK_FEDERATED_IDENTITY_URL = null
402
- REPOSITORIES_USER_HTTP_LINK_FEDERATED_IDENTITY_URL = ${?REPOSITORIES_USER_HTTP_LINK_FEDERATED_IDENTITY_URL}
403
- CLIENT_USER_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL = null
404
- CLIENT_USER_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL = ${?CLIENT_USER_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL}
405
- REPOSITORIES_USER_HTTP_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL = null
406
- REPOSITORIES_USER_HTTP_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL = ${?REPOSITORIES_USER_HTTP_FIND_SUBJECT_BY_FEDERATED_IDENTITY_URL}
407
- CLIENT_USER_BEARER_TOKEN = null
408
- CLIENT_USER_BEARER_TOKEN = ${?CLIENT_USER_BEARER_TOKEN}
409
- REPOSITORIES_USER_HTTP_BEARER_TOKEN = null
410
- REPOSITORIES_USER_HTTP_BEARER_TOKEN = ${?REPOSITORIES_USER_HTTP_BEARER_TOKEN}
411
- CLIENT_USER_TIMEOUT = null
412
- CLIENT_USER_TIMEOUT = ${?CLIENT_USER_TIMEOUT}
413
- REPOSITORIES_USER_HTTP_TIMEOUT = null
414
- REPOSITORIES_USER_HTTP_TIMEOUT = ${?REPOSITORIES_USER_HTTP_TIMEOUT}
415
- CLIENT_USER_MAX_RESPONSE_BYTES = null
416
- CLIENT_USER_MAX_RESPONSE_BYTES = ${?CLIENT_USER_MAX_RESPONSE_BYTES}
417
- REPOSITORIES_USER_HTTP_MAX_RESPONSE_BYTES = null
418
- REPOSITORIES_USER_HTTP_MAX_RESPONSE_BYTES = ${?REPOSITORIES_USER_HTTP_MAX_RESPONSE_BYTES}
419
- CLIENT_CODE_DEFAULT_EXPIRES_IN = null
420
- CLIENT_CODE_DEFAULT_EXPIRES_IN = ${?CLIENT_CODE_DEFAULT_EXPIRES_IN}
421
- STANDALONE_IN_MEMORY_CODE_REPOSITORY_DEFAULT_EXPIRES_IN = null
422
- STANDALONE_IN_MEMORY_CODE_REPOSITORY_DEFAULT_EXPIRES_IN = ${?STANDALONE_IN_MEMORY_CODE_REPOSITORY_DEFAULT_EXPIRES_IN}
423
- CLIENT_CODE_ENDPOINT_URI = null
424
- CLIENT_CODE_ENDPOINT_URI = ${?CLIENT_CODE_ENDPOINT_URI}
425
- CLIENT_CODE_PASSWORD = null
426
- CLIENT_CODE_PASSWORD = ${?CLIENT_CODE_PASSWORD}
427
- }
@@ -1,39 +0,0 @@
1
- # Mailpit for the SMTP mail sender: a DEVELOPMENT overlay on
2
- # docker-compose.yml, for a run with MFA on (the template's default, or
3
- # MFA_MODE in .env) whose mail you can read.
4
- #
5
- # docker compose -f docker-compose.yml -f docker-compose.mailpit.yml up --build
6
- #
7
- # Write MFA_ENCRYPTION_KEY into .env first (openssl rand -base64 32): this run
8
- # reads its MFA key from it, not the development sample key.
9
- #
10
- # Mailpit keeps every mail the provider sends and delivers none; read them at
11
- # http://localhost:8025. Never use it in production, where
12
- # STANDARD_SMTP_MAIL_SENDER_* name a real relay. Leave every
13
- # STANDARD_SMTP_MAIL_SENDER_* unset in .env for this run, USER and PASSWORD
14
- # included: the overlay sets HOST, PORT, SECURE and FROM, not the credentials.
15
- #
16
- # The SMTP sender sends in plaintext (`none`) only to a loopback host, so
17
- # Mailpit shares the app container's network namespace and listens on its
18
- # localhost, and the app service publishes Mailpit's web UI. The configuration
19
- # is selected as `mailpit` (config/mailpit.conf, the development overlay
20
- # under another name), since under `development` the template installs the
21
- # sender that logs each code instead. Under that name the MFA stores may not
22
- # be kept in memory, so both are on the Redis docker-compose.yml runs.
23
-
24
- services:
25
- app:
26
- ports:
27
- - "127.0.0.1:8025:8025"
28
- environment:
29
- CONFIG_ENV: mailpit
30
- ADAPTERS_MFA_FACTOR_STORE: redis
31
- ADAPTERS_MFA_TRANSACTION_STORE: redis
32
- STANDARD_SMTP_MAIL_SENDER_HOST: localhost
33
- STANDARD_SMTP_MAIL_SENDER_PORT: "1025"
34
- STANDARD_SMTP_MAIL_SENDER_SECURE: none
35
- STANDARD_SMTP_MAIL_SENDER_FROM: auth@example.com
36
-
37
- mailpit:
38
- image: axllent/mailpit:v1.31.3
39
- network_mode: service:app