feat(examples): add Multiple Custom Domains (MCD) web example#80
feat(examples): add Multiple Custom Domains (MCD) web example#80frederikprijck wants to merge 1 commit into
Conversation
|
Warning Review limit reached
Next review available in: 34 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
📝 WalkthroughWalkthroughA new ChangesFastify MCD Example
Sequence Diagram(s)sequenceDiagram
participant Browser
participant FastifyServer
participant resolveAuth0Domain
participant fastifyAuth0Plugin
participant Auth0Tenant
Browser->>FastifyServer: GET /auth/login (Host: app-tenant1.localhost)
FastifyServer->>resolveAuth0Domain: hostname = "app-tenant1.localhost"
resolveAuth0Domain-->>FastifyServer: AUTH0_CUSTOM_DOMAIN_1
FastifyServer->>fastifyAuth0Plugin: DomainResolver returns AUTH0_CUSTOM_DOMAIN_1
fastifyAuth0Plugin->>Auth0Tenant: fetch OIDC discovery for AUTH0_CUSTOM_DOMAIN_1
Auth0Tenant-->>fastifyAuth0Plugin: discovery document
fastifyAuth0Plugin-->>FastifyServer: 302 Location → AUTH0_CUSTOM_DOMAIN_1/authorize?redirect_uri=http://app-tenant1.localhost/...
FastifyServer-->>Browser: 302 redirect to AUTH0_CUSTOM_DOMAIN_1
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (1)
examples/example-fastify-web-mcd/src/index.spec.ts (1)
80-92: ⚡ Quick winAdd a host-without-port regression test.
Current suite misses the common
Host: tenant-1.localhostpath; adding it would lock in resolver behavior across proxy/header variations.Suggested test addition
+ test('login from tenant-1 host without explicit port still resolves tenant-1 domain', async () => { + const res = await fastify.inject({ + method: 'GET', + url: '/auth/login', + headers: { host: 'tenant-1.localhost' }, + }); + const location = new URL(res.headers['location']?.toString() ?? ''); + + expect(res.statusCode).toBe(302); + expect(location.host).toBe(TENANT_1_DOMAIN); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/example-fastify-web-mcd/src/index.spec.ts` around lines 80 - 92, Add a new regression test after the existing 'login from an unmapped host falls back to the default domain' test to cover the case where the Host header does not include a port. Create a test similar to the existing one but use a host header value like 'unknown.localhost' (without the port number :3000) in the fastify.inject call, and verify it still falls back to the DEFAULT_DOMAIN and behaves consistently. This ensures the host resolver handles both host-with-port and host-without-port variations correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/examples.yml:
- Around line 24-25: The actions/checkout action in the checkout code step is
persisting credentials unnecessarily, increasing token exposure risk. Add the
persist-credentials parameter set to false to the actions/checkout action
configuration. Since this workflow only performs read operations and does not
push or write any changes, credential persistence is not needed and should be
explicitly disabled to follow security best practices.
In `@examples/example-fastify-web-mcd/package.json`:
- Line 21: The `@auth0/auth0-fastify` dependency in package.json is pinned to an
unsafe wildcard version (*) which prevents reproducible builds and can introduce
breaking changes. Replace the wildcard version with a specific pinned version
using the caret syntax (^1.3.0) to lock the dependency to a known stable release
while allowing compatible patch updates. This ensures consistent builds across
different environments and time periods.
In `@examples/example-fastify-web-mcd/README.md`:
- Around line 19-22: The code fence for the hosts file entries (127.0.0.1
tenant-1.localhost and 127.0.0.1 tenant-2.localhost) is missing a language
identifier, which causes markdown linting to fail. Change the opening code fence
from triple backticks with no language to triple backticks followed by `text` to
properly specify the content type and satisfy markdown linting requirements.
In `@examples/example-fastify-web-mcd/src/index.ts`:
- Line 95: The reply.redirect call on line 95 embeds the raw request.url
directly into the returnTo query parameter without URL encoding, which allows
special characters like ampersands and equals signs to break the query string
syntax. Wrap the request.url value with encodeURIComponent() to properly encode
it before interpolating it into the redirect URL string.
- Around line 37-53: The environment variable assignments for
defaultAuth0Domain, AUTH0_CUSTOM_DOMAIN_1, and AUTH0_CUSTOM_DOMAIN_2 use `as
string` type assertions which only silence TypeScript but do not validate the
values at runtime. Add explicit validation checks to ensure each of these
required environment variables is actually defined before using them, and throw
an error immediately if any are missing. This prevents undefined values from
propagating into the domainsByHost map and resolveAuth0Domain function, which
would cause harder-to-debug failures later.
- Around line 38-53: The resolveAuth0Domain function performs an exact match
lookup of the host parameter against the domainsByHost map, but incoming Host
headers from proxies may omit the port or have inconsistent formatting, causing
the lookup to fail and silently fall back to the default domain. Normalize the
host parameter before the lookup against domainsByHost to handle cases where the
port may or may not be present in the Host header, ensuring consistent
resolution of the correct Auth0 custom domain for multi-tenant setups.
In `@examples/example-fastify-web-mcd/views/layout.ejs`:
- Line 45: The "Log out" link on line 45 uses unescaped EJS output syntax (<%-
... %>) when rendering locals.user.name, which creates an XSS vulnerability if
the user name contains malicious content. Replace the unescaped output syntax
<%- ... %> with the escaped output syntax <%= ... %> for the expression
containing locals.user.name to ensure user-controlled data is properly escaped
before being rendered in the HTML.
---
Nitpick comments:
In `@examples/example-fastify-web-mcd/src/index.spec.ts`:
- Around line 80-92: Add a new regression test after the existing 'login from an
unmapped host falls back to the default domain' test to cover the case where the
Host header does not include a port. Create a test similar to the existing one
but use a host header value like 'unknown.localhost' (without the port number
:3000) in the fastify.inject call, and verify it still falls back to the
DEFAULT_DOMAIN and behaves consistently. This ensures the host resolver handles
both host-with-port and host-without-port variations correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1848e135-4d7f-4603-890c-46222ea6dee5
⛔ Files ignored due to path filters (1)
examples/example-fastify-web-mcd/public/img/auth0.pngis excluded by!**/*.png
📒 Files selected for processing (12)
.github/workflows/examples.ymlREADME.mdexamples/example-fastify-web-mcd/.env.exampleexamples/example-fastify-web-mcd/README.mdexamples/example-fastify-web-mcd/package.jsonexamples/example-fastify-web-mcd/src/index.spec.tsexamples/example-fastify-web-mcd/src/index.tsexamples/example-fastify-web-mcd/tsconfig.jsonexamples/example-fastify-web-mcd/views/index.ejsexamples/example-fastify-web-mcd/views/layout.ejsexamples/example-fastify-web-mcd/views/private.ejsexamples/example-fastify-web-mcd/views/public.ejs
645ffa9 to
0024d6f
Compare
Adds example-fastify-web-mcd, demonstrating MCD support in @auth0/auth0-fastify via a per-request domain resolver. A single app serves two hostnames (brand-a.localhost and brand-b.localhost) mapped to different Auth0 custom domains of the same tenant, with the app base URL inferred per request in resolver mode. Includes a vitest spec (msw + fastify.inject) covering per-host domain resolution and default-domain fallback, a Build and Test Examples workflow, and a link from the root README.
0024d6f to
ec81908
Compare
Description
Adds a Multiple Custom Domains (MCD) example for
@auth0/auth0-fastify.A single Fastify app serves two hostnames —
brand-a.localhostandbrand-b.localhost— on one port, each mapped to a different Auth0 custom domain of the same Auth0 tenant (custom domains that resolve to one underlying tenant at the DNS level). It uses a single plugin registration configured with a domain resolver function instead of a staticdomainstring.What's included
examples/example-fastify-web-mcd/— runnable example:src/index.ts(host → custom-domain resolver, per-domaindiscoveryCache), EJS views showing the serving host + resolved Auth0 domain, README, and.env.example.src/index.spec.ts(vitest + msw +fastify.inject, matching the SDK's own test conventions) covering per-host domain resolution and default-domain fallback. 3/3 passing.Multiple Custom Domainsjob to.github/workflows/examples.yml(build +test:ci), alongside the existing web and api example jobs.README.md— links the new example.Testing
npm run build -w @auth0/auth0-fastify✅npm run build -w example-fastify-web-mcd✅npm run test:ci -w example-fastify-web-mcd✅ (3 tests)Security
The example and README document the MCD security requirements: the resolver must only ever return trusted custom domains of your tenant, and the app must run behind a reverse proxy that sanitizes
Host/X-Forwarded-Host.Summary by CodeRabbit
New Features
Documentation
Tests & CI