Skip to main content
Urbicon UI
Back to Recipes

Password Reset Flow

The two-page forgot/reset flow: request a link, then set a new password from the emailed token.

Live Preview

Forgot password

Enter your email address and we will send you a link to reset your password.

Back to sign in

Key Features

  • ForgotPasswordPage requests a reset link by email
  • Timing-safe and enumeration-safe — always the same fire-and-forget response
  • ResetPasswordPage consumes the token and sets a new password
  • Reset token claimed atomically (consumeResetToken) so one link is single-use
  • All sessions invalidated on a successful reset
  • onPasswordResetFailed hook surfaces a broken mail transport

Code

Password Reset Flow — full flow

// 1. src/routes/api/auth/forgot-password/+server.ts — request a reset link
import { createForgotPasswordHandler } from '@urbicon-ui/auth/server';
import { authDeps } from '$lib/server/auth-setup';
export const { POST } = createForgotPasswordHandler(authDeps);

// 2. src/routes/api/auth/reset-password/+server.ts — consume the token
import { createResetPasswordHandler } from '@urbicon-ui/auth/server';
import { authDeps } from '$lib/server/auth-setup';
export const { POST } = createResetPasswordHandler(authDeps);

// 3. Observe delivery failures. forgot-password is fire-and-forget (so response
//    time can't reveal whether the account exists), so a broken mail transport
//    can't surface as an HTTP error — wire the hook in auth-setup.ts:
//    hooks: { onPasswordResetFailed: (email, err) => reportError(err) }

// 4. src/routes/auth/forgot-password/+page.svelte
<script lang="ts">
  import { ForgotPasswordPage } from '@urbicon-ui/auth';
  import { en } from '@urbicon-ui/auth/i18n/en';
</script>

<ForgotPasswordPage t={en} />

// 5. src/routes/auth/reset-password/+page.svelte — token arrives as ?token=...
<script lang="ts">
  import { ResetPasswordPage } from '@urbicon-ui/auth';
  import { en } from '@urbicon-ui/auth/i18n/en';
  import { page } from '$app/state';

  const token = page.url.searchParams.get('token') ?? '';
</script>

<!-- On success the page shows a confirmation + a link to loginUrl (default /auth/login). -->
<ResetPasswordPage t={en} {token} />