SessionExpired
Re-authentication form for a session that ended: the same person, a password (and code) or a passkey away, with switch account and sign out.
Code
import { AuthLayout, SessionExpired } from "@fadymondy/nasaq/web";export function Expired() { return ( <AuthLayout title="Welcome back"> <SessionExpired user={{ name: "Sara Nasser", email: "[email protected]" }} keepsWork onSubmit={async ({ password }) => { const ok = await api.reauth(password); if (!ok) return { error: "Wrong password." }; }} onSignOut={() => api.signOut()} /> </AuthLayout> );}declare const api: { reauth(p: string): Promise<boolean>; signOut(): void };Auth · beta
Live examples and controls: SessionExpired in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/session-expired.jsonThe form shown when a session ended: expired, revoked from another device, or the password changed. Who was signed in is
known, so only the secret is asked again. Put it in an AuthLayout. Use LockScreen when the session is still valid but locked.
When to use
- A request came back 401 and the person must sign in again without losing their place.
When not to use
- A locked but valid session:
lock-screen. - A first sign-in:
login-form.
Import
import { AuthLayout, SessionExpired } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"Quick start
import { AuthLayout, SessionExpired } from "@fadymondy/nasaq/web";
export function Expired() {
return (
<AuthLayout title="Welcome back">
<SessionExpired
user={{ name: "Sara Nasser", email: "[email protected]" }}
keepsWork
onSubmit={async ({ password }) => {
const ok = await api.reauth(password);
if (!ok) return { error: "Wrong password." };
}}
onSignOut={() => api.signOut()}
/>
</AuthLayout>
);
}
declare const api: { reauth(p: string): Promise<boolean>; signOut(): void };Anatomy
SessionExpired data-slot="session-expired" data-reason
├─ Alert (why)
├─ user row
├─ error summary
├─ password, optional code
├─ Sign in again · Use a passkey
└─ Use a different account · Sign outAPI
form props (except onSubmit, children) plus:
| Prop | Type | Default | Description |
|---|---|---|---|
user | LockUser | required | Who was signed in. |
reason | expired, revoked, password-changed | expired | Picks the message. |
requireCode | boolean | false | Ask for a 6 digit authenticator code. |
onSubmit | (values) => AuthSubmitResult | required | Resolve nothing on success, or { error } / { fieldErrors }. |
onPasskey | () => Promise | Shows the passkey button where WebAuthn works. | |
onSwitchAccount, onSignOut | () => void | Show their link buttons. | |
keepsWork | boolean | false | Tells people their unsaved changes are safe. |
footer, labels |
Examples
With a code and passkey
import { SessionExpired } from "@fadymondy/nasaq/web";
export const Strict = () => <SessionExpired user={{ name: "Omar" }} reason="revoked" requireCode onPasskey={() => api.passkey()} onSubmit={async () => undefined} />;
declare const api: { passkey(): Promise<void> };Accessibility
- Errors are summarised and focus moves to the summary. The password field is auto focused.
- A hidden username lets password managers fill the right entry.
- The passkey button appears only when the browser supports it.
RTL & i18n
- English and Arabic built in; pass
labels. Emails stay left to right.
Styling & tokens
- Tokens only. Reuses
Alert,PasswordInput,OtpInput,Button.
Do / Don't
- Do say why the session ended.
- Do keep the person's place: return them to the page after success.
- Don't ask for the email again.
Related
Lab
https://docs.nasaqui.com/?path=/docs/components-auth-pages-session-expired--docs
ResetPasswordForm
Choose a new password with a confirmation field, strength meter and optional policy checklist, then a Password changed or Link expired screen; en and ar built in.
SignInFlow
Identifier-first sign-in: the email and the providers first, then the step your backend picks for that address (password, one-time code, sign-in link, SSO, sign-up or blocked), with two-factor and forgot password in place.