From e13349e52a1cd9fa1ba188fbacd8ac8093b01930 Mon Sep 17 00:00:00 2001 From: Alexis Aguilar <98043211+alexisintech@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:42:30 -0400 Subject: [PATCH] update email/password guide --- docs/custom-flows/email-password.mdx | 405 ++++++++++++++------------- 1 file changed, 203 insertions(+), 202 deletions(-) diff --git a/docs/custom-flows/email-password.mdx b/docs/custom-flows/email-password.mdx index 40dd4b08a1..64b64f2dc4 100644 --- a/docs/custom-flows/email-password.mdx +++ b/docs/custom-flows/email-password.mdx @@ -4,7 +4,7 @@ description: Learn how to build a custom email/password sign-up and sign-in flow --- > [!WARNING] -> This guide is for users who want to build a _custom_ user interface using the Clerk API. To use a _prebuilt_ UI, you should use Clerk's [Account Portal pages](/docs/customization/account-portal/overview) or [prebuilt components](/docs/components/overview). +> This guide is for users who want to build a _custom_ user interface using the Clerk API. To use a _prebuilt_ UI, use Clerk's [Account Portal pages](/docs/customization/account-portal/overview) or [prebuilt components](/docs/components/overview). This guide will walk you through how to build a custom email/password sign-up and sign-in flow. @@ -13,28 +13,30 @@ This guide will walk you through how to build a custom email/password sign-up an ### Enable email and password authentication - To use email and password authentication, you first need to enable these authentication strategies in the Clerk Dashboard. + To use email and password authentication, you first need to enable these [authentication strategies](/docs/authentication/configuration/sign-up-sign-in-options#authentication-strategies) in the Clerk Dashboard. - 1. Navigate to the Clerk Dashboard. - 1. Go to **User & Authentication > [Email, Phone, and Username](https://dashboard.clerk.com/last-active?path=user-authentication/email-phone-username)** in the sidebar menu. - 1. Ensure that _only_ **Email address** is required. Use the settings cog icon to check if a setting is required or optional. By default, the email address [verification method](/docs/authentication/configuration/sign-up-sign-in-options#verification-methods) is set to **Email code**. This means that when a user signs up using their email address and password, Clerk will send a one-time code to the user's email address. The user must then enter this code to verify their email and complete the sign-up process. - 1. In the **Username** section, ensure that **Username** is not required, or else the `create()` method will require a username to be passed in the params. If you would like to use usernames, you must handle collecting the username in your custom flow. + 1. Navigate to the [Clerk Dashboard](https://dashboard.clerk.com/last-active?path=user-authentication/email-phone-username). + 1. In the navigation sidebar, select **User & Authentication > Email, Phone, and Username**. + 1. Ensure that _only_ **Email address** is required. If **Phone number** and **Username** are enabled, ensure they are not required. Use the settings cog icon next to each setting to check if a setting is required or optional. If you would like to require **Username**, you must collect the username and pass it to the `create()` method in your custom flow. 1. In the **Authentication strategies** section of this page, ensure **Password** is enabled. - ### Create the email/password sign-up flow + > [!NOTE] + > By default, the [verification method](/docs/authentication/configuration/sign-up-sign-in-options#verification-methods) for the **Email address** strategy is set to **Email verification code**. This means that when a user signs up using their email address and password, Clerk will send a one-time code to the user's email address. The user must then enter this code to verify their email and complete the sign-up process. - To sign up a user using their email and password, you must: + ### Sign-up flow + + To sign up a user using their email, password, and email verification code, you must: 1. Initiate the sign-up process by collecting the user's email address and password. 1. Prepare the email address verification, which sends a one-time code to the given address. - 1. Attempt to complete the email address verification by supplying the one-time code. + 1. Collect the one-time code and attempt to complete the email address verification with it. 1. If the email address verification is successful, set the newly created session as the active session. This example is written for Next.js App Router but it can be adapted for any React meta framework, such as Remix. - ```tsx {{ filename: '/app/sign-up/[[...sign-up]].tsx' }} + ```tsx {{ filename: '/app/sign-up/[[...sign-up]].tsx', collapsible: true }} 'use client' import * as React from 'react' @@ -85,19 +87,19 @@ This guide will walk you through how to build a custom email/password sign-up an try { // Use the code the user provided to attempt verification - const completeSignUp = await signUp.attemptEmailAddressVerification({ + const signUpAttempt = await signUp.attemptEmailAddressVerification({ code, }) // If verification was completed, set the session to active // and redirect the user - if (completeSignUp.status === 'complete') { - await setActive({ session: completeSignUp.createdSessionId }) + if (signUpAttempt.status === 'complete') { + await setActive({ session: signUpAttempt.createdSessionId }) router.push('/') } else { // If the status is not complete, check why. User may need to // complete further steps. - console.error(JSON.stringify(completeSignUp, null, 2)) + console.error(JSON.stringify(signUpAttempt, null, 2)) } } catch (err: any) { // See https://clerk.com/docs/custom-flows/error-handling @@ -146,7 +148,7 @@ This guide will walk you through how to build a custom email/password sign-up an />
- +
@@ -158,109 +160,109 @@ This guide will walk you through how to build a custom email/password sign-up an "]}> - For the following example, your HTML file should look like this: - - ```html {{ filename: 'index.html' }} - - - - - - Clerk + JavaScript App - - -
- -
-

