Customize the sign up form
Customize the sign up form by adding new fields or modifying existing ones.
Before you start
The next instructions assume that you have a working application that uses SuperTokens for authentication. If not, please refer to the quickstart guide and then return here.
What type of UI are you using?
Add extra fields
To include more fields in the sign up form, you need to first update both the frontend and backend configuration. Then, when the sing up payload arrives on the backend, you should add a way to persist those values.
1. Add the new fields to the UI
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [{
id: "name",
label: "Full name",
placeholder: "First name and last name"
}, {
id: "age",
label: "Your age",
placeholder: "How old are you?",
}, {
id: "country",
label: "Your country",
placeholder: "Where do you live?",
optional: true
}]
}
}
}),
Session.init()
]
});
Create custom components
By default, the new fields use input
elements.
To enable more complex fields you can create your own custom components.
You may need to disable the Shadow DOM if you're integrating with a different component library that requires you to import its own CSS. For instance, some component libraries, such as react-international-phone, might expect you to include their CSS alongside their components. For more information, refer to Disable use of shadow DOM.
Set the inputComponent
property for each field that you want to customize.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword"
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [{
id: "select-dropdown",
label: "Select Dropdown",
inputComponent: ({ value, name, onChange }) => (
<div data-supertokens="inputContainer">
<div data-supertokens="inputWrapper ">
<select
style={{
border: "unset",
borderRadius: "6px",
height: "32px",
backgroundColor: "#fafafa",
color: "#757575",
letterSpacing: "1.2px",
fontSize: "14px",
width: "100%",
marginRight: "25px",
padding: "1px 0 1px 10px"
}}
value={value}
name={name}
onChange={(e) => onChange(e.target.value)}>
<option value="" disabled hidden>
Select an option
</option>
<option value="option 1">Option 1</option>
<option value="option 2">Option 2</option>
<option value="option 3">Option 3</option>
</select>
</div>
</div>
),
optional: true,
},
{
id: "terms",
label: "",
optional: false,
nonOptionalErrorMsg: "You must accept the terms and conditions",
inputComponent: ({ name, onChange }) => (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "left",
marginBottom: " -12px",
}}>
<input name={name} type="checkbox" onChange={(e) => onChange(e.target.checked.toString())}></input>
<span style={{ marginLeft: 5 }}>
I agree to the{" "}
<a href="https://supertokens.com/legal/terms-and-conditions" data-supertokens="link">
Terms and Conditions
</a>
</span>
</div>
),
}]
}
}
}),
Session.init()
]
});
2. Include the extra fields in the backend configuration
Change the Backend SDK initialization call to ensure that the system processes the new fields when a new user registers.
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
signUpFeature: {
formFields: [{
id: "name"
}, {
id: "age"
}, {
id: "country",
optional: true
}]
}
}),
Session.init({ /* ... */ })
]
});
3. Save the values after a successful sign up
Use the signUpPOST
API function to process the field values and persist them.
SuperTokens does not store custom form fields. You can either save them in your database or use the User Metadata feature .
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
override: {
apis: (originalImplementation) => {
return {
...originalImplementation,
signUpPOST: async function (input) {
if (originalImplementation.signUpPOST === undefined) {
throw Error("Should never come here");
}
// First we call the original implementation of signUpPOST.
let response = await originalImplementation.signUpPOST(input);
// Post sign up response, we check if it was successful
if (response.status === "OK") {
// These are the input form fields values that the user used while signing up
let formFields = input.formFields;
}
return response;
}
}
}
}
}),
Session.init({ /* ... */ })
]
});
Customize each form field
Modify labels and placeholders
To change the labels and placeholders of the fields, update the formFields
property, in the recipe configuration.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword"
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [{
id: "email",
label: "customFieldName",
placeholder: "Custom value"
}]
}
}
}),
Session.init()
]
});
Set default values
Add a getDefaultValue
option to the formFields
configuration to set default values.
Keep in mind that the function needs to return a string.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword"
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [{
id: "email",
label: "Your Email",
getDefaultValue: () => "john.doe@gmail.com"
}, {
id: "name",
label: "Full name",
getDefaultValue: () => "John Doe",
}]
}
}
}),
Session.init()
]
});
Change the optional error message
When you try to submit the login form without filling in the required fields, the UI, by default, shows an error stating that the Field is not optional
.
To customize this message set the nonOptionalErrorMsg
property to a custom string.
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword"
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [{
id: "email",
label: "Your Email",
placeholder: "Email",
nonOptionalErrorMsg: "Please add your email"
}, {
id: "name",
label: "Full name",
placeholder: "Name",
nonOptionalErrorMsg: "Full name is required",
}]
}
}
}),
Session.init()
]
});
Change the field order
To customize the order of fields in your sign up form, override the EmailPasswordSignUpForm
component.
Use the next example as a reference.
Do you use react-router-dom?
import React from "react";
import { SuperTokensWrapper } from "supertokens-auth-react";
import { EmailPasswordComponentsOverrideProvider } from "supertokens-auth-react/recipe/emailpassword";
function App() {
return (
<SuperTokensWrapper>
<EmailPasswordComponentsOverrideProvider
components={{
EmailPasswordSignUpForm_Override: ({ DefaultComponent, ...props }) => {
return (
<DefaultComponent
{...props}
formFields={[
props.formFields.find(({ id }) => id === 'name')!,
props.formFields.find(({ id }) => id === 'email')!,
props.formFields.find(({ id }) => id === 'password')!,
]}
/>
);
},
}}>
{/* Rest of the JSX */}
</EmailPasswordComponentsOverrideProvider>
</SuperTokensWrapper>
);
}
export default App;
Change field validators
1. Update the frontend configuration
Add a validate
method to any of your formFields
.
The following example shows how to add age verification to the form:
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [{
id: "name",
label: "Full name",
placeholder: "First name and last name"
}, {
id: "age",
label: "Your age",
placeholder: "How old are you?",
optional: true,
/* Validation method to make sure that age is above 18 */
validate: async (value) => {
if (parseInt(value) > 18) {
return undefined; // means that there is no error
}
return "You must be over 18 to register";
}
}, {
id: "country",
label: "Your country",
placeholder: "Where do you live?",
optional: true
}]
}
}
}),
Session.init()
]
});
2. Update the backend configuration
Add validate
functions to each of the form fields, in the backend SDK initialization call.
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
signUpFeature: {
formFields: [{
id: "name"
}, {
id: "age",
/* Validation method to make sure that age >= 18 */
validate: async (value, tenantId) => {
if (parseInt(value) >= 18) {
return undefined; // means that there is no error
}
return "You must be over 18 to register";
}
}, {
id: "country",
optional: true
}]
}
}),
Session.init({
})
]
});
Notice the tenantId
argument passed into the validate
function. Using that, you can define custom logic per tenant. For example, you can define different password policies for different tenants.
Change the default email and password validators
By default, SuperTokens adds an email and a password validator to the sign up form.
- The default email validator makes sure that the provided email is in the correct email format.
- The default password validator makes sure that the provided password:
- has a minimum of 8 characters.
- contains at least one lowercase character
- contains at least one number
To add your own validators follow the steps described initially in this section.
- The email validator that you define for sign up is also applied automatically to sign in.
- The password validator that you define for sign up is also applied automatically to reset password forms.
Here is an example of what you need to change.
1. Update the frontend configuration
import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
EmailPassword.init({
signInAndUpFeature: {
signUpForm: {
formFields: [{
id: "email",
label: "...",
validate: async (value) => {
// Your own validation returning a string or undefined if no errors.
return "...";
}
}, {
id: "password",
label: "...",
validate: async (value) => {
// Your own validation returning a string or undefined if no errors.
return "...";
}
}]
}
}
})
]
});
1. Update the backend configuration
import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
supertokens: {
connectionURI: "...",
},
recipeList: [
EmailPassword.init({
signUpFeature: {
formFields: [{
id: "email",
validate: async (value, tenantId) => {
// Your own validation returning a string or undefined if no errors.
return "...";
}
}, {
id: "password",
validate: async (value, tenantId) => {
// Your own validation returning a string or undefined if no errors.
return "...";
}
}]
}
}),
]
});
Add terms of service and privacy policy links
To add "Terms of service" and "Privacy policy" links to your sign up page add the links in the frontend SDK initialization call. Based on the provided configuration the data renders in the following way:
- Provided both links: "By signing up, you agree to the Terms of Service and Privacy Policy"
- Provided only Terms of service link: "By signing up, you agree to the Terms of Service"
- Provided only Privacy policy link: "By signing up, you agree to the Privacy Policy"
import SuperTokens from "supertokens-auth-react";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
termsOfServiceLink: "https://example.com/terms-of-service",
privacyPolicyLink: "https://example.com/privacy-policy",
recipeList: [/* ... */]
});