-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdocker-compose.verify.yml
More file actions
192 lines (186 loc) · 7.95 KB
/
Copy pathdocker-compose.verify.yml
File metadata and controls
192 lines (186 loc) · 7.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# Conformance stack for `seamless verify`.
# Brings up Postgres + the auth API + the Express adapter from local source
# (paths supplied by the verify command via env) so the Playwright harness can
# drive every auth flow. NODE_ENV=test enables the API's external-delivery seam
# so OTP / magic-link tokens are returned in responses (no real email/SMS).
#
# Required env (the `seamless verify` command writes these into .env.verify):
# SEAMLESS_API_DIR absolute path to seamless-auth-api source
# SEAMLESS_ADAPTER_DIR absolute path to the express adapter source
# API_SERVICE_TOKEN shared secret between API and adapter
# JWKS_KID key id the adapter expects (must match the API's active kid)
# OWNER_EMAIL tenant owner; this email gets the admin role at signup
name: seamless-verify
services:
postgres:
# Matches POSTGRES_IMAGE in src/core/images.ts, so the harness runs the same
# major a fresh scaffold gets. Every run starts with `down -v`, so the volume
# is always new and a major bump needs no migration here.
image: postgres:18
environment:
POSTGRES_USER: seamless
POSTGRES_PASSWORD: seamless
POSTGRES_DB: seamless_auth
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U seamless -d seamless_auth']
interval: 3s
timeout: 3s
retries: 20
auth-api:
# Built with the production Dockerfile (compiles dist/), but run with
# NODE_ENV=test so signing keys auto-generate and prod-only env (JWKS keys)
# is skipped. validateEnvs.sh gates startup on the env below.
build:
context: ${SEAMLESS_API_DIR}
dockerfile: Dockerfile
ports:
- '5312:5312'
environment:
# `development` (not `test`): the API's JWKS endpoint only serves the
# auto-generated dev public key when NODE_ENV === 'development', even though
# signing treats any non-production env as dev. Running as development keeps
# JWKS publication working so the adapter/SDKs can verify tokens.
NODE_ENV: development
PORT: '5312'
APP_NAME: Seamless Verify
APP_ID: seamless-verify
APP_ORIGINS: http://localhost:3000,http://localhost:5173
# Must equal the adapter's AUTH_SERVER_URL: the adapter validates the `iss`
# claim on API-signed tokens against the URL it reaches the API on.
ISSUER: http://auth-api:5312
DEFAULT_ROLES: user
AVAILABLE_ROLES: user,admin
LOGIN_METHODS: passkey,magic_link,email_otp,phone_otp,oauth
# Required system config as of auth-api 0.3.0: the base URL for emailed
# magic links. Without it (and with a fresh DB, so system_config isn't seeded)
# the server exits at startup. The browser-visible web app runs on 5173.
FRONTEND_URL: http://localhost:5173
DB_LOGGING: 'false'
ACCESS_TOKEN_TTL: 15m
REFRESH_TOKEN_TTL: 1h
RATE_LIMIT: '100000'
DELAY_AFTER: '100000'
# The dedicated per-IP OTP/magic-link/registration/OAuth limiters are not
# tuned by RATE_LIMIT; the suite drives many flows from one IP and would trip
# them. This dev-only flag skips them (ignored under NODE_ENV=production).
DISABLE_AUTH_RATE_LIMITS: 'true'
RPID: localhost
ORIGINS: http://localhost:5173,http://localhost:3000
DB_HOST: postgres
DB_PORT: '5432'
DB_USER: seamless
DB_PASSWORD: seamless
DB_NAME: seamless_auth
API_SERVICE_TOKEN: ${API_SERVICE_TOKEN}
# The first admin comes from the OWNER_EMAIL grant at signup, so the
# harness can assert admin promotion without a separate invite flow.
OWNER_EMAIL: ${OWNER_EMAIL}
# OAuth: a single "mock" provider backed by the harness's in-process OIDC.
# authorizationUrl is browser/harness-visible (localhost); token/userInfo are
# called server-side from the container, so they go via host.docker.internal.
MOCK_CLIENT_SECRET: mock-secret
OAUTH_PROVIDERS: '[{"id":"mock","name":"Mock OIDC","enabled":true,"clientId":"mock-client","clientSecretEnv":"MOCK_CLIENT_SECRET","authorizationUrl":"http://localhost:9000/authorize","tokenUrl":"http://host.docker.internal:9000/token","userInfoUrl":"http://host.docker.internal:9000/userinfo","scopes":["openid","email"],"redirectUri":"http://localhost:5173/oauth/callback","redirectUris":["http://localhost:5173/oauth/callback"],"allowSignup":true,"accountLinking":"email"}]'
extra_hosts:
- 'host.docker.internal:host-gateway'
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: ['CMD', 'node', 'dist/healthCheck.js']
interval: 3s
timeout: 5s
retries: 40
# Harness-owned adopter backend: real @seamless-auth/express with a capture
# transport so the harness can read OTP/magic-link codes the adapter would
# otherwise strip. ISSUER on auth-api is set to this AUTH_SERVER_URL host.
adapter:
build:
context: ./adapter-app
ports:
- '3000:3000'
environment:
PORT: '3000'
AUTH_SERVER_URL: http://auth-api:5312
APP_ORIGIN: http://localhost:3000
# Browser origin allowed by CORS (the React app, served below).
WEB_ORIGIN: http://localhost:5173
API_SERVICE_TOKEN: ${API_SERVICE_TOKEN}
COOKIE_SIGNING_KEY: ${API_SERVICE_TOKEN}
JWKS_KID: ${JWKS_KID}
depends_on:
auth-api:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-fsS', 'http://localhost:3000/']
interval: 3s
timeout: 3s
retries: 20
# The same adopter backend on Fastify, so the cookie path is conformance-tested
# for both adapters rather than only the one the harness happens to be written
# against. Identical env contract and capture transport; only the framework and
# the published port differ, which is what makes a failure here attributable.
adapter-fastify:
build:
context: ./adapter-fastify-app
ports:
- '3001:3001'
environment:
PORT: '3001'
AUTH_SERVER_URL: http://auth-api:5312
APP_ORIGIN: http://localhost:3001
WEB_ORIGIN: http://localhost:5173
API_SERVICE_TOKEN: ${API_SERVICE_TOKEN}
COOKIE_SIGNING_KEY: ${API_SERVICE_TOKEN}
JWKS_KID: ${JWKS_KID}
depends_on:
auth-api:
condition: service_healthy
healthcheck:
test: ['CMD', 'curl', '-fsS', 'http://localhost:3001/']
interval: 3s
timeout: 3s
retries: 20
# React starter app (built SPA on nginx), pointed at the adapter so the React
# SDK's `${apiHost}/auth/*` calls hit the adapter's mount. Browser-visible URL,
# so API_URL is the host-mapped adapter (localhost:3000), not the compose host.
# Gated behind the `react` profile so the api/adapter-only runs skip the build.
#
# The inline Dockerfile mirrors the starter's own Dockerfile, but additionally
# installs a locally-built @seamless-auth/react tarball when present (--local
# mode packs it into ./react-vendor; that dir is empty otherwise → published SDK).
react:
profiles: ['react']
build:
context: ${SEAMLESS_REACT_DIR}
additional_contexts:
sdk: ./react-vendor
dockerfile_inline: |
FROM node:24-slim AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
COPY --from=sdk . /tmp/sdk/
RUN if ls /tmp/sdk/seamless-auth-react-*.tgz >/dev/null 2>&1; then \
npm install /tmp/sdk/seamless-auth-react-*.tgz; \
fi
RUN npm run build
FROM nginx:alpine
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 80
CMD ["/entrypoint.sh"]
ports:
- '5173:80'
environment:
API_URL: http://localhost:3000
depends_on:
adapter:
condition: service_healthy
healthcheck:
test: ['CMD', 'wget', '--no-verbose', '--tries=1', '--spider', 'http://localhost/health']
interval: 3s
timeout: 3s
retries: 20