Sign up

-
- - - - - + Use the following tabs to view the code necessary for each file. + + + ```html {{ filename: 'index.html', collapsible: true }} + + + + + + Clerk + JavaScript App + + +
+ +
+

Sign up

+ + + + + + + +
+ + -
- - - - - - ``` + + + + ``` - And your JavaScript file should look like this: + ```js {{ filename: 'main.js', collapsible: true }} + import { Clerk } from '@clerk/clerk-js' - ```js {{ filename: 'main.js' }} - import { Clerk } from '@clerk/clerk-js' + // Initialize Clerk with your Clerk publishable key + const clerk = new Clerk('{{pub_key}}') + await clerk.load() - // Initialize Clerk with your Clerk publishable key - const clerk = new Clerk('{{pub_key}}') - await clerk.load() + if (clerk.user) { + // Mount user button component + document.getElementById('signed-in').innerHTML = ` +
+ ` - if (clerk.user) { - // Mount user button component - document.getElementById('signed-in').innerHTML = ` -
- ` + const userbuttonDiv = document.getElementById('user-button') - const userbuttonDiv = document.getElementById('user-button') - - clerk.mountUserButton(userbuttonDiv) - } else { - // Handle the sign-up form - document.getElementById('sign-up-form').addEventListener('submit', async (e) => { - e.preventDefault() - - const formData = new FormData(e.target) - const emailAddress = formData.get('email') - const password = formData.get('password') - - try { - // Start the sign-up process using the phone number method - await clerk.client.signUp.create({ emailAddress, password }) - await clerk.client.signUp.prepareEmailAddressVerification() - // Hide sign-up form - document.getElementById('sign-up').setAttribute('hidden', '') - // Show verification form - document.getElementById('verifying').removeAttribute('hidden') - } catch (error) { - // See https://clerk.com/docs/custom-flows/error-handling - // for more info on error handling - console.error(error) - } - }) - - // Handle the verification form - document.getElementById('verifying').addEventListener('submit', async (e) => { - const formData = new FormData(e.target) - const code = formData.get('code') - - try { - // Verify the phone number - const verify = await clerk.client.signUp.attemptEmailAddressVerification({ - code, - }) - - // Now that the user is created, set the session to active. - await clerk.setActive({ session: verify.createdSessionId }) - } catch (error) { - // See https://clerk.com/docs/custom-flows/error-handling - // for more info on error handling - console.error(error) - } - }) - } - ``` + clerk.mountUserButton(userbuttonDiv) + } else { + // Handle the sign-up form + document.getElementById('sign-up-form').addEventListener('submit', async (e) => { + e.preventDefault() + + const formData = new FormData(e.target) + const emailAddress = formData.get('email') + const password = formData.get('password') + + try { + // Start the sign-up process using the email and password provided + await clerk.client.signUp.create({ emailAddress, password }) + await clerk.client.signUp.prepareEmailAddressVerification() + // Hide sign-up form + document.getElementById('sign-up').setAttribute('hidden', '') + // Show verification form + document.getElementById('verifying').removeAttribute('hidden') + } catch (error) { + // See https://clerk.com/docs/custom-flows/error-handling + // for more info on error handling + console.error(error) + } + }) + + // Handle the verification form + document.getElementById('verifying').addEventListener('submit', async (e) => { + const formData = new FormData(e.target) + const code = formData.get('code') + + try { + // Use the code the user provided to attempt verification + const signUpAttempt = await clerk.client.signUp.attemptEmailAddressVerification({ + code, + }) + + // Now that the user is created, set the session to active. + await clerk.setActive({ session: signUpAttempt.createdSessionId }) + } catch (error) { + // See https://clerk.com/docs/custom-flows/error-handling + // for more info on error handling + console.error(error) + } + }) + } + ``` +
- ```html {{ filename: 'index.html' }} + ```html {{ filename: 'index.html', collapsible: true }} @@ -320,7 +322,7 @@ This guide will walk you through how to build a custom email/password sign-up an const password = formData.get('password') try { - // Start the sign-up process using the phone number method + // Start the sign-up process using the email and password provided await Clerk.client.signUp.create({ emailAddress, password }) await Clerk.client.signUp.prepareEmailAddressVerification() // Hide sign-up form @@ -340,13 +342,13 @@ This guide will walk you through how to build a custom email/password sign-up an const code = formData.get('code') try { - // Verify the phone number - const verify = await Clerk.client.signUp.attemptEmailAddressVerification({ + // Use the code the user provided to attempt verification + const signUpAttempt = await Clerk.client.signUp.attemptEmailAddressVerification({ code, }) // Now that the user is created, set the session to active. - await Clerk.setActive({ session: verify.createdSessionId }) + await Clerk.setActive({ session: signUpAttempt.createdSessionId }) } catch (error) { // See https://clerk.com/docs/custom-flows/error-handling // for more info on error handling @@ -383,7 +385,7 @@ This guide will walk you through how to build a custom email/password sign-up an Then create a sign-up page that sends users an email verification code to create an account. - ```tsx {{ filename: '/app/(auth)/sign-up.tsx' }} + ```tsx {{ filename: '/app/(auth)/sign-up.tsx', collapsible: true }} import * as React from 'react' import { Text, TextInput, TouchableOpacity, View } from 'react-native' import { useSignUp } from '@clerk/clerk-expo' @@ -512,7 +514,7 @@ This guide will walk you through how to build a custom email/password sign-up an - ```swift {{ filename: 'EmailPasswordSignUpView.swift' }} + ```swift {{ filename: 'EmailPasswordSignUpView.swift', collapsible: true }} import SwiftUI import ClerkSDK @@ -588,20 +590,19 @@ This guide will walk you through how to build a custom email/password sign-up an
- ### Create the email/password sign-in flow + ### Sign-in flow To authenticate a user using their email and password, you must: 1. Initiate the sign-in process by collecting the user's email address and password. - 1. Prepare the first factor verification. - 1. Attempt to complete the first factor verification. - 1. If the verification is successful, set the newly created session as the active session. + 1. Create a `SignIn` using the email address and password provided. + 1. If the attempt is successful, set the newly created session as the active session. This example is written for Next.js App Router but it can be adapted for any React meta framework, such as Remix. - ```tsx {{ filename: '/app/sign-in/[[...sign-in]].tsx' }} + ```tsx {{ filename: '/app/sign-in/[[...sign-in]].tsx', collapsible: true }} 'use client' import * as React from 'react' @@ -682,91 +683,91 @@ This guide will walk you through how to build a custom email/password sign-up an "]}> - For the following example, your HTML file should look like this: - - ```html {{ filename: 'index.html' }} - - - - - - Clerk + JavaScript App - - -
- -
-

Sign in

-
- - - - - -
-
- - - - - ``` - - And your JavaScript file should look like this: - - ```js {{ filename: 'main.js' }} - import { Clerk } from '@clerk/clerk-js' - - // Initialize Clerk with your Clerk publishable key - const clerk = new Clerk('{{pub_key}}') - await clerk.load() - - if (clerk.user) { - // Mount user button component - document.getElementById('signed-in').innerHTML = ` -
- ` - - const userbuttonDiv = document.getElementById('user-button') - - clerk.mountUserButton(userbuttonDiv) - } else { - // Handle the sign-in form - document.getElementById('sign-in-form').addEventListener('submit', async (e) => { - e.preventDefault() - - const formData = new FormData(e.target) - const emailAddress = formData.get('email') - const password = formData.get('password') - - try { - // Start the sign-in process - const signInAttempt = await clerk.client.signIn.create({ - identifier: emailAddress, - password, - }) - - // If the sign-in is complete, set the user as active - if (signInAttempt.status === 'complete') { - await clerk.setActive({ session: signInAttempt.createdSessionId }) - - location.reload() - } else { - // If the status is not complete, check why. User may need to - // complete further steps. - console.error(JSON.stringify(signInAttempt, null, 2)) + Use the following tabs to view the code necessary for each file. + + + ```html {{ filename: 'index.html', collapsible: true }} + + + + + + Clerk + JavaScript App + + +
+ +
+

Sign in

+
+ + + + + +
+
+ + + + + ``` + + ```js {{ filename: 'main.js', collapsible: true }} + import { Clerk } from '@clerk/clerk-js' + + // Initialize Clerk with your Clerk publishable key + const clerk = new Clerk('{{pub_key}}') + await clerk.load() + + if (clerk.user) { + // Mount user button component + document.getElementById('signed-in').innerHTML = ` +
+ ` + + const userbuttonDiv = document.getElementById('user-button') + + clerk.mountUserButton(userbuttonDiv) + } else { + // Handle the sign-in form + document.getElementById('sign-in-form').addEventListener('submit', async (e) => { + e.preventDefault() + + const formData = new FormData(e.target) + const emailAddress = formData.get('email') + const password = formData.get('password') + + try { + // Start the sign-in process + const signInAttempt = await clerk.client.signIn.create({ + identifier: emailAddress, + password, + }) + + // If the sign-in is complete, set the user as active + if (signInAttempt.status === 'complete') { + await clerk.setActive({ session: signInAttempt.createdSessionId }) + + location.reload() + } else { + // If the status is not complete, check why. User may need to + // complete further steps. + console.error(JSON.stringify(signInAttempt, null, 2)) + } + } catch (error) { + // See https://clerk.com/docs/custom-flows/error-handling + // for more info on error handling + console.error(error) } - } catch (error) { - // See https://clerk.com/docs/custom-flows/error-handling - // for more info on error handling - console.error(error) - } - }) - } - ``` + }) + } + ``` +
- ```html {{ filename: 'index.html' }} + ```html {{ filename: 'index.html', collapsible: true }} @@ -871,7 +872,7 @@ This guide will walk you through how to build a custom email/password sign-up an Then, create a sign-in page that allows users to sign in or navigate to the sign-up page that you created earlier. - ```tsx {{ filename: '/app/(auth)/sign-in.tsx' }} + ```tsx {{ filename: '/app/(auth)/sign-in.tsx', collapsible: true }} import { useClerk, useSignIn } from '@clerk/clerk-expo' import { Link, Stack } from 'expo-router' import { Text, TextInput, TouchableOpacity, View } from 'react-native' @@ -960,7 +961,7 @@ This guide will walk you through how to build a custom email/password sign-up an - ```swift {{ filename: 'EmailPasswordSignInView.swift' }} + ```swift {{ filename: 'EmailPasswordSignInView.swift', collapsible: true }} import SwiftUI import ClerkSDK