Email & Password
Learn how to set up authentication using a password.
Overview
One of the most common authentication methods used today is the humble email and password. With this setup, users that come to your website will need to supply these credentials in order to gain access to their account.
Clerk enforces every user to have a verified email address. This is done during sign up, by sending a one-time code to the supplied email address.
There are a few different ways to set up an email/password user management system in Clerk. You can use Clerk Components or build a completely custom flow with ClerkJS or Clerk React. The rest of this guide will explain how to set up an email/password user management system using any of the above methods.
To keep your users safe, Clerk follows a "secure-by-default" policy, and we follow all NIST best practices. This includes password validations out of the box.
Before you start
- You need to create a Clerk Application in your Clerk Dashboard. For more information, check out our Set up your application guide.
- You need to install Clerk React or ClerkJS to your application.
Configuration
The first thing you need to do is enable email address and password-based authentication on the Email, Phone, Username page.
Select Email address for your contact information and Password as your authentication factor.
Sign up using a custom flow
The email/password sign-up flow requires users to provide their email address and their password and returns a newly-created user with an active session.
A successful sign-up consists of the following steps:
1. Initiate the sign-up process, by collecting the user's email address and password.
2. Prepare the email address verification, which sends a one-time code to the given address.
3. Attempt to complete the email address verification by supplying the one-time code.
4. If the email address verification is successful, complete the sign-up process by creating the user account and setting their session as active.
1"use client"2import { useState } from "react";3import { useSignUp } from "@clerk/nextjs";4import { useRouter } from "next/router";56export default function SignUpForm() {7const { isLoaded, signUp, setActive } = useSignUp();8const [emailAddress, setEmailAddress] = useState("");9const [password, setPassword] = useState("");10const [pendingVerification, setPendingVerification] = useState(false);11const [code, setCode] = useState("");12const router = useRouter();13// start the sign up process.14const handleSubmit = async (e) => {15e.preventDefault();16if (!isLoaded) {17return;18}1920try {21await signUp.create({22emailAddress,23password,24});2526// send the email.27await signUp.prepareEmailAddressVerification({ strategy: "email_code" });2829// change the UI to our pending section.30setPendingVerification(true);31} catch (err: any) {32console.error(JSON.stringify(err, null, 2));33}34};3536// This verifies the user using email code that is delivered.37const onPressVerify = async (e) => {38e.preventDefault();39if (!isLoaded) {40return;41}4243try {44const completeSignUp = await signUp.attemptEmailAddressVerification({45code,46});47if (completeSignUp.status !== "complete") {48/* investigate the response, to see if there was an error49or if the user needs to complete more steps.*/50console.log(JSON.stringify(completeSignUp, null, 2));51}52if (completeSignUp.status === "complete") {53await setActive({ session: completeSignUp.createdSessionId })54router.push("/");55}56} catch (err: any) {57console.error(JSON.stringify(err, null, 2));58}59};6061return (62<div>63{!pendingVerification && (64<form>65<div>66<label htmlFor="email">Email</label>67<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />68</div>69<div>70<label htmlFor="password">Password</label>71<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />72</div>73<button onClick={handleSubmit}>Sign up</button>74</form>75)}76{pendingVerification && (77<div>78<form>79<input80value={code}81placeholder="Code..."82onChange={(e) => setCode(e.target.value)}83/>84<button onClick={onPressVerify}>85Verify Email86</button>87</form>88</div>89)}90</div>91);92}
1import { useState } from "react";2import { useSignUp } from "@clerk/nextjs";3import { useRouter } from "next/router";45export default function SignUpForm() {6const { isLoaded, signUp, setActive } = useSignUp();7const [emailAddress, setEmailAddress] = useState("");8const [password, setPassword] = useState("");9const [pendingVerification, setPendingVerification] = useState(false);10const [code, setCode] = useState("");11const router = useRouter();12// start the sign up process.13const handleSubmit = async (e) => {14e.preventDefault();15if (!isLoaded) {16return;17}1819try {20await signUp.create({21emailAddress,22password,23});2425// send the email.26await signUp.prepareEmailAddressVerification({ strategy: "email_code" });2728// change the UI to our pending section.29setPendingVerification(true);30} catch (err: any) {31console.error(JSON.stringify(err, null, 2));32}33};3435// This verifies the user using email code that is delivered.36const onPressVerify = async (e) => {37e.preventDefault();38if (!isLoaded) {39return;40}4142try {43const completeSignUp = await signUp.attemptEmailAddressVerification({44code,45});46if (completeSignUp.status !== "complete") {47/* investigate the response, to see if there was an error48or if the user needs to complete more steps.*/49console.log(JSON.stringify(completeSignUp, null, 2));50}51if (completeSignUp.status === "complete") {52await setActive({ session: completeSignUp.createdSessionId })53router.push("/");54}55} catch (err: any) {56console.error(JSON.stringify(err, null, 2));57}58};5960return (61<div>62{!pendingVerification && (63<form>64<div>65<label htmlFor="email">Email</label>66<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />67</div>68<div>69<label htmlFor="password">Password</label>70<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />71</div>72<button onClick={handleSubmit}>Sign up</button>73</form>74)}75{pendingVerification && (76<div>77<form>78<input79value={code}80placeholder="Code..."81onChange={(e) => setCode(e.target.value)}82/>83<button onClick={onPressVerify}>84Verify Email85</button>86</form>87</div>88)}89</div>90);91}
1import { useState } from "react";2import { useSignUp } from "@clerk/clerk-react";34export default function SignUpForm() {5const { isLoaded, signUp, setActive } = useSignUp();6const [emailAddress, setEmailAddress] = useState("");7const [password, setPassword] = useState("");8const [pendingVerification, setPendingVerification] = useState(false);9const [code, setCode] = useState("");10// start the sign up process.11const handleSubmit = async (e) => {12e.preventDefault();13if (!isLoaded) {14return;15}1617try {18await signUp.create({19emailAddress,20password,21});2223// send the email.24await signUp.prepareEmailAddressVerification({ strategy: "email_code" });2526// change the UI to our pending section.27setPendingVerification(true);28} catch (err: any) {29console.error(JSON.stringify(err, null, 2));30}31};3233// This verifies the user using email code that is delivered.34const onPressVerify = async (e) => {35e.preventDefault();36if (!isLoaded) {37return;38}3940try {41const completeSignUp = await signUp.attemptEmailAddressVerification({42code,43});44if (completeSignUp.status !== "complete") {45/* investigate the response, to see if there was an error46or if the user needs to complete more steps.*/47console.log(JSON.stringify(completeSignUp, null, 2));48}49if (completeSignUp.status === "complete") {50await setActive({ session: completeSignUp.createdSessionId })51}52} catch (err: any) {53console.error(JSON.stringify(err, null, 2));54}55};5657return (58<div>59{!pendingVerification && (60<form>61<div>62<label htmlFor="email">Email</label>63<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />64</div>65<div>66<label htmlFor="password">Password</label>67<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />68</div>69<button onClick={handleSubmit}>Sign up</button>70</form>71)}72{pendingVerification && (73<div>74<form>75<input76value={code}77placeholder="Code..."78onChange={(e) => setCode(e.target.value)}79/>80<button onClick={onPressVerify}>81Verify Email82</button>83</form>84</div>85)}86</div>87);88}
1import { useState } from "react";2import { useSignUp } from "@clerk/remix";34export default function SignUpForm() {5const { isLoaded, signUp, setActive } = useSignUp();6const [emailAddress, setEmailAddress] = useState("");7const [password, setPassword] = useState("");8const [pendingVerification, setPendingVerification] = useState(false);9const [code, setCode] = useState("");10// start the sign up process.11const handleSubmit = async (e) => {12e.preventDefault();13if (!isLoaded) {14return;15}1617try {18await signUp.create({19emailAddress,20password,21});2223// send the email.24await signUp.prepareEmailAddressVerification({ strategy: "email_code" });2526// change the UI to our pending section.27setPendingVerification(true);28} catch (err: any) {29console.error(JSON.stringify(err, null, 2));30}31};3233// This verifies the user using email code that is delivered.34const onPressVerify = async (e) => {35e.preventDefault();36if (!isLoaded) {37return;38}3940try {41const completeSignUp = await signUp.attemptEmailAddressVerification({42code,43});44if (completeSignUp.status !== "complete") {45/* investigate the response, to see if there was an error46or if the user needs to complete more steps.*/47console.log(JSON.stringify(completeSignUp, null, 2));48}49if (completeSignUp.status === "complete") {50await setActive({ session: completeSignUp.createdSessionId })51// Handle your own logic here, like redirecting to a new page if needed.52}53} catch (err: any) {54console.error(JSON.stringify(err, null, 2));55}56};5758return (59<div>60{!pendingVerification && (61<form>62<div>63<label htmlFor="email">Email</label>64<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />65</div>66<div>67<label htmlFor="password">Password</label>68<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />69</div>70<button onClick={handleSubmit}>Sign up</button>71</form>72)}73{pendingVerification && (74<div>75<form>76<input77value={code}78placeholder="Code..."79onChange={(e) => setCode(e.target.value)}80/>81<button onClick={onPressVerify}>82Verify Email83</button>84</form>85</div>86)}87</div>88);89}
1import { useState } from "react";2// Use the react package when using Gatsby3import { useSignUp } from "@clerk/react";4import { useRouter } from "next/router";56export default function SignUpForm() {7const { isLoaded, signUp, setActive } = useSignUp();8const [emailAddress, setEmailAddress] = useState("");9const [password, setPassword] = useState("");10const [pendingVerification, setPendingVerification] = useState(false);11const [code, setCode] = useState("");12const router = useRouter();13// start the sign up process.14const handleSubmit = async (e) => {15e.preventDefault();16if (!isLoaded) {17return;18}1920try {21await signUp.create({22emailAddress,23password,24});2526// send the email.27await signUp.prepareEmailAddressVerification({ strategy: "email_code" });2829// change the UI to our pending section.30setPendingVerification(true);31} catch (err: any) {32console.error(JSON.stringify(err, null, 2));33}34};3536// This verifies the user using email code that is delivered.37const onPressVerify = async (e) => {38e.preventDefault();39if (!isLoaded) {40return;41}4243try {44const completeSignUp = await signUp.attemptEmailAddressVerification({45code,46});47if (completeSignUp.status !== "complete") {48/* investigate the response, to see if there was an error49or if the user needs to complete more steps.*/50console.log(JSON.stringify(completeSignUp, null, 2));51}52if (completeSignUp.status === "complete") {53await setActive({ session: completeSignUp.createdSessionId })54router.push("/");55}56} catch (err: any) {57console.error(JSON.stringify(err, null, 2));58}59};6061return (62<div>63{!pendingVerification && (64<form>65<div>66<label htmlFor="email">Email</label>67<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />68</div>69<div>70<label htmlFor="password">Password</label>71<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />72</div>73<button onClick={handleSubmit}>Sign up</button>74</form>75)}76{pendingVerification && (77<div>78<form>79<input80value={code}81placeholder="Code..."82onChange={(e) => setCode(e.target.value)}83/>84<button onClick={onPressVerify}>85Verify Email86</button>87</form>88</div>89)}90</div>91);92}
1import * as React from "react";2import { Text, TextInput, TouchableOpacity, View } from "react-native";3import { useSignUp } from "@clerk/clerk-expo";45export default function SignUpScreen() {6const { isLoaded, signUp, setActive } = useSignUp();78const [emailAddress, setEmailAddress] = React.useState("");9const [password, setPassword] = React.useState("");10const [pendingVerification, setPendingVerification] = React.useState(false);11const [code, setCode] = React.useState("");1213// start the sign up process.14const onSignUpPress = async () => {15if (!isLoaded) {16return;17}1819try {20await signUp.create({21emailAddress,22password,23});2425// send the email.26await signUp.prepareEmailAddressVerification({ strategy: "email_code" });2728// change the UI to our pending section.29setPendingVerification(true);30} catch (err: any) {31console.error(JSON.stringify(err, null, 2));32}33};3435// This verifies the user using email code that is delivered.36const onPressVerify = async () => {37if (!isLoaded) {38return;39}4041try {42const completeSignUp = await signUp.attemptEmailAddressVerification({43code,44});4546await setActive({ session: completeSignUp.createdSessionId });47} catch (err: any) {48console.error(JSON.stringify(err, null, 2));49}50};5152return (53<View>54{!pendingVerification && (55<View>56<View>57<TextInput58autoCapitalize="none"59value={emailAddress}60placeholder="Email..."61onChangeText={(email) => setEmailAddress(email)}62/>63</View>6465<View>66<TextInput67value={password}68placeholder="Password..."69placeholderTextColor="#000"70secureTextEntry={true}71onChangeText={(password) => setPassword(password)}72/>73</View>7475<TouchableOpacity onPress={onSignUpPress}>76<Text>Sign up</Text>77</TouchableOpacity>78</View>79)}80{pendingVerification && (81<View>82<View>83<TextInput84value={code}85placeholder="Code..."86onChangeText={(code) => setCode(code)}87/>88</View>89<TouchableOpacity onPress={onPressVerify}>90<Text>Verify Email</Text>91</TouchableOpacity>92</View>93)}94</View>95);96}
1<!DOCTYPE html>2<html lang="en">34<head>5<meta charset="UTF-8" />6<meta http-equiv="X-UA-Compatible" content="IE=edge" />7<meta name="viewport" content="width=device-width, initial-scale=1.0" />8<title>Clerk JavaScript Email + Password</title>9</head>1011<body>12<h1>Clerk JavaScript Email + Password</h1>1314<div id="auth-signup">15<input placeholder="email" id="email" type="email"></input>16<input placeholder="password" id="password" type="password"></input>17<button onclick="SignUp()">SignUp</button>1819</div>20<div id="auth-verification" hidden="true">21<input placeholder="code" id="code" type="text"></input>22<button onclick="VerifyEmailAddress()">Verify</button>23</div>2425<div id="user-button" />26<script>27const SignUp = async () => {28const emailAddress = document.getElementById('email').value;29const password = document.getElementById('password').value;30const {client} = window.Clerk;31try {32await client.signUp.create({33emailAddress,34password35});36await client.signUp.prepareEmailAddressVerification();37//hide signup form38document.getElementById('auth-signup').hidden = true;39//show verification form40document.getElementById('auth-verification').hidden = false;41}42catch (err) {43console.log(err)44}45};46const VerifyEmailAddress = async () => {47const code = document.getElementById('code').value;48const {client, setActive} = window.Clerk;49try {50// Verify the email address.51const verify = await client.signUp.attemptEmailAddressVerification({52code53});54// user is created now set the session to active this never is not null.55await setActive({session: verify.createdSessionId})56}5758catch (err) {59console.log(err)60}61}62</script>63// Script to load Clerk up64<script src="src/script.js" async crossorigin="anonymous"></script>65</body>6667</html>
Sign in using a custom flow
In email/password authentication, the sign-in is a process that requires users to provide their email address and their password and authenticates them by creating a new session for the user.
1"use client"2import { useState } from "react";3import { useSignIn } from "@clerk/nextjs";4import { useRouter } from "next/router";56export default function SignInForm() {7const { isLoaded, signIn, setActive } = useSignIn();8const [emailAddress, setEmailAddress] = useState("");9const [password, setPassword] = useState("");10const router = useRouter();11// start the sign In process.12const handleSubmit = async (e) => {13e.preventDefault();14if (!isLoaded) {15return;16}1718try {19const result = await signIn.create({20identifier: emailAddress,21password,22});2324if (result.status === "complete") {25console.log(result);26await setActive({ session: result.createdSessionId });27router.push("/")28}29else {30/*Investigate why the login hasn't completed */31console.log(result);32}3334} catch (err: any) {35console.error("error", err.errors[0].longMessage)36}37};3839return (40<div>41<form>42<div>43<label htmlFor="email">Email</label>44<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />45</div>46<div>47<label htmlFor="password">Password</label>48<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />49</div>50<button onClick={handleSubmit}>Sign In</button>51</form>52</div>53);54}
1import { useState } from "react";2import { useSignIn } from "@clerk/nextjs";3import { useRouter } from "next/router";45export default function SignInForm() {6const { isLoaded, signIn, setActive } = useSignIn();7const [emailAddress, setEmailAddress] = useState("");8const [password, setPassword] = useState("");9const router = useRouter();10// start the sign In process.11const handleSubmit = async (e) => {12e.preventDefault();13if (!isLoaded) {14return;15}1617try {18const result = await signIn.create({19identifier: emailAddress,20password,21});2223if (result.status === "complete") {24console.log(result);25await setActive({ session: result.createdSessionId });26router.push("/")27}28else {29/*Investigate why the login hasn't completed */30console.log(result);31}3233} catch (err: any) {34console.error("error", err.errors[0].longMessage)35}36};3738return (39<div>40<form>41<div>42<label htmlFor="email">Email</label>43<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />44</div>45<div>46<label htmlFor="password">Password</label>47<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />48</div>49<button onClick={handleSubmit}>Sign In</button>50</form>51</div>52);53}
1import { useState } from "react";2import { useSignIn } from "@clerk/clerk-react";34export default function SignInForm() {5const { isLoaded, signIn, setActive } = useSignIn();6const [emailAddress, setEmailAddress] = useState("");7const [password, setPassword] = useState("");8// start the sign In process.9const handleSubmit = async (e) => {10e.preventDefault();11if (!isLoaded) {12return;13}1415try {16const result = await signIn.create({17identifier: emailAddress,18password,19});2021if (result.status === "complete") {22await setActive({ session: result.createdSessionId });23// redirect the user how you see fit.24}25else {26/*Investigate why the login hasn't completed */27console.log(result);28}2930} catch (err: any) {31console.error("error", err.errors[0].longMessage)32}33};3435return (36<div>37<form>38<div>39<label htmlFor="email">Email</label>40<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />41</div>42<div>43<label htmlFor="password">Password</label>44<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />45</div>46<button onClick={handleSubmit}>Sign In</button>47</form>48</div>49);50}
1import { useState } from "react";2import { useSignIn } from "@clerk/remix";34export default function SignInForm() {5const { isLoaded, signIn, setActive } = useSignIn();6const [emailAddress, setEmailAddress] = useState("");7const [password, setPassword] = useState("");8// start the sign In process.9const handleSubmit = async (e) => {10e.preventDefault();11if (!isLoaded) {12return;13}1415try {16const result = await signIn.create({17identifier: emailAddress,18password,19});2021if (result.status === "complete") {22await setActive({ session: result.createdSessionId });23// redirect the user how you see fit.24}25else {26/*Investigate why the login hasn't completed */27console.log(result);28}2930} catch (err: any) {31console.error("error", err.errors[0].longMessage)32}33};3435return (36<div>37<form>38<div>39<label htmlFor="email">Email</label>40<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />41</div>42<div>43<label htmlFor="password">Password</label>44<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />45</div>46<button onClick={handleSubmit}>Sign In</button>47</form>48</div>49);50}
1import { useState } from "react";2// Use React for Gatsby3import { useSignIn } from "@clerk/clerk-react";45export default function SignInForm() {6const { isLoaded, signIn, setActive } = useSignIn();7const [emailAddress, setEmailAddress] = useState("");8const [password, setPassword] = useState("");9// start the sign In process.10const handleSubmit = async (e) => {11e.preventDefault();12if (!isLoaded) {13return;14}1516try {17const result = await signIn.create({18identifier: emailAddress,19password,20});2122if (result.status === "complete") {23await setActive({ session: result.createdSessionId });24// redirect the user how you see fit.25}26else {27/*Investigate why the login hasn't completed */28console.log(result);29}3031} catch (err: any) {32console.error("error", err.errors[0].longMessage)33}34};3536return (37<div>38<form>39<div>40<label htmlFor="email">Email</label>41<input onChange={(e) => setEmailAddress(e.target.value)} id="email" name="email" type="email" />42</div>43<div>44<label htmlFor="password">Password</label>45<input onChange={(e) => setPassword(e.target.value)} id="password" name="password" type="password" />46</div>47<button onClick={handleSubmit}>Sign In</button>48</form>49</div>50);51}
1import React from "react";2import { Text, TextInput, TouchableOpacity, View } from "react-native";3import { useSignIn } from "@clerk/clerk-expo";45export default function SignInScreen() {6const { signIn, setActive, isLoaded } = useSignIn();78const [emailAddress, setEmailAddress] = React.useState("");9const [password, setPassword] = React.useState("");1011const onSignInPress = async () => {12if (!isLoaded) {13return;14}1516try {17const completeSignIn = await signIn.create({18identifier: emailAddress,19password,20});21if (completeSignIn.status === "complete") {22await setActive({ session: result.createdSessionId });23// redirect the user how you see fit.24}25else {26/*Investigate why the login hasn't completed */27console.log(result);28}2930} catch (err: any) {31console.log(err);32}33};34return (35<View>36<View>37<TextInput38autoCapitalize="none"39value={emailAddress}40placeholder="Email..."41onChangeText={(emailAddress) => setEmailAddress(emailAddress)}42/>43</View>4445<View>46<TextInput47value={password}48placeholder="Password..."49secureTextEntry={true}50onChangeText={(password) => setPassword(password)}51/>52</View>5354<TouchableOpacity onPress={onSignInPress}>55<Text>Sign in</Text>56</TouchableOpacity>57</View>58);59}
1<!DOCTYPE html>2<html lang="en">34<head>5<meta charset="UTF-8" />6<meta http-equiv="X-UA-Compatible" content="IE=edge" />7<meta name="viewport" content="width=device-width, initial-scale=1.0" />8<title>Clerk JavaScript Email + Password</title>9</head>1011<body>12<h1>Clerk JavaScript Email + Password</h1>1314<div id="auth-signin">15<input placeholder="email" id="email" type="email"></input>16<input placeholder="password" id="password" type="password"></input>17<button onclick="SignIn()">SignIn</button>1819</div>20<script>21const SignIn = async () => {22const emailAddress = document.getElementById('email').value;23const password = document.getElementById('password').value;24const {client} = window.Clerk;25try {26const signInAttempt = await client.signIn.create({27emailAddress,28password29});30if (signInAttempt.status === "complete") {31await setActive({ session: signInAttempt.createdSessionId });32// redirect the user how you see fit.33}34else {35/*Investigate why the login hasn't completed */36console.log(signInAttempt);37}38}39catch (err) {40console.log(err)41}42};43</script>44// Script to load Clerk up45<script src="src/script.js" async crossorigin="anonymous"></script>46</body>4748</html>