Skip to content
Esc
navigateopen⌘Jpreview
Dashboard
On this page

Password reset

Learn how the password reset functionality works

Overview

The password reset feature consists of two actions: one in which a user requests a reset password link over email and another where the user sets the new password.

The password reset forms

UI type

The following images show how the password reset forms render when you are using the pre-built UI.

You see this if you navigate to /auth/reset-password.

UI to send password reset email

You see this if you navigate to /auth/reset-password?token=TOKEN.

UI to change password

The password reset email

This is how the email that gets delivered to the learner looks like:

Email UI for password reset email

You can find the source code of this template on GitHub. To customize the template check the email delivery section for more information.


Embed the reset form in a page

To embed the reset form in a page you can use the next steps.

1. Disable the default implementation

import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    EmailPassword.init({
      resetPasswordUsingTokenFeature: {
        disableDefaultUI: true,
      },
    }),
  ],
});
// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)

supertokensUIInit({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    supertokensUIEmailPassword.init({
      resetPasswordUsingTokenFeature: {
        disableDefaultUI: true,
      },
    }),
  ],
});

If you navigate to /auth/reset-password, you should not see the widget anymore.

2. Render the component yourself

Add the ResetPasswordUsingToken component in your app:

import React from "react";
import { ResetPasswordUsingToken } from "supertokens-auth-react/recipe/emailpassword/prebuiltui";

class ResetPasswordPage extends React.Component {
  render() {
    return (
      <div>
        <ResetPasswordUsingToken />
      </div>
    );
  }
}

3. Change the website path for reset password UI

This step is optional. The default path for this is component is /auth/reset-password.

If you are displaying this at some custom path, then you need to add additional configuration on the backend and frontend:

3.1 On the backend

import SuperTokens from "supertokens-node";
import EmailPassword from "supertokens-node/recipe/emailpassword";

SuperTokens.init({
  supertokens: {
    connectionURI: "...",
  },
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    EmailPassword.init({
      emailDelivery: {
        override: (originalImplementation) => {
          return {
            ...originalImplementation,
            sendEmail: async function (input) {
              if (input.type === "PASSWORD_RESET") {
                return originalImplementation.sendEmail({
                  ...input,
                  passwordResetLink: input.passwordResetLink.replace(
                    // This is: `<YOUR_WEBSITE_DOMAIN>/auth/reset-password`
                    "http://localhost:3000/auth/reset-password",
                    "http://localhost:3000/your/path",
                  ),
                });
              }
              return originalImplementation.sendEmail(input);
            },
          };
        },
      },
    }),
  ],
});
import (
	"strings"

	"github.com/supertokens/supertokens-golang/ingredients/emaildelivery"
	"github.com/supertokens/supertokens-golang/recipe/emailpassword"
	"github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels"
	"github.com/supertokens/supertokens-golang/supertokens"
)

func main() {
	supertokens.Init(supertokens.TypeInput{
		RecipeList: []supertokens.Recipe{
			emailpassword.Init(&epmodels.TypeInput{

				EmailDelivery: &emaildelivery.TypeInput{
					Override: func(originalImplementation emaildelivery.EmailDeliveryInterface) emaildelivery.EmailDeliveryInterface {
						ogSendEmail := *originalImplementation.SendEmail

						(*originalImplementation.SendEmail) = func(input emaildelivery.EmailType, userContext supertokens.UserContext) error {
							// This is: `<YOUR_WEBSITE_DOMAIN>/auth/reset-password`
							input.PasswordReset.PasswordResetLink = strings.Replace(
								input.PasswordReset.PasswordResetLink,
								"http://localhost:3000/auth/reset-password",
								"http://localhost:3000/your/path", 1,
							)
							return ogSendEmail(input, userContext)
						}
						return originalImplementation
					},
				},

			}),
		},
	})
}
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe.emailpassword.types import EmailDeliveryOverrideInput, EmailTemplateVars
from supertokens_python.recipe import emailpassword
from typing import Dict, Any
from supertokens_python.ingredients.emaildelivery.types import EmailDeliveryConfig

def custom_email_deliver(original_implementation: EmailDeliveryOverrideInput) -> EmailDeliveryOverrideInput:
    original_send_email = original_implementation.send_email

    async def send_email(template_vars: EmailTemplateVars, user_context: Dict[str, Any]) -> None:
        # This is: `<YOUR_WEBSITE_DOMAIN>/auth/reset-password`
        template_vars.password_reset_link = template_vars.password_reset_link.replace(
            "http://localhost:3000/auth/reset-password", "http://localhost:3000/your/path")
        return await original_send_email(template_vars, user_context)

    original_implementation.send_email = send_email
    return original_implementation

init(
    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
    framework='...',
    recipe_list=[
        emailpassword.init(
            email_delivery=EmailDeliveryConfig(override=custom_email_deliver)
        )
    ]
)

3.2 On the frontend

import SuperTokens from "supertokens-auth-react";
import EmailPassword from "supertokens-auth-react/recipe/emailpassword";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    EmailPassword.init({
      // The user will be taken to the custom path when they click on forgot password.
      getRedirectionURL: async (context) => {
        if (context.action === "RESET_PASSWORD") {
          return "/custom-reset-password-path";
        }
      },
    }),
  ],
});
// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)

supertokensUIInit({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    supertokensUIEmailPassword.init({
      // The user will be taken to the custom path when they click on forgot password.
      getRedirectionURL: async (context) => {
        if (context.action === "RESET_PASSWORD") {
          return "/custom-reset-password-path";
        }
      },
    }),
  ],
});

You can use the backend SDK to generate the reset password link as shown below:

import EmailPassword from "supertokens-node/recipe/emailpassword";

async function createResetPasswordLink(userId: string, email: string) {
  const linkResponse = await EmailPassword.createResetPasswordLink("public", userId, email);

  if (linkResponse.status === "OK") {
    console.log(linkResponse.link);
  } else {
    // user does not exist or is not an email password user
  }
}
import (
	"fmt"

	"github.com/supertokens/supertokens-golang/recipe/emailpassword"
)

func main() {
	userID := "..."

	linkRes, err := emailpassword.CreateResetPasswordLink("public", userID)
	if err != nil {
		// handle error
	}

	if linkRes.OK != nil {
		link := linkRes.OK.Link
		fmt.Println(link)

	} else {
		// user does not exist or is not an email password user
	}
}
from supertokens_python.recipe.emailpassword.asyncio import create_reset_password_link

async def create_link(user_id: str, email: str):
    link = await create_reset_password_link("public", user_id, email)

    if isinstance(link, str):
        print(link)
    else:
        print("user does not exist or is not an email password user")
from supertokens_python.recipe.emailpassword.syncio import create_reset_password_link

def create_link(user_id: str, email: str):
    link = create_reset_password_link("public", user_id, email)

    if isinstance(link, str):
        print(link)
    else:
        print("user does not exist or is not an email password user")

By default, the password reset link’s lifetime is 1 hour. You can change this via a core’s configuration (time in milliseconds):

# Here we set the lifetime to 2 hours.

docker run \
    -p 3567:3567 \
    -e EMAIL_VERIFICATION_TOKEN_LIFETIME=7200000 \
    -d supertokens/supertokens-<db_name>
# You need to add the following to the config.yaml file.
# The file path can be found by running the "supertokens --help" command

email_verification_token_lifetime: 7200000

See also

API reference

API schema and response details