mirror of
https://github.com/moeru-ai/airi.git
synced 2026-08-14 08:52:42 +00:00
## Summary Adds a self-contained better-auth plugin (`server/apps/api/src/libs/auth-plugins/steam.ts`) implementing Steam OpenID 2.0 sign-in, account linking, and callback verification via "dumb mode". Steam's web login is OpenID 2.0, not OAuth2/OIDC, so it cannot be registered as a `socialProviders` entry, and better-auth has no plugin hook for extending its OAuth2 endpoints with a non-OAuth2 protocol. The plugin therefore adds the endpoints Steam's protocol needs: `POST /sign-in/steam`, `POST /link/steam`, and `GET /steam/callback`. - Callback verification uses OpenID "dumb mode" (`openid.mode=check_authentication`): one extra round trip to Steam instead of managing RSA association state. - New sign-ups get a placeholder `<steamid64>@steam.placeholder.local` with `emailVerified: true`, mirroring Apple Sign In's `<sub>@apple.placeholder.local`. - The plugin's request/query schemas use Zod; a `// NOTICE:` documents that better-auth's OpenAPI generator is Zod-native. Steam verification uses `ofetch`. - Wires Steam into `apps/ui-server-auth` sign-in and profile "Connected accounts", plus the shared `OAuthProvider` / `defaultSignInProviders` in `packages/stage-ui`. - Linking routes through `/link/steam` via the client's `$fetch`; unlinking needs no special-casing (`/unlink-account` already takes a free-form `providerId`). No Steam Web API key is required for this browser-based flow. We intentionally do not depend on community Steam packages (e.g. `better-auth-steam`) or the still-open upstream draft ([better-auth#4877](https://github.com/better-auth/better-auth/pull/4877)). Steam never returns an email, and we need sign-up that does not ask the user for one plus first-class account linking; the available options either require an email at sign-in, lack linking, or are abandoned / blocked — shipping a small in-tree plugin is the safer auth dependency for this requirement. ## Test plan - [x] `pnpm exec vitest run server/apps/api/src/libs/auth-plugins/steam.test.ts` — 6/6 passing - [x] `pnpm -F @proj-airi/ui-server-auth exec vitest run` — 32/32 passing - [x] `pnpm -F @proj-airi/stage-ui exec vitest run src/libs/steam-auth-client.test.ts src/composables/use-linked-accounts.test.ts` — 5/5 passing - [x] `pnpm -F @proj-airi/api-server typecheck` - [x] `pnpm -F @proj-airi/ui-server-auth typecheck` - [x] `pnpm -F @proj-airi/stage-ui typecheck` ## Follow-ups - Desktop Steam ticket sign-in (top of this stack): silent startup ticket exchange for Steam builds; the server resolves or creates the AIRI user for the verified SteamID before issuing an OIDC code. - Steam persona name/avatar via `GetPlayerSummaries` inside the plugin, if display names beyond `Steam User <id>` are wanted. --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>