www/apps/resources/app/storefront-development/customers/register/page.mdx
import { CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: Register Customer in Storefront,
}
In this guide, you'll learn how to register a customer in your storefront.
This guide covers registration using email and password. For authentication with third-party providers, refer to the Third-Party Login guide.
To register a customer, you implement the following steps:
POST request to the /auth/customer/emailpass/register Get Registration Token API route to obtain a registration JWT token.However, a customer may enter an email that's already used either by an admin user, another customer, or a custom actor type. To handle this scenario:
POST request to the /auth/customer/emailpass Authenticate Customer API route. The customer is only allowed to register if their email and password match the existing identity. This allows admin users to log in or register as customers.When you're using the JS SDK, this flow is simplified with quick registration and login methods. The rest of this guide uses the JS SDK to demonstrate the registration flow. However, if you're not using the JS SDK, you can still implement the same flow using the API routes.
<Note title="Tip">Learn how to install and configure the JS SDK in the JS SDK documentation.
</Note>An example implementation of the registration flow in a storefront:
<CodeTabs group="store-request"> <CodeTab label="React" value="react">export const highlights = [ ["24", "register", "Send a request to set the registration token in the JS SDK."], ["28", "catch", "Maybe another identity exists with the same email."], ["31", "", "If an unexpected error occurs, exit the flow."], ["38", "login", "Try to obtain a login JWT token."], ["41", "catch", "The existing account belongs to another customer, so authentication failed."], ["57", "create", "Send a request to create the customer."], ["66", "TODO", "Redirect the customer to the log in page."], ["67", "catch", "Handle registration failure"], ]
"use client" // include with Next.js 13+
import { useState } from "react"
import { sdk } from "@/lib/sdk"
import { FetchError } from "@medusajs/js-sdk"
export default function Register() {
const [loading, setLoading] = useState(false)
const [firstName, setFirstName] = useState("")
const [lastName, setLastName] = useState("")
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const handleRegistration = async (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.preventDefault()
if (!firstName || !lastName || !email || !password) {
return
}
setLoading(true)
try {
await sdk.auth.register("customer", "emailpass", {
email,
password,
})
} catch (error) {
const fetchError = error as FetchError
if (fetchError.statusText !== "Unauthorized" || fetchError.message !== "Identity with email already exists") {
alert(`An error occurred while creating account: ${fetchError}`)
return
}
// another identity (for example, admin user)
// exists with the same email. So, use the auth
// flow to login and create a customer.
const loginResponse = (await sdk.auth.login("customer", "emailpass", {
email,
password,
}).catch((e) => {
alert(`An error occurred while creating account: ${e}`)
}))
if (!loginResponse) {
return
}
if (typeof loginResponse !== "string") {
alert("Authentication requires more actions, which isn't supported by this flow.")
return
}
}
// create customer
try {
const { customer } = await sdk.store.customer.create({
first_name: firstName,
last_name: lastName,
email,
})
setLoading(false)
console.log(customer)
// TODO redirect to login page
} catch (error) {
console.error(error)
alert("Error: " + error)
return
}
}
return (
<form>
<input
type="text"
name="first_name"
value={firstName}
placeholder="First Name"
onChange={(e) => setFirstName(e.target.value)}
/>
<input
type="text"
name="last_name"
value={lastName}
placeholder="Last Name"
onChange={(e) => setLastName(e.target.value)}
/>
<input
type="email"
name="email"
value={email}
placeholder="Email"
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
name="password"
value={password}
placeholder="Password"
onChange={(e) => setPassword(e.target.value)}
/>
<button
disabled={loading}
onClick={handleRegistration}
>
Register
</button>
</form>
)
}
export const fetchHighlights = [ ["7", "register", "Send a request to obtain a registration JWT token."], ["11", "catch", "Maybe another identity exists with the same email."], ["21", "login", "Try to obtain a login JWT token."], ["24", "catch", "The existing account belongs to another customer, so authentication failed."], ["40", "create", "Send a request to register the customer."], ["47", "TODO", "Redirect the customer to the log in page."], ["48", "catch", "Handle registration failure"], ]
// other imports...
import { FetchError } from "@medusajs/js-sdk"
const handleRegistration = async () => {
// obtain registration JWT token
try {
await sdk.auth.register("customer", "emailpass", {
email,
password,
})
} catch (error) {
const fetchError = error as FetchError
if (fetchError.statusText !== "Unauthorized" || fetchError.message !== "Identity with email already exists") {
alert(`An error occurred while creating account: ${fetchError}`)
return
}
// another identity (for example, admin user)
// exists with the same email. So, use the auth
// flow to login and register a customer.
const loginResponse = (await sdk.auth.login("customer", "emailpass", {
email,
password,
}).catch((e) => {
alert(`An error occurred while creating account: ${e}`)
}))
if (!loginResponse) {
return
}
if (typeof loginResponse !== "string") {
alert("Authentication requires more actions, which isn't supported by this flow.")
return
}
}
// register customer
try {
const { customer } = await sdk.store.customer.create({
first_name: firstName,
last_name: lastName,
email,
})
console.log(customer)
// TODO redirect to login page
} catch (error) {
console.error(error)
alert("Error: " + error)
return
}
}
In the above example, you create a handleRegistration function that:
/auth/customer/emailpass/register API route using the auth.register method. If an error is thrown:
/auth/customer/emailpass API route using the auth.login method. This will fail if the existing identity has a different password, which doesn't allow the customer from registering.auth.register and auth.login methods. So, if you're not using the JS SDK, make sure to pass the received authentication tokens as explained in the API reference