Skip to Content
ComputeAccess & Sign-in

Access & end-user sign-in

Every Ignite app has a public URL, https://<app>-<org>.ignite.dodil.cloud (copy it from public_urls in dodil ignite app get <app>). Two settings decide who may call it:

  • --allow-unauthenticated (public_invoke): whether anonymous callers get through. Owner-pays: anonymous traffic bills your org. Default false.
  • --user-pool (user_pool): an AppID  user pool, org/pool, whose people may sign in to the app. The Ignite gateway runs the login and hands your app a verified identity, so the app contains no auth code. The pool must belong to the app’s own org.

Platform principals (you, your service accounts, CI, dodil ignite invoke) can always call the app with a Dodil token. A user pool adds sign-in; it never removes platform access.

Who gets in

--user-pool--allow-unauthenticatedWho can call the app
unsetfalsePlatform principals only.
unsettrueAnyone, with no identity.
setfalseSign-in required. An anonymous browser GET is redirected to /.dodil/auth/login; any other anonymous request gets 401 with a JSON body {"error":"end-user login required","login_url":"…"}.
settrueOptional sign-in. Anonymous requests pass. When the caller has a session or presents a pool token, the identity headers are injected, and the app decides. Use this for an app with an MCP endpoint (see below).

Set it up

  1. Create the pool and invite people (see AppID → Sign-in for Ignite apps  for roles, invites, and Google/Microsoft sign-in):

    dodil appid pool create acme --display-name "Acme" --with-local dodil appid user create acme [email protected] --roles rep
  2. Attach the pool to the app:

    dodil ignite app create acme-app --user-pool <org>/acme # sign-in required dodil ignite app update acme-app --user-pool <org>/acme # on an existing app dodil ignite app update acme-app --allow-unauthenticated=true # make sign-in optional dodil ignite app update acme-app --clear-user-pool # back to platform-only

    Deploying with Git CI? Set it in .dodil/deploy.yaml:

    apps: - name: acme-app user_pool: acme # "pool" (same org) or "org/pool"; "" detaches; absent = no change public_invoke: false # applied only when the app is first created

    public_invoke in deploy.yaml takes effect only at creation. To change it later, use dodil ignite app update <app> --allow-unauthenticated=<true|false>.

  3. Allowlist the callback on the pool. The gateway signs people in with the redirect URI https://<public_url>/.dodil/auth/callback; a pool without it signs nobody in (“redirect_uri is not in the pool’s allowlist”). This is a manual step today:

    dodil appid settings get acme -o json # settings set REPLACES the object: read first dodil appid settings set acme --redirect-uris https://<public_url>/.dodil/auth/callback
  4. Verify with a real person: open the app URL in a private window, sign in as an invited user, and check that you land back in the app. dodil ignite invoke uses your platform token and skips the sign-in, so it can’t prove sign-in works.

Reserved paths

On an app with a user pool, the gateway answers these paths itself; your app never sees them:

PathWhat it does
/.dodil/auth/loginStarts sign-in (PKCE against the pool). Takes an optional return_to path.
/.dodil/auth/callbackThe pool redirects back here; the gateway sets the session cookie.
/.dodil/auth/logoutClears the session cookie, revokes the session at the pool, and redirects to /.

The session is an HttpOnly, host-only cookie, so page JavaScript never holds a token. Serve the UI and the API from one app (one host) so the cookie reaches both.

Identity headers

On every request that passes, the gateway strips any inbound copy of these headers and then sets them itself:

HeaderContents
X-Dodil-UserJSON: sub, email, connection, app_roles
X-Dodil-User-JwtThe pool access token the gateway verified. The permissions claim (and tenant, when pinned) is only here.
X-Dodil-Auth-Sourcepool (a person from the pool) or platform (a platform principal)

A client can’t forge them: the gateway removes them before setting its own. A local dev server does not, so a test that sets X-Dodil-User by hand passes even where production would refuse the request. Check once against the deployed URL.

The headers reach apps that run a container (image or Git builds). See AppID → Read the identity in your handler  for a FastAPI example.

MCP endpoints

If your app serves an MCP endpoint that people connect from Claude.ai or ChatGPT, use --user-pool with --allow-unauthenticated=true. The assistant’s first requests are anonymous discovery calls, and with sign-in required the gateway refuses them before your app can answer. Today the app itself must:

  • serve GET /.well-known/oauth-protected-resource/mcp naming the pool issuer https://appid.dodil.io/<org>/<pool>;
  • answer an unauthenticated /mcp with 401 and WWW-Authenticate: Bearer resource_metadata="<base>/.well-known/oauth-protected-resource/mcp";
  • refuse every other route that arrives without X-Dodil-User.

The full walkthrough, including client approval in AppID, is in AppID → A person connecting Claude.ai or ChatGPT .

See also