Skip to main content

Allow users to change their passwords

caution

SuperTokens does not provide the UI for users to change/update their password, you will need to create the UI and setup a route on your backend to have this functionality.

In this section we will go over how you can create a route on your backend which can update a user's password. Calling this route will check if the old password is valid and update the user's profile with the new password.

Step 1: Creating the /change-password route#

  • You will need to create a route on your backend which is protected by the session verification middleware, this will ensure that only a authenticated user can access the protected route.
  • To learn more about how to use the session verfication middleware for other frameworks click here
import { verifySession } from "supertokens-node/recipe/session/framework/express";
import { SessionRequest } from "supertokens-node/framework/express"
import express from "express";

let app = express();

app.post("/change-password", verifySession(), async (req: SessionRequest, res: express.Response) => {
// TODO: see next steps
})

Step 2: Validate and update the user's password#

  • You can now use session object to retrive the logged in user's userId.
  • Use the recipe's sign in function and check if the old password is valid
  • Update the user's password.
// the following example uses express
import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
import { verifySession } from "supertokens-node/recipe/session/framework/express";
import { SessionRequest } from "supertokens-node/framework/express"
import express from "express";

let app = express();

app.post("/change-password", verifySession(), async (req: SessionRequest, res: express.Response) => {

// get the supertokens session object from the req
let session = req.session

// retrive the old password from the request body
let oldPassword = req.body.oldPassword

// retrive the new password from the request body
let updatedPassword = req.body.newPassword

// get the user's Id from the session
let userId = session!.getUserId()

// get the signed in user's email from the getUserById function
let userInfo = await ThirdPartyEmailPassword.getUserById(userId)

if (userInfo === undefined) {
throw new Error("Should never come here")
}

// call signin to check that input password is correct
let isPasswordValid = await ThirdPartyEmailPassword.emailPasswordSignIn(userInfo.email, oldPassword)

if (isPasswordValid.status !== "OK") {
// TODO: handle incorrect password error
return
}

// validate the new password
let passwordValidationResponse = passwordValidator(updatedPassword);
if(passwordValidationResponse !== undefined) {
// TODO: handle invalid password error
return
}


// update the user's password using updateEmailOrPassword
let response = await ThirdPartyEmailPassword.updateEmailOrPassword({
userId,
password: updatedPassword
})

// TODO: send successful password update response

})

function passwordValidator(value: string): string | undefined {
// length >= 8 && < 100
// must have a number and a character
// as per https://github.com/supertokens/supertokens-auth-react/issues/5#issuecomment-709512438

if (value.length < 8) {
return "Password must contain at least 8 characters, including a number";
}

if (value.length >= 100) {
return "Password's length must be lesser than 100 characters";
}

if (value.match(/^.*[A-Za-z]+.*$/) === null) {
return "Password must contain at least one alphabet";
}

if (value.match(/^.*[0-9]+.*$/) === null) {
return "Password must contain at least one number";
}

return undefined;
}

caution

If you have declared custom password validation policies please add the policies to the passwordValidator function defined in the code snippet above. The updateEmailOrPassword function will not apply custom password validation policies.

Step 3: Revoke all sessions associated with the user (optional)#

  • Revoking all sessions associated with the user will force them to reauthenticate with their new password.
// the following example uses express
import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
import Session from "supertokens-node/recipe/session";
import { verifySession } from "supertokens-node/recipe/session/framework/express";
import { SessionRequest } from "supertokens-node/framework/express"
import express from "express";

let app = express();

app.post("/change-password", verifySession(), async (req: SessionRequest, res: express.Response) => {

let userId = req.session!.getUserId();

/**
*
* ...
* see previous step
* ...
*
* */

// revoke all sessions for the user
await Session.revokeAllSessionsForUser(userId)

// revoke the current user's session, we do this to remove the auth cookies, logging out the user on the frontend.
await req.session!.revokeSession()

// TODO: send successful password update response

})