Browse docs All docs
Docs / Add Auth0 authentication to your app
Guidedeploymill://guides/auth/auth0

Add Auth0 authentication to your app

You are an agent wiring Auth0 as the external identity provider for end-user login / accounts in a DeployMill-managed app. Read this together with the general deploymill://guides/auth reference (the four platform facts about auth on DeployMill still apply) and deploymill://guides/secrets (the secret hand-off).

DeployMill operates nothing here

This is bring-your-own auth. DeployMill does not run a user store, a login UI, or any token validation for you. What it does is small and explicit:

  • It records your choice in the auth block of .deploymill/project.json (provider-neutral config).
  • It hands off the Auth0 secret values the normal way (set_env_vars / request_secret) so the agent never sees them.
  • On reconcile_project it runs a read-only presence-check that the expected env-var names are set on the app, and emits a typed auth_secret_missing hint (with this guide's URI) when they are not. It reads key names only, never the values.

Auth0 holds your users, sessions, and login pages. Your app talks to Auth0 with its SDK.

The env-var contract

Auth0 needs these env vars on the app:

  • AUTH0_DOMAIN: your tenant domain (e.g. your-tenant.us.auth0.com). Not secret.
  • AUTH0_CLIENT_ID: not secret, safe to set_env_vars.
  • AUTH0_CLIENT_SECRET: secret. Push it through the vault / hand-off, never into a transcript.

These are the exact names the reconcile presence-check looks for. If any is missing, reconcile_project returns applied.auth.hint === "auth_secret_missing" with the missing name(s) in applied.auth.missingEnvKeys and a pointer to this guide.

The secret hand-off (agent never sees values)

  1. request_secret({ name: "AUTH0_CLIENT_SECRET" }) → hand the returned link to the user → poll secret_request_statusbind_secret({ applicationId, name: "AUTH0_CLIENT_SECRET" }) (or declare it under secrets in project.json and reconcile). The value is resolved server-side. It never appears in chat.
  2. set_env_vars({ applicationId, vars: { AUTH0_DOMAIN: "your-tenant.us.auth0.com", AUTH0_CLIENT_ID: "…" } }). These are not secret.

Register the app's prod host and every preview host in Auth0's allowed callback URLs. See deploymill://guides/secrets for the full vault flow and deploymill://guides/previews for per-preview wiring.

App-side SDK snippet

A minimal Express/Node sketch using express-openid-connect:

import { auth } from "express-openid-connect";

app.use(
  auth({
    issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}`,
    clientID: process.env.AUTH0_CLIENT_ID,
    clientSecret: process.env.AUTH0_CLIENT_SECRET,
    baseURL: process.env.APP_BASE_URL, // host-pinned per environment (see the auth guide)
    secret: process.env.SESSION_SECRET,
    authRequired: false,
  })
);

app.get("/me", (req, res) => res.json({ user: req.oidc.user ?? null }));

(Use the matching Auth0 SDK for your framework. The env-var names are the same.)

The auth project.json block

Declare the provider so reconcile records it and runs the presence-check:

{
  "version": 2,
  "auth": { "provider": "auth0", "audience": "users" }
}

audience is optional and only "users" today (end-user login). Then reconcile_project. If the keys are wired you get applied.auth.hint === null. If not, fix the missing names it reports and reconcile again.