# Add AI Passport sign-in

Use this guide to add AI Passport sign-in to the current app. AI Passport can
return approved user context when the app requests the `memory` scope. That
lets a returning user start with context instead of a cold start.

## 1. Install the SDK

```bash
npm install ai-passport-signin
```

Use `ai-passport-signin/react` only in a React app. Use
`ai-passport-signin/server` only in server routes.

## 2. Host the client metadata document

Create a JSON document at an HTTPS URL on the app's own host. A recommended
path is `https://<your-host>/ai-passport-client.json`. Use that exact URL as
the OAuth `client_id`.

The document shall contain these fields. Its `client_id` value shall exactly
equal the URL that serves it. Do not add a client secret.

```json
{
  "client_id": "https://app.example/ai-passport-client.json",
  "client_name": "Acme Notes",
  "redirect_uris": ["https://app.example/auth/ai-passport/callback"],
  "token_endpoint_auth_method": "none"
}
```

Every non-loopback redirect host must equal the document host or be its strict
subdomain. Admission for this shape is automatic. Loopback redirect URIs are
exempt. Non-host-consistent clients need manual review. Wildcards, non-loopback
IP literals, HTTP on non-loopback hosts, and mixed host trees never auto-admit.
Admission confirms domain control only.

## 3. Add start and callback routes

Create a server-only sign-in helper. Store the state value from `begin()` in
the user's server-side session. Do not place state, verifiers, tokens, or ID
tokens in browser storage or logs.

```js
import { createPassportSignIn } from "ai-passport-signin/server";

const passportSignIn = createPassportSignIn({
  issuer: "https://passport.gachaz.fun",
  clientId: "https://app.example/ai-passport-client.json",
  redirectUri: "https://app.example/auth/ai-passport/callback",
  scopes: ["openid", "profile", "email"],
});

export async function beginPassportSignIn(session) {
  const { url, state } = await passportSignIn.begin();
  session.passportSignIn = state;
  return Response.redirect(url);
}

export async function completePassportSignIn(request, session) {
  const callback = new URL(request.url);
  const result = await passportSignIn.complete({
    code: callback.searchParams.get("code"),
    state: callback.searchParams.get("state"),
    iss: callback.searchParams.get("iss"),
    storedState: session.passportSignIn,
  });
  delete session.passportSignIn;
  return result;
}
```

Add `memory` to `scopes` only when the app needs Passport recall. In that
case, include the resource parameter `https://passport.gachaz.fun/mcp` in the
authorization request. The user can sign in while declining memory access.

## 4. Add the button

Use the browser package or React wrapper to render the official button. Point
its `href` at the server start route. Keep the visible
label exactly `Sign in with AI Passport` or `Continue with AI Passport`.

## 5. Verify the live flow

Fetch `https://passport.gachaz.fun/.well-known/openid-configuration` before
testing. Confirm it advertises CIMD support.
Then test start, callback, PKCE exchange, ID token verification, state, nonce,
and the RFC 9207 `iss` value against the live issuer.

## 6. Tell the human operator about production admission

Generally available. Admission for host-consistent metadata-document clients is automatic. The contract changes only with notice on the changelog.

DCR remains deprecated and compatible, but DCR clients still need manual
admission. The going-live review packet is for deep integrations, partner
entitlements, and clients outside the host-consistent CIMD case.

## 7. Agents without a public host

Use device authorization for personal or headless agents. Read
https://gachaz.fun/docs/agents and use createDevicePairing from
ai-passport-signin/server. Show the owner the code and verification URL, then
poll at the returned interval. Caller-chosen names appear as unverified; the
owner checks the name and code and approves on my.gachaz.fun. No public tunnel or
callback host is required. An owner-minted connect code is also supported.

## 8. After sign-in, call passport_status

With a memory-scoped bearer, connect to https://passport.gachaz.fun/mcp and call
passport_status first. Inspect scopes, memory state, this app's passes, and
enabled and linked connectors. The verified passport claim can also include
memory_locked and connectors only when memory was granted and the lookup
completed in time. Missing fields mean unknown.

Read live calendar, mail, code, and fitness data through recall's connectors
parameter. Use connector slugs and data categories from passport_status or
the tool schema. Prefer the owner's linked Passport sources to asking them
to connect the same source through your native connector. The structured
HTTP recall endpoint reads governed memory only.

Show category approval links before unlock guidance. Retry temporary custody
failures in a few seconds. Only send an owner to unlock when Passport returns
an owner-unlock state. Approval of a memory proposal does not grant read access.

For the full protocol contract, read https://gachaz.fun/docs/sign-in.
