Skip to content
Zeitlos
Dashboard

Authentication

.md

Password reset

Build the reset page your app needs, then point Zeitlos at it.

Password reset is the one auth flow that needs a page from you. The email has to land somewhere that collects a new password, and only your app can provide that.

Because of that, reset is disabled until you configure the page. Until then, forgetPassword throws RESET_PASSWORD_NOT_CONFIGURED.

How the flow works

  1. The user asks to reset their password in your app.
  2. You call forgetPassword({ email }).
  3. Zeitlos emails them a link to your reset page, with a token in the query string.
  4. Your page collects a new password and calls resetPassword({ token, newPassword }).
  5. You send them to sign in.

Setting it up

  1. Build the reset page

    Any route in your app — /reset-password is a fine choice. It reads token from the query string and collects a new password:

    app/reset-password/page.tsx
    'use client';
    
    import { useState } from 'react';
    import { createClient, ZeitlosError } from '@zeitlosapp/sdk';
    
    const client = createClient();
    
    export default function ResetPassword() {
      const [error, setError] = useState<string | null>(null);
    
      async function submit(newPassword: string) {
        const token = new URLSearchParams(location.search).get('token');
        if (!token) return setError('This link is malformed.');
    
        try {
          await client.auth.resetPassword({ token, newPassword });
          location.href = '/sign-in';
        } catch (err) {
          if (err instanceof ZeitlosError && err.code === 'INVALID_TOKEN') {
            setError('This link has expired or was already used.');
          }
        }
      }
    
      // …your form, calling submit(newPassword)
    }
  2. Tell Zeitlos where it is

    Go to Authentication → Settings → Password reset and enter the page's full URL, e.g. https://yourapp.com/reset-password. The card's badge flips from Disabled to Enabled once saved.

  3. Trigger a reset from your app

    From your "Forgot password?" screen:

    TypeScript
    await client.auth.forgetPassword({ email });

    This always resolves the same way whether or not the account exists — it does not reveal which emails are registered. Show a neutral "if that email exists, we've sent a link" message.

Tip

You can test the whole flow locally. See Local development for more details.

Reset tokens are single-use and time-limited. A link that has expired or already been used throws INVALID_TOKEN on resetPassword. Catch it and offer to send a fresh link rather than leaving the user on a dead page.

Where the email comes from

The sender name and reply-to address are under Authentication → Settings → Email, along with a preview of what the message looks like.