From 55d5855e8780238a39e5995d3469c8262d3b68e8 Mon Sep 17 00:00:00 2001 From: Brandon Corbett Date: Mon, 6 Jul 2026 19:38:52 -0400 Subject: [PATCH] fix: correct passwordless login copy and doc drift Fix a passwordless copy slip in the built-in Login view (it suggested resetting a password on an unexpected error; there are no passwords here). Refresh docs that had drifted from the actual client surface: - README OAuth callback example now reads the provider from sessionStorage (matching the bundled flow) instead of hardcoding "google" - README built-in routes list adds /oauth/callback - README backend expectations add the login-OTP variants and organization routes - AGENTS.md refreshes the stale public API export/type list, completes the assumed-endpoints list, and documents that the express adapter mounts /webAuthn (camelCase) with case-sensitive cookie-path matching, so client paths must stay byte-for-byte aligned with the adapter Note: an earlier revision of this branch also lowercased the client's /webAuthn paths. That was reverted: the @seamless-auth/express adapter matches cookie-requirement paths case-sensitively against camelCase keys, so changing only the client would break WebAuthn login through the adapter. The casing is instead being made robust in the server adapter. --- .changeset/login-copy-and-doc-fixes.md | 12 +++++++ AGENTS.md | 46 ++++++++++++++++---------- README.md | 17 ++++++++-- src/views/Login.tsx | 4 +-- 4 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 .changeset/login-copy-and-doc-fixes.md diff --git a/.changeset/login-copy-and-doc-fixes.md b/.changeset/login-copy-and-doc-fixes.md new file mode 100644 index 0000000..517761b --- /dev/null +++ b/.changeset/login-copy-and-doc-fixes.md @@ -0,0 +1,12 @@ +--- +'@seamless-auth/react': patch +--- + +Fix a passwordless copy slip in the built-in Login view, which previously +suggested resetting a password on an unexpected error (there are no passwords in +this system). + +Docs: correct the OAuth callback example to read the provider from +sessionStorage (matching the bundled flow) instead of hardcoding a provider, +list the `/oauth/callback` built-in route, and complete the backend endpoint +expectations (login OTP variants and organization routes). diff --git a/AGENTS.md b/AGENTS.md index eeae6a0..2ebd095 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -55,7 +55,10 @@ Important implication: ## Current Public API -Exports from `src/index.ts` currently include: +`src/index.ts` is the authoritative export list. Treat the enumeration below as a +summary and re-check `src/index.ts` before relying on it. + +Runtime exports currently include: - `AuthProvider` - `AuthRoutes` @@ -63,20 +66,20 @@ Exports from `src/index.ts` currently include: - `useAuth` - `useAuthClient` - `usePasskeySupport` +- `hasScopedRole` and `roleGrantsAccess` +- `encodePrfSalt`, `extractPasskeyPrfResult`, and `isPasskeyPrfSupported` -Exported types currently include: +Exported types currently include the provider/client input and result types plus +domain models, for example: -- `AuthContextType` -- `Credential` -- `CurrentUserResult` -- `LoginInput` -- `PasskeyLoginResult` -- `PasskeyMetadata` -- `PasskeyRegistrationResult` -- `RegisterInput` -- `SeamlessAuthClient` -- `SeamlessAuthClientOptions` -- `User` +- `AuthContextType`, `Credential`, `User`, `Organization`, `OrganizationMembership` +- `LoginInput`, `LoginMethod`, `LoginStartResult`, `RegisterInput`, `CurrentUserResult` +- `PasskeyMetadata`, `PasskeyLoginResult`, `PasskeyLoginWithPrfResult`, `PasskeyRegistrationResult`, `RegisterPasskeyOptions` +- `PasskeyPrfInput`, `PasskeyPrfResult` +- OAuth types: `OAuthProvider`, `OAuthProvidersResult`, `StartOAuthLoginInput`, `StartOAuthLoginResult`, `FinishOAuthLoginInput` +- Organization types: `CreateOrganizationInput`, `UpdateOrganizationInput`, `OrganizationMemberInput`, `OrganizationMemberUpdateInput`, `OrganizationsResult`, `OrganizationResult`, `OrganizationMembersResult` +- Step-up types: `StepUpMethod`, `StepUpStatus`, `StepUpVerificationResult`, `StepUpWithPasskeyPrfResult` +- `SeamlessAuthClient` and `SeamlessAuthClientOptions` Public API changes should be treated deliberately: @@ -124,23 +127,29 @@ Important architectural reality: The built-in flows and exported client assume these route families exist: - `/login` -- `/logout` +- `/logout` and `/logout/all` - `/registration/register` - `/webAuthn/login/start` - `/webAuthn/login/finish` - `/webAuthn/register/start` - `/webAuthn/register/finish` -- `/otp/generate-phone-otp` -- `/otp/generate-email-otp` -- `/otp/verify-phone-otp` -- `/otp/verify-email-otp` +- `/otp/generate-phone-otp`, `/otp/generate-email-otp`, and their `-login-` variants +- `/otp/verify-phone-otp`, `/otp/verify-email-otp`, and their `-login-` variants - `/magic-link` - `/magic-link/check` - `/magic-link/verify/:token` +- `/oauth/providers`, `/oauth/:providerId/start`, `/oauth/:providerId/callback` +- `/step-up/status`, `/step-up/webauthn/start`, `/step-up/webauthn/finish` +- `/organizations` and `/organizations/:organizationId` (plus `/switch` and `/members` subroutes) - `/users/me` - `/users/credentials` - `/users/delete` +The `@seamless-auth/express` adapter mounts the WebAuthn routes as `/webAuthn` +(camelCase), and its cookie middleware matches request paths case-sensitively. +Keep the client paths byte-for-byte aligned with the adapter's mounted paths; +do not "normalize" casing here in isolation. + Before documenting new flow behavior, verify the route contract in `seamless-auth-server` or `seamless-auth-api`. ## Migration Status @@ -228,3 +237,4 @@ Avoid these patterns unless the user explicitly asks for them: - leaving README or repo guidance out of sync with the actual exports - creating a second source of truth for session state outside `AuthProvider` - using em dashes (—) in public-facing text: commit messages, code comments, PR/issue descriptions, changesets, and docs. Use a comma, parentheses, or a separate sentence instead. +- adding AI or assistant attribution to commits or pull requests. Do not add `Co-Authored-By: Claude` (or any other AI/assistant) trailers, "Generated with Claude Code" lines, or similar credits. Commits and PRs are authored solely under the repository owner's identity. diff --git a/README.md b/README.md index 2e4065a..503eb38 100644 --- a/README.md +++ b/README.md @@ -323,11 +323,14 @@ function OAuthCallback() { useEffect(() => { const params = new URLSearchParams(window.location.search); - const providerId = 'google'; + // Persist the provider you passed to startOAuthLogin so the callback knows + // which provider to finish. The built-in AuthRoutes flow stores this in + // sessionStorage; use whatever your custom start flow saved. + const providerId = sessionStorage.getItem('seamless:oauth:provider'); const code = params.get('code'); const state = params.get('state'); - if (!code || !state) { + if (!providerId || !code || !state) { return; } @@ -448,6 +451,7 @@ function CustomLogin() { - `/verifyPhoneOTP` - `/verifyEmailOTP` - `/verify-magiclink` +- `/oauth/callback` - `/registerPasskey` - `/magiclinks-sent` @@ -476,6 +480,10 @@ The built-in flows assume compatible endpoints for: - `/otp/generate-email-otp` - `/otp/verify-phone-otp` - `/otp/verify-email-otp` +- `/otp/generate-login-phone-otp` +- `/otp/generate-login-email-otp` +- `/otp/verify-login-phone-otp` +- `/otp/verify-login-email-otp` - `/magic-link` - `/magic-link/check` - `/magic-link/verify/:token` @@ -488,6 +496,11 @@ The built-in flows assume compatible endpoints for: - `/users/me` - `/users/credentials` - `/users/delete` +- `/organizations` +- `/organizations/:organizationId` +- `/organizations/:organizationId/switch` +- `/organizations/:organizationId/members` +- `/organizations/:organizationId/members/:userId` ## Notes diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 2bf5f5b..750cee7 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -104,12 +104,12 @@ const Login: React.FC = () => { return; } setFormErrors( - 'An unexpected error occurred. Try again. If the problem persists, try resetting your password.' + 'An unexpected error occurred. Try again. If the problem persists, contact support.' ); } catch { console.error('Unexpected login error.'); setFormErrors( - 'An unexpected error occurred. Try again. If the problem persists, try resetting your password.' + 'An unexpected error occurred. Try again. If the problem persists, contact support.' ); } };