Password-based Authentication
Password-based authentication block for React Single Page Applications
Installation
Folder structure
This block includes the Supabase client. If you already have one installed, you can skip overwriting it.
1import { useState } from 'react'
2
3import { cn } from '@/lib/utils'
4import { createClient } from '@/lib/supabase/client'
5import { Button } from '@/components/ui/button'
6import {
7 Card,
8 CardContent,
9 CardDescription,
10 CardHeader,
11 CardTitle,
12} from '@/components/ui/card'
13import { Input } from '@/components/ui/input'
14import { Label } from '@/components/ui/label'
15
16export function ForgotPasswordForm({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
17 const [email, setEmail] = useState('')
18 const [error, setError] = useState<string | null>(null)
19 const [success, setSuccess] = useState(false)
20 const [isLoading, setIsLoading] = useState(false)
21
22 const handleForgotPassword = async (e: React.FormEvent) => {
23 const supabase = createClient()
24 e.preventDefault()
25 setIsLoading(true)
26 setError(null)
27
28 try {
29 // The url which will be included in the email. This URL needs to be configured in your redirect URLs in the Supabase dashboard at https://supabase.com/dashboard/project/_/auth/url-configuration
30 const { error } = await supabase.auth.resetPasswordForEmail(email, {
31 redirectTo: 'http://localhost:3000/update-password',
32 })
33 if (error) throw error
34 setSuccess(true)
35 } catch (error: unknown) {
36 setError(error instanceof Error ? error.message : 'An error occurred')
37 } finally {
38 setIsLoading(false)
39 }
40 }
41
42 return (
43 <div className={cn('flex flex-col gap-6', className)} {...props}>
44 {success ? (
45 <Card>
46 <CardHeader>
47 <CardTitle className="text-2xl">Check Your Email</CardTitle>
48 <CardDescription>Password reset instructions sent</CardDescription>
49 </CardHeader>
50 <CardContent>
51 <p className="text-sm text-muted-foreground">
52 If you registered using your email and password, you will receive a password reset
53 email.
54 </p>
55 </CardContent>
56 </Card>
57 ) : (
58 <Card>
59 <CardHeader>
60 <CardTitle className="text-2xl">Reset Your Password</CardTitle>
61 <CardDescription>
62 Type in your email and we'll send you a link to reset your password
63 </CardDescription>
64 </CardHeader>
65 <CardContent>
66 <form onSubmit={handleForgotPassword}>
67 <div className="flex flex-col gap-6">
68 <div className="grid gap-2">
69 <Label htmlFor="email">Email</Label>
70 <Input
71 id="email"
72 type="email"
73 placeholder="m@example.com"
74 required
75 value={email}
76 onChange={(e) => setEmail(e.target.value)}
77 />
78 </div>
79 {error && <p className="text-sm text-red-500">{error}</p>}
80 <Button type="submit" className="w-full" disabled={isLoading}>
81 {isLoading ? 'Sending...' : 'Send reset email'}
82 </Button>
83 </div>
84 <div className="mt-4 text-center text-sm">
85 Already have an account?{' '}
86 <a href="/login" className="underline underline-offset-4">
87 Login
88 </a>
89 </div>
90 </form>
91 </CardContent>
92 </Card>
93 )}
94 </div>
95 )
96}Usage
Once you install the block in your React project, you'll get all the necessary pages and components to set up a password-based authentication flow.
Getting started
After installing the block, you'll have the following environment variables in your .env.local file:
VITE_SUPABASE_URL=
VITE_SUPABASE_PUBLISHABLE_KEY=-
If you're using supabase.com, you can find these values in the Connect modal under App Frameworks or in your project's API settings.
-
If you're using a local instance of Supabase, you can find these values by running
supabase startorsupabase status(if you already have it running).
Setting up routes and redirect URLs
-
Set the site URL in the URL Configuration settings in the Supabase Dashboard.
-
Set up the route users will visit to reset or update their password. Go to the URL Configuration settings and add the
forgot-passwordroute to the list of Redirect URLs. It should look something like:http://example.com/auth/forgot-password. -
Update the redirect paths in
login.tsxandupdate-password.tsxcomponents to point to the logged-in routes in your app. Our examples use/protected, but you can set this to whatever fits your app. -
Add the following code in the authenticated route to redirect to login if the user is unauthenticated.
import { useEffect } from "react"
import { createClient } from "@supabase/supabase-js"
export default function AuthenticatedRoute() {
useEffect(() => {
const checkAuth = async () => {
const client = createClient()
const { error } = await client.auth.getUser()
if (error) {
location.href = "/login"
}
}
checkAuth()
}, [])
return <div>Authenticated page</div>;
}