Unverified 提交 4f96b55b authored 作者: Mohamed Aziz Mejri's avatar Mohamed Aziz Mejri 提交者: GitHub

Adding password reset guide (#3254)

<!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/3254" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open in Devin Review"> </picture> </a> <!-- devin-review-badge-end -->
上级 7ca82352
{
"name": "dyad",
"version": "0.43.0",
"version": "0.44.0-beta.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dyad",
"version": "0.43.0",
"version": "0.44.0-beta.1",
"license": "MIT",
"dependencies": {
"@ai-sdk/amazon-bedrock": "^4.0.46",
......
......@@ -4,6 +4,7 @@ import { DyadError, DyadErrorKind } from "@/errors/dyad_error";
import addAuthentication from "@/prompts/guides/add-authentication.md?raw";
import addEmailVerification from "@/prompts/guides/add-email-verification.md?raw";
import addPasswordReset from "@/prompts/guides/add-password-reset.md?raw";
/**
* Registry of available guides. To add a new guide, import its .md file
......@@ -12,13 +13,14 @@ import addEmailVerification from "@/prompts/guides/add-email-verification.md?raw
const GUIDES: Record<string, string> = {
"add-authentication": addAuthentication,
"add-email-verification": addEmailVerification,
"add-password-reset": addPasswordReset,
};
const readGuideSchema = z.object({
guide: z
.string()
.describe(
"Name of the guide to read (e.g. 'add-authentication', 'add-email-verification')",
"Name of the guide to read (e.g. 'add-authentication', 'add-email-verification', 'add-password-reset')",
),
});
......
## Password Reset
Neon Auth supports a built-in password reset flow. A user requests a reset link, Neon Auth emails them a verification link containing a reset token, the user clicks the link and lands on a reset page in your app, and the new password is set.
<critical-rules>
- **must-not-implement-custom-token-flow**: Do NOT implement your own password reset token generation, storage, or verification. Neon Auth manages the token lifecycle. The SDK's low-level password-reset methods (e.g. `resetPasswordForEmail`) are NOT fully supported yet — you MUST use the provided UI components (`AuthView` with `credentials={{ forgotPassword: true }}`, or the standalone `ForgotPasswordForm` / `ResetPasswordForm`).
- **must-route-reset-link-to-app**: The reset link in the email MUST point back to a page in your app that renders `ResetPasswordForm` (or `AuthView` with the forgot-password flow enabled). Without this page, the user clicks the email link and hits a dead route. Wire up the `redirectTo` / reset-password route before shipping.
- **must-style-reset-pages**: The forgot-password and reset-password pages MUST be styled to match the app (same rules as the sign-in / sign-up pages). Do NOT leave them with default or unstyled appearance.
</critical-rules>
### How It Works
1. User clicks "Forgot password?" and submits their email on the forgot-password page.
2. Neon Auth sends a password-reset email containing a link to your app's reset-password page. The link includes a short-lived reset token.
3. User clicks the link and lands on the reset-password page in your app.
4. User enters a new password; the form exchanges the token for a password update.
5. The password is updated. The user is then signed in or sent to the sign-in page.
**Reset tokens expire after 15 minutes.** If the link expires, the user must request a new one.
### Option A (Recommended): Enable Forgot-Password on `AuthView`
The simplest integration — `AuthView` already renders the sign-in UI; enabling `credentials.forgotPassword` adds the "Forgot password?" link and the full request/reset flow with no extra routes on your side beyond the reset-password page.
<code-template label="authview-with-forgot-password" file="app/auth/[path]/page.tsx" language="tsx">
import { AuthView } from '@neondatabase/auth/react';
import './auth.css';
export const dynamicParams = false;
export default async function AuthPage({
params,
}: {
params: Promise<{ path: string }>;
}) {
const { path } = await params;
return (
<AuthView
path={path}
credentials={{ forgotPassword: true }}
/>
);
}
</code-template>
With the `[path]` catch-all already in place from the base auth setup, `AuthView` handles both the `/auth/forgot-password` and `/auth/reset-password` routes automatically.
### Option B: Custom Pages with `ForgotPasswordForm` and `ResetPasswordForm`
Use this when you need custom layouts, copy, or branding on the reset pages beyond what `AuthView` exposes. The standalone components still own the token exchange — you only own the page shell.
<code-template label="forgot-password-page" file="app/auth/forgot-password/page.tsx" language="tsx">
'use client';
import { ForgotPasswordForm } from '@neondatabase/auth/react';
import { authClient } from '@/lib/auth/client';
import { useRouter } from 'next/navigation';
export default function ForgotPasswordPage() {
const router = useRouter();
return (
<div>
<h1>Reset your password</h1>
<p>Enter your email and we'll send you a link to reset your password.</p>
<ForgotPasswordForm
authClient={authClient}
redirectTo={`${typeof window !== 'undefined' ? window.location.origin : ''}/auth/reset-password`}
onSuccess={() => {
router.push('/auth/forgot-password/sent');
}}
/>
</div>
);
}
</code-template>
<code-template label="reset-password-page" file="app/auth/reset-password/page.tsx" language="tsx">
'use client';
import { ResetPasswordForm } from '@neondatabase/auth/react';
import { authClient } from '@/lib/auth/client';
import { useRouter } from 'next/navigation';
export default function ResetPasswordPage() {
const router = useRouter();
return (
<div>
<h1>Choose a new password</h1>
<ResetPasswordForm
authClient={authClient}
onSuccess={() => {
router.push('/auth/sign-in');
}}
/>
</div>
);
}
</code-template>
### Component Props
- **`ForgotPasswordForm`**
- `authClient` — the shared `authClient` instance from `@/lib/auth/client`.
- `redirectTo` — absolute URL of the reset-password page in your app. This is the link the user clicks in their email; it must be a real, unauthenticated route.
- `onSuccess` — fires after the reset email is sent. Use this to show a "Check your inbox" confirmation.
- **`ResetPasswordForm`**
- `authClient` — the shared `authClient` instance.
- `onSuccess` — fires after the password is successfully updated. Use this to redirect to sign-in (or to the app if the user is auto-signed-in).
### Important Notes
- The reset-password page MUST be reachable without authentication — the user is not signed in when they click the email link.
- Reset tokens expire after **15 minutes**. Surface a clear "request a new link" affordance on the reset-password page in case the user arrives with an expired token.
- Do NOT call `authClient.resetPasswordForEmail` or other low-level password-reset SDK methods directly — they are not fully supported. Use the UI components above.
- Password reset requires email/password sign-up to be enabled on the Neon Auth project. If it is not, the forgot-password link will not appear.
import addAuthenticationGuide from "./guides/add-authentication.md?raw";
import addEmailVerificationGuide from "./guides/add-email-verification.md?raw";
import addPasswordResetGuide from "./guides/add-password-reset.md?raw";
export function getNeonAvailableSystemPrompt(
neonClientCode: string,
......@@ -43,11 +44,14 @@ function getSharedNeonPrompt(
? `## Auth (detailed guide available)
When the task involves authentication, login, sign-up, user sessions, or auth UI, you MUST call the \`read_guide\` tool with guide="add-authentication" BEFORE writing any auth code. Do NOT implement auth without reading the guide first.
${emailVerificationEnabled ? `\n**IMPORTANT:** Email verification is enabled. After reading the auth guide and BEFORE writing any sign-up code, you MUST also call \`read_guide\` with guide="add-email-verification".` : ""}`
${emailVerificationEnabled ? `\n**IMPORTANT:** Email verification is enabled. After reading the auth guide and BEFORE writing any sign-up code, you MUST also call \`read_guide\` with guide="add-email-verification".` : ""}
**IMPORTANT:** If the task involves password reset, forgot-password, or "reset my password" flows, you MUST call \`read_guide\` with guide="add-password-reset" BEFORE writing any password-reset code. Do NOT hand-roll a reset-token flow.`
: `## Auth
${addAuthenticationGuide}
${emailVerificationEnabled ? `\n${addEmailVerificationGuide}` : ""}`;
${emailVerificationEnabled ? `\n${addEmailVerificationGuide}` : ""}
${addPasswordResetGuide}`;
return `
<neon-system-prompt>
......@@ -128,9 +132,11 @@ function getNextJsNeonPrompt(
const authDecisionSteps = isLocalAgentMode
? `4. **If** user needs auth APIs or sessions → call \`read_guide\` with guide="add-authentication"${emailVerificationEnabled ? `, then call \`read_guide\` with guide="add-email-verification"` : ""}, then follow the Neon Auth API path.
5. **If** user wants prebuilt auth or account pages → call \`read_guide\` with guide="add-authentication"${emailVerificationEnabled ? `, then call \`read_guide\` with guide="add-email-verification"` : ""}, then extend with the UI path.`
5. **If** user wants prebuilt auth or account pages → call \`read_guide\` with guide="add-authentication"${emailVerificationEnabled ? `, then call \`read_guide\` with guide="add-email-verification"` : ""}, then extend with the UI path.
6. **If** user wants password reset or forgot-password → call \`read_guide\` with guide="add-password-reset", then wire up the reset flow per that guide.`
: `4. **If** user needs auth APIs or sessions → follow the Auth guide above${emailVerificationEnabled ? " and the Email Verification guide" : ""}, then follow the Neon Auth API path.
5. **If** user wants prebuilt auth or account pages → follow the Auth guide above${emailVerificationEnabled ? " and the Email Verification guide" : ""}, then extend with the UI path.`;
5. **If** user wants prebuilt auth or account pages → follow the Auth guide above${emailVerificationEnabled ? " and the Email Verification guide" : ""}, then extend with the UI path.
6. **If** user wants password reset or forgot-password → follow the Password Reset guide above, then wire up the reset flow per that guide.`;
return `
<nextjs-instructions>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论