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.' ); } };