Which frontend SDK do you use?
supertokens-auth-react
supertokens-web-js / mobile
Changes to email password flow
We start by disabling the public facing sign up API on the backend:
- NodeJS
 - GoLang
 - Python
 
import SuperTokens from "supertokens-node";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
SuperTokens.init({    appInfo: {        apiDomain: "...",        appName: "...",        websiteDomain: "..."    },    supertokens: {        connectionURI: "...",    },    recipeList: [        ThirdPartyEmailPassword.init({            override: {                apis: (originalImplementation) => {                    return {                        ...originalImplementation,                        emailPasswordSignUpPOST: undefined,                    }                }            }        })    ]});import (    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword"    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels"    "github.com/supertokens/supertokens-golang/supertokens")
func main() {    supertokens.Init(supertokens.TypeInput{        RecipeList: []supertokens.Recipe{            thirdpartyemailpassword.Init(&tpepmodels.TypeInput{                Override: &tpepmodels.OverrideStruct{                    APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface {                        originalImplementation.EmailPasswordSignUpPOST = nil                        return originalImplementation                    },                },            }),        },    })}from supertokens_python import init, InputAppInfofrom supertokens_python.recipe import thirdpartyemailpasswordfrom supertokens_python.recipe.thirdpartyemailpassword.interfaces import APIInterface
def apis_override(original_impl: APIInterface):    original_impl.disable_emailpassword_sign_up_post = True    return original_impl
init(    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),    framework='...',     recipe_list=[        thirdpartyemailpassword.init(            override=thirdpartyemailpassword.InputOverrideConfig(                apis=apis_override            ),        )    ])The next step is to disable the sign up button on the sign in form. This can be done by using CSS to hide the sign up button:
- ReactJS
 - Angular
 - Vue
 
import SuperTokens from "supertokens-auth-react";import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
SuperTokens.init({    appInfo: {        apiDomain: "...",        appName: "...",        websiteDomain: "..."    },    recipeList: [        ThirdPartyEmailPassword.init({            signInAndUpFeature: {                style: {                    "headerSubtitle": {                        display: "none"                    }                },                providers: [/* ... */],            },        }),    ]});/app/auth/supertokensAuthComponent.tsx
import SuperTokens from "supertokens-auth-react";import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
SuperTokens.init({    appInfo: {        apiDomain: "...",        appName: "...",        websiteDomain: "..."    },    recipeList: [        ThirdPartyEmailPassword.init({            signInAndUpFeature: {                style: {                    "headerSubtitle": {                        display: "none"                    }                },                providers: [/* ... */],            },        }),    ]});/components/Supertokens.tsx
import SuperTokens from "supertokens-auth-react";import ThirdPartyEmailPassword from "supertokens-auth-react/recipe/thirdpartyemailpassword";
SuperTokens.init({    appInfo: {        apiDomain: "...",        appName: "...",        websiteDomain: "..."    },    recipeList: [        ThirdPartyEmailPassword.init({            signInAndUpFeature: {                style: {                    "headerSubtitle": {                        display: "none"                    }                },                providers: [/* ... */],            },        }),    ]});To create email password users, you will need to make an API on your backend which will:
- Call the 
emailPasswordSignUpfunction from our backend SDK using that user's email and a fake password. This fake password should be unguessable and should be shared across all invited users. - Generate a password reset link and send that as an invite link to the user's email.
 - In the code below, we also make sure that the user who calls this API has the 
adminrole - but you can change this part to whatever you like. 
Once the user clicks the link, they will be shown a page asking them to input their password after which, they can login.
- NodeJS
 - GoLang
 - Python
 
- Express
 - Hapi
 - Fastify
 - Koa
 - Loopback
 - AWS Lambda / Netlify
 - Next.js
 - NestJS
 
import express from "express";import { verifySession } from "supertokens-node/recipe/session/framework/express";import { SessionRequest } from "supertokens-node/framework/express";import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
let app = express();
app.post("/create-user", verifySession({    overrideGlobalClaimValidators: async function (globalClaimValidators) {        return [...globalClaimValidators,        UserRoles.UserRoleClaim.validators.includes("admin")]    }}), async (req: SessionRequest, res) => {    let email = req.body.email;
    let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);    if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {        res.status(400).send("User already exists");        return;    }
    // we successfully created the user. Now we should send them their invite link    let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
    if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {        throw new Error("Should never come here");    }
    let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token    await ThirdPartyEmailPassword.sendEmail({        type: "PASSWORD_RESET",        passwordResetLink: inviteLink,        user: {            email: signUpResult.user.email,            id: signUpResult.user.id        }    });    res.send("Success");});import Hapi from "@hapi/hapi";import { verifySession } from "supertokens-node/recipe/session/framework/hapi";import { SessionRequest } from "supertokens-node/framework/hapi";import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
let server = Hapi.server({ port: 8000 });
server.route({    path: "/create-user",    method: "post",    options: {        pre: [            {                method: verifySession({                    overrideGlobalClaimValidators: async function (globalClaimValidators) {                        return [...globalClaimValidators,                        UserRoles.UserRoleClaim.validators.includes("admin")]                    }                })            },        ],    },    handler: async (req: SessionRequest, res) => {        let email = (req.payload.valueOf() as any).email;
        let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);        if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {            res.response("User already exists").code(400);            return;        }
        // we successfully created the user. Now we should send them their invite link        let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
        if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {            throw new Error("Should never come here");        }
        let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token        await ThirdPartyEmailPassword.sendEmail({            type: "PASSWORD_RESET",            passwordResetLink: inviteLink,            user: {                email: signUpResult.user.email,                id: signUpResult.user.id            }        });        res.response("Success").code(200);    }})import Fastify from "fastify";import { verifySession } from "supertokens-node/recipe/session/framework/fastify";import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
let fastify = Fastify();
fastify.post("/create-user", {    preHandler: verifySession({        overrideGlobalClaimValidators: async function (globalClaimValidators) {            return [...globalClaimValidators,            UserRoles.UserRoleClaim.validators.includes("admin")]        }    }),}, async (req, res) => {    let email = req.body.email;
    let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);    if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {        res.code(400).send("User already exists");        return;    }
    // we successfully created the user. Now we should send them their invite link    let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
    if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {        throw new Error("Should never come here");    }
    let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token    await ThirdPartyEmailPassword.sendEmail({        type: "PASSWORD_RESET",        passwordResetLink: inviteLink,        user: {            email: signUpResult.user.email,            id: signUpResult.user.id        }    });    res.code(200).send("Success");});import { verifySession } from "supertokens-node/recipe/session/framework/awsLambda";import { SessionEventV2 } from "supertokens-node/framework/awsLambda";import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
async function createUser(awsEvent: SessionEventV2) {    let email = JSON.parse(awsEvent.body!).email;
    let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);    if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {        return {            statusCode: '400',            body: "User already exists"        }    }
    // we successfully created the user. Now we should send them their invite link    let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
    if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {        throw new Error("Should never come here");    }
    let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token    await ThirdPartyEmailPassword.sendEmail({        type: "PASSWORD_RESET",        passwordResetLink: inviteLink,        user: {            email: signUpResult.user.email,            id: signUpResult.user.id        }    });    return {        statusCode: '200',        body: "Success"    }};
exports.handler = verifySession(createUser, {    overrideGlobalClaimValidators: async function (globalClaimValidators) {        return [...globalClaimValidators,        UserRoles.UserRoleClaim.validators.includes("admin")]    }});import KoaRouter from "koa-router";import { verifySession } from "supertokens-node/recipe/session/framework/koa";import { SessionContext } from "supertokens-node/framework/koa";import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
let router = new KoaRouter();
router.post("/create-user", verifySession({    overrideGlobalClaimValidators: async function (globalClaimValidators) {        return [...globalClaimValidators,        UserRoles.UserRoleClaim.validators.includes("admin")]    }}), async (ctx: SessionContext, next) => {    let email = (ctx.body as any).email;
    let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);    if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {        ctx.status = 400;        ctx.body = "User already exists";        return;    }
    // we successfully created the user. Now we should send them their invite link    let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
    if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {        throw new Error("Should never come here");    }
    let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token    await ThirdPartyEmailPassword.sendEmail({        type: "PASSWORD_RESET",        passwordResetLink: inviteLink,        user: {            email: signUpResult.user.email,            id: signUpResult.user.id        }    });    ctx.status = 200;    ctx.body = "Success";});import { inject, intercept } from "@loopback/core";import { RestBindings, MiddlewareContext, post, response } from "@loopback/rest";import { verifySession } from "supertokens-node/recipe/session/framework/loopback";import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
class LikeComment {    constructor(@inject(RestBindings.Http.CONTEXT) private ctx: MiddlewareContext) { }    @post("/create-user")    @intercept(verifySession({        overrideGlobalClaimValidators: async function (globalClaimValidators) {            return [...globalClaimValidators,            UserRoles.UserRoleClaim.validators.includes("admin")]        }    }))    async handler() {        let email = "" // TODO: get from request body
        let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);        if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {            // TODO: send 400 response to the client.            return;        }
        // we successfully created the user. Now we should send them their invite link        let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
        if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {            throw new Error("Should never come here");        }
        let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token        await ThirdPartyEmailPassword.sendEmail({            type: "PASSWORD_RESET",            passwordResetLink: inviteLink,            user: {                email: signUpResult.user.email,                id: signUpResult.user.id            }        });        // TODO: send 200 response to the client    }}import { superTokensNextWrapper } from 'supertokens-node/nextjs'import { verifySession } from "supertokens-node/recipe/session/framework/express";import { SessionRequest } from "supertokens-node/framework/express";import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
export default async function createUser(req: SessionRequest, res: any) {    await superTokensNextWrapper(        async (next) => {            await verifySession({                overrideGlobalClaimValidators: async function (globalClaimValidators) {                    return [...globalClaimValidators,                    UserRoles.UserRoleClaim.validators.includes("admin")]                }            })(req, res, next);        },        req,        res    )
    let email = req.body.email;
    let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);    if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {        res.status(400).json({ message: 'User already exists' })        return;    }
    // we successfully created the user. Now we should send them their invite link    let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
    if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {        throw new Error("Should never come here");    }
    let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token    await ThirdPartyEmailPassword.sendEmail({        type: "PASSWORD_RESET",        passwordResetLink: inviteLink,        user: {            email: signUpResult.user.email,            id: signUpResult.user.id        }    });    res.status(200).json({ message: 'Success' })}import { Controller, Post, UseGuards, Session } from "@nestjs/common";import { SessionContainer } from "supertokens-node/recipe/session";import { AuthGuard } from './auth/auth.guard';import UserRoles from "supertokens-node/recipe/userroles";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn";
@Controller()export class CreateUserController {  @Post('create-user')  @UseGuards(new AuthGuard({    overrideGlobalClaimValidators: async function (globalClaimValidators: any) {      return [...globalClaimValidators,      UserRoles.UserRoleClaim.validators.includes("admin")]    }  })) // For more information about this guard please read our NestJS guide.  async postAPI(@Session() session: SessionContainer): Promise<void> {    let email = "" // TODO: get from request body
    let signUpResult = await ThirdPartyEmailPassword.emailPasswordSignUp(email, FAKE_PASSWORD);    if (signUpResult.status === "EMAIL_ALREADY_EXISTS_ERROR") {      // TODO: send 400 response to the client.      return;    }
    // we successfully created the user. Now we should send them their invite link    let passwordResetToken = await ThirdPartyEmailPassword.createResetPasswordToken(signUpResult.user.id);
    if (passwordResetToken.status === "UNKNOWN_USER_ID_ERROR") {      throw new Error("Should never come here");    }
    let inviteLink = "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.token    await ThirdPartyEmailPassword.sendEmail({      type: "PASSWORD_RESET",      passwordResetLink: inviteLink,      user: {        email: signUpResult.user.email,        id: signUpResult.user.id      }    });    // TODO: send 200 response to the client  }}- Chi
 - net/http
 - Gin
 - Mux
 
import (    "net/http"
    "github.com/supertokens/supertokens-golang/ingredients/emaildelivery"    "github.com/supertokens/supertokens-golang/recipe/session"    "github.com/supertokens/supertokens-golang/recipe/session/claims"    "github.com/supertokens/supertokens-golang/recipe/session/sessmodels"    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword"    "github.com/supertokens/supertokens-golang/recipe/userroles/userrolesclaims"    "github.com/supertokens/supertokens-golang/supertokens")
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
func main() {    _ = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
        session.VerifySession(&sessmodels.VerifySessionOptions{            OverrideGlobalClaimValidators: func(globalClaimValidators []claims.SessionClaimValidator, sessionContainer sessmodels.SessionContainer, userContext supertokens.UserContext) ([]claims.SessionClaimValidator, error) {                globalClaimValidators = append(globalClaimValidators, userrolesclaims.PermissionClaimValidators.Includes("admin", nil, nil))                return globalClaimValidators, nil            },        }, createUserAPI).ServeHTTP(rw, r)    })}
func createUserAPI(w http.ResponseWriter, r *http.Request) {    email := "" // TODO: read email from request body
    signUpResult, err := thirdpartyemailpassword.EmailPasswordSignUp(email, FAKE_PASSWORD)    if err != nil {        // TODO: send 500 to the client        return    }
    if signUpResult.EmailAlreadyExistsError != nil {        // TODO: send 400 to the client        return    }
    // we successfully created the user. Now we should send them their invite link    passwordResetToken, err := thirdpartyemailpassword.CreateResetPasswordToken(signUpResult.OK.User.ID)    if err != nil {        // TODO: send 500 to the client        return    }
    inviteLink := "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.OK.Token    err = thirdpartyemailpassword.SendEmail(emaildelivery.EmailType{        PasswordReset: &emaildelivery.PasswordResetType{            User: emaildelivery.User{                ID:    signUpResult.OK.User.ID,                Email: signUpResult.OK.User.Email,            },            PasswordResetLink: inviteLink,        },    })    if err != nil {        // TODO: send 500 to the client        return    }    // TODO: send 200 to the client}import (    "net/http"
    "github.com/gin-gonic/gin"    "github.com/supertokens/supertokens-golang/ingredients/emaildelivery"    "github.com/supertokens/supertokens-golang/recipe/session"    "github.com/supertokens/supertokens-golang/recipe/session/claims"    "github.com/supertokens/supertokens-golang/recipe/session/sessmodels"    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword"    "github.com/supertokens/supertokens-golang/recipe/userroles/userrolesclaims"    "github.com/supertokens/supertokens-golang/supertokens")
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
func main() {    router := gin.New()
    // Wrap the API handler in session.VerifySession    router.POST("/create-user", verifySession(&sessmodels.VerifySessionOptions{        OverrideGlobalClaimValidators: func(globalClaimValidators []claims.SessionClaimValidator, sessionContainer sessmodels.SessionContainer, userContext supertokens.UserContext) ([]claims.SessionClaimValidator, error) {            globalClaimValidators = append(globalClaimValidators, userrolesclaims.PermissionClaimValidators.Includes("admin", nil, nil))            return globalClaimValidators, nil        },    }), createUserAPI)}
// This is a function that wraps the supertokens verification function// to work the ginfunc verifySession(options *sessmodels.VerifySessionOptions) gin.HandlerFunc {    return func(c *gin.Context) {        session.VerifySession(options, func(rw http.ResponseWriter, r *http.Request) {            c.Request = c.Request.WithContext(r.Context())            c.Next()        })(c.Writer, c.Request)        // we call Abort so that the next handler in the chain is not called, unless we call Next explicitly        c.Abort()    }}
func createUserAPI(c *gin.Context) {    email := "" // TODO: read email from request body
    signUpResult, err := thirdpartyemailpassword.EmailPasswordSignUp(email, FAKE_PASSWORD)    if err != nil {        // TODO: send 500 to the client        return    }
    if signUpResult.EmailAlreadyExistsError != nil {        // TODO: send 400 to the client        return    }
    // we successfully created the user. Now we should send them their invite link    passwordResetToken, err := thirdpartyemailpassword.CreateResetPasswordToken(signUpResult.OK.User.ID)    if err != nil {        // TODO: send 500 to the client        return    }
    inviteLink := "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.OK.Token    err = thirdpartyemailpassword.SendEmail(emaildelivery.EmailType{        PasswordReset: &emaildelivery.PasswordResetType{            User: emaildelivery.User{                ID:    signUpResult.OK.User.ID,                Email: signUpResult.OK.User.Email,            },            PasswordResetLink: inviteLink,        },    })    if err != nil {        // TODO: send 500 to the client        return    }    // TODO: send 200 to the client}import (    "net/http"
    "github.com/go-chi/chi"    "github.com/supertokens/supertokens-golang/ingredients/emaildelivery"    "github.com/supertokens/supertokens-golang/recipe/session"    "github.com/supertokens/supertokens-golang/recipe/session/claims"    "github.com/supertokens/supertokens-golang/recipe/session/sessmodels"    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword"    "github.com/supertokens/supertokens-golang/recipe/userroles/userrolesclaims"    "github.com/supertokens/supertokens-golang/supertokens")
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
func main() {    r := chi.NewRouter()
    // Wrap the API handler in session.VerifySession    r.Post("/create-user", session.VerifySession(&sessmodels.VerifySessionOptions{        OverrideGlobalClaimValidators: func(globalClaimValidators []claims.SessionClaimValidator, sessionContainer sessmodels.SessionContainer, userContext supertokens.UserContext) ([]claims.SessionClaimValidator, error) {            globalClaimValidators = append(globalClaimValidators, userrolesclaims.PermissionClaimValidators.Includes("admin", nil, nil))            return globalClaimValidators, nil        },    }, createUserAPI))}
func createUserAPI(w http.ResponseWriter, r *http.Request) {    email := "" // TODO: read email from request body
    signUpResult, err := thirdpartyemailpassword.EmailPasswordSignUp(email, FAKE_PASSWORD)    if err != nil {        // TODO: send 500 to the client        return    }
    if signUpResult.EmailAlreadyExistsError != nil {        // TODO: send 400 to the client        return    }
    // we successfully created the user. Now we should send them their invite link    passwordResetToken, err := thirdpartyemailpassword.CreateResetPasswordToken(signUpResult.OK.User.ID)    if err != nil {        // TODO: send 500 to the client        return    }
    inviteLink := "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.OK.Token    err = thirdpartyemailpassword.SendEmail(emaildelivery.EmailType{        PasswordReset: &emaildelivery.PasswordResetType{            User: emaildelivery.User{                ID:    signUpResult.OK.User.ID,                Email: signUpResult.OK.User.Email,            },            PasswordResetLink: inviteLink,        },    })    if err != nil {        // TODO: send 500 to the client        return    }    // TODO: send 200 to the client}import (    "net/http"
    "github.com/gorilla/mux"    "github.com/supertokens/supertokens-golang/ingredients/emaildelivery"    "github.com/supertokens/supertokens-golang/recipe/session"    "github.com/supertokens/supertokens-golang/recipe/session/claims"    "github.com/supertokens/supertokens-golang/recipe/session/sessmodels"    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword"    "github.com/supertokens/supertokens-golang/recipe/userroles/userrolesclaims"    "github.com/supertokens/supertokens-golang/supertokens")
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
func main() {    router := mux.NewRouter()
    // Wrap the API handler in session.VerifySession    router.HandleFunc("/create-user", session.VerifySession(&sessmodels.VerifySessionOptions{        OverrideGlobalClaimValidators: func(globalClaimValidators []claims.SessionClaimValidator, sessionContainer sessmodels.SessionContainer, userContext supertokens.UserContext) ([]claims.SessionClaimValidator, error) {            globalClaimValidators = append(globalClaimValidators, userrolesclaims.PermissionClaimValidators.Includes("admin", nil, nil))            return globalClaimValidators, nil        },    }, createUserAPI)).Methods(http.MethodPost)}
func createUserAPI(w http.ResponseWriter, r *http.Request) {    email := "" // TODO: read email from request body
    signUpResult, err := thirdpartyemailpassword.EmailPasswordSignUp(email, FAKE_PASSWORD)    if err != nil {        // TODO: send 500 to the client        return    }
    if signUpResult.EmailAlreadyExistsError != nil {        // TODO: send 400 to the client        return    }
    // we successfully created the user. Now we should send them their invite link    passwordResetToken, err := thirdpartyemailpassword.CreateResetPasswordToken(signUpResult.OK.User.ID)    if err != nil {        // TODO: send 500 to the client        return    }
    inviteLink := "http://localhost:3000/auth/reset-password?token=" + passwordResetToken.OK.Token    err = thirdpartyemailpassword.SendEmail(emaildelivery.EmailType{        PasswordReset: &emaildelivery.PasswordResetType{            User: emaildelivery.User{                ID:    signUpResult.OK.User.ID,                Email: signUpResult.OK.User.Email,            },            PasswordResetLink: inviteLink,        },    })    if err != nil {        // TODO: send 500 to the client        return    }    // TODO: send 200 to the client}- FastAPI
 - Flask
 - Django
 
from supertokens_python.recipe.session.framework.fastapi import verify_sessionfrom supertokens_python.recipe.session import SessionContainerfrom fastapi import Dependsfrom supertokens_python.recipe.userroles import UserRoleClaimfrom supertokens_python.recipe.thirdpartyemailpassword.asyncio import emailpassword_sign_up, create_reset_password_token, send_emailfrom supertokens_python.recipe.thirdpartyemailpassword.interfaces import EmailPasswordSignUpEmailAlreadyExistsError, CreateResetPasswordWrongUserIdErrorfrom supertokens_python.recipe.emailpassword.types import PasswordResetEmailTemplateVars, PasswordResetEmailTemplateVarsUser
FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
@app.post('/create-user')  async def create_user(session: SessionContainer = Depends(verify_session(    override_global_claim_validators=lambda global_validators, session, user_context: global_validators +    [UserRoleClaim.validators.includes("admin")]))):    email = ""  # TODO: read from request body.    sign_up_result = await emailpassword_sign_up(email, FAKE_PASSWORD)
    if isinstance(sign_up_result, EmailPasswordSignUpEmailAlreadyExistsError):        # TODO: send 400 response to client        return
    # we successfully created the user. Now we should send them their invite link    password_reset_token = await create_reset_password_token(sign_up_result.user.user_id)
    if isinstance(password_reset_token, CreateResetPasswordWrongUserIdError):        raise Exception("Should never come here")
    invite_link = "http://localhost:3000/auth/reset-password?token=" + \        password_reset_token.token
    await send_email(input_=PasswordResetEmailTemplateVars(PasswordResetEmailTemplateVarsUser(sign_up_result.user.user_id, sign_up_result.user.email), invite_link))
    # TODO: send 200 responspe to clientfrom supertokens_python.recipe.session.framework.flask import verify_sessionfrom supertokens_python.recipe.userroles import UserRoleClaimfrom supertokens_python.recipe.thirdpartyemailpassword.syncio import emailpassword_sign_up, create_reset_password_token, send_emailfrom supertokens_python.recipe.thirdpartyemailpassword.interfaces import EmailPasswordSignUpEmailAlreadyExistsError, CreateResetPasswordWrongUserIdErrorfrom supertokens_python.recipe.emailpassword.types import PasswordResetEmailTemplateVars, PasswordResetEmailTemplateVarsUser
FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
@app.route('/create_user', methods=['POST'])  @verify_session(    override_global_claim_validators=lambda global_validators, session, user_context: global_validators +    [UserRoleClaim.validators.includes("admin")])def create_user():    email = ""  # TODO: read from request body.    sign_up_result = emailpassword_sign_up(email, FAKE_PASSWORD)
    if isinstance(sign_up_result, EmailPasswordSignUpEmailAlreadyExistsError):        # TODO: send 400 response to client        return
    # we successfully created the user. Now we should send them their invite link    password_reset_token = create_reset_password_token(        sign_up_result.user.user_id)
    if isinstance(password_reset_token, CreateResetPasswordWrongUserIdError):        raise Exception("Should never come here")
    invite_link = "http://localhost:3000/auth/reset-password?token=" + \        password_reset_token.token
    send_email(input_=PasswordResetEmailTemplateVars(PasswordResetEmailTemplateVarsUser(        sign_up_result.user.user_id, sign_up_result.user.email), invite_link))
    # TODO: send 200 responspe to clientfrom supertokens_python.recipe.session.framework.django.asyncio import verify_sessionfrom django.http import HttpRequestfrom supertokens_python.recipe.userroles import UserRoleClaimfrom supertokens_python.recipe.thirdpartyemailpassword.asyncio import emailpassword_sign_up, create_reset_password_token, send_emailfrom supertokens_python.recipe.thirdpartyemailpassword.interfaces import EmailPasswordSignUpEmailAlreadyExistsError, CreateResetPasswordWrongUserIdErrorfrom supertokens_python.recipe.emailpassword.types import PasswordResetEmailTemplateVars, PasswordResetEmailTemplateVarsUser
FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
@verify_session(    override_global_claim_validators=lambda global_validators, session, user_context: global_validators +    [UserRoleClaim.validators.includes("admin")])async def create_user(request: HttpRequest):    email = ""  # TODO: read from request body.    sign_up_result = await emailpassword_sign_up(email, FAKE_PASSWORD)
    if isinstance(sign_up_result, EmailPasswordSignUpEmailAlreadyExistsError):        # TODO: send 400 response to client        return
    # we successfully created the user. Now we should send them their invite link    password_reset_token = await create_reset_password_token(sign_up_result.user.user_id)
    if isinstance(password_reset_token, CreateResetPasswordWrongUserIdError):        raise Exception("Should never come here")
    invite_link = "http://localhost:3000/auth/reset-password?token=" + \        password_reset_token.token
    await send_email(input_=PasswordResetEmailTemplateVars(PasswordResetEmailTemplateVarsUser(sign_up_result.user.user_id, sign_up_result.user.email), invite_link))
    # TODO: send 200 responspe to client- The code above uses the default password reset path for the invite link (
/auth/reset-password). If you are using the pre built UI, this will show password reset page to the user. If you want to show a different UI to the user, then you can use a different path in the link and make your own UI on that path. If you are making your own UI, you can use the password reset functions provided by our frontend SDK to call the password reset token consumption API from the frontend. - The 
sendEmailfunction used above sends the default password reset email (or the one you customised using theemailDeliveryconfig). Instead, you can also send a different email to the user specifically for the invite flow. - You can change the lifetime of the password reset token, and therefore the invite link, by following this guide.
 
The final step is to:
- Override the 
emailPasswordSignInrecipe function on the backend to reject sign in attempts which use the fake password. This is done so that if someone knows the fake password, they cannot sign in as the invited user before they reset their password. - Override the change password functions to prevent users from changing their password to the fake password.
 
- NodeJS
 - GoLang
 - Python
 
import SuperTokens from "supertokens-node";import ThirdPartyEmailPassword from "supertokens-node/recipe/thirdpartyemailpassword";
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
SuperTokens.init({    appInfo: {        apiDomain: "...",        appName: "...",        websiteDomain: "..."    },    supertokens: {        connectionURI: "...",    },    recipeList: [        ThirdPartyEmailPassword.init({            override: {                apis: (originalImplementation) => {                    // ... override from previous code snippets...                    return originalImplementation                },                functions: (originalImplementation) => {                    return {                        ...originalImplementation,                        updateEmailOrPassword: async function (input) {                            // This can be called on the backend                            // in your own APIs                            if (input.password === FAKE_PASSWORD) {                                throw new Error("Use a different password")                            }                            return originalImplementation.updateEmailOrPassword(input);                        },                        resetPasswordUsingToken: async function (input) {                            // This is called during the password reset flow                            // when the user enters their new password                            if (input.newPassword === FAKE_PASSWORD) {                                return {                                    status: "RESET_PASSWORD_INVALID_TOKEN_ERROR"                                }                            }                            return originalImplementation.resetPasswordUsingToken(input);                        },                        emailPasswordSignIn: async function (input) {                            // This is called in the email password sign in API                            if (input.password === FAKE_PASSWORD) {                                return {                                    status: "WRONG_CREDENTIALS_ERROR"                                }                            }                            return originalImplementation.emailPasswordSignIn(input);                        },                    }                }            }        })    ]});import (    "errors"
    "github.com/supertokens/supertokens-golang/recipe/emailpassword/epmodels"    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword"    "github.com/supertokens/supertokens-golang/recipe/thirdpartyemailpassword/tpepmodels"    "github.com/supertokens/supertokens-golang/supertokens")
const FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
func main() {    supertokens.Init(supertokens.TypeInput{        RecipeList: []supertokens.Recipe{            thirdpartyemailpassword.Init(&tpepmodels.TypeInput{                Override: &tpepmodels.OverrideStruct{                    APIs: func(originalImplementation tpepmodels.APIInterface) tpepmodels.APIInterface {                        // ...from previous code snippets...                        return originalImplementation                    },                    Functions: func(originalImplementation tpepmodels.RecipeInterface) tpepmodels.RecipeInterface {                        ogResetPasswordUsingToken := *originalImplementation.ResetPasswordUsingToken                        ogEmailPasswordSignIn := *originalImplementation.EmailPasswordSignIn                        ogUpdateEmailOrPassword := *originalImplementation.UpdateEmailOrPassword
                        (*originalImplementation.UpdateEmailOrPassword) = func(userId string, email, password *string, userContext supertokens.UserContext) (epmodels.UpdateEmailOrPasswordResponse, error) {                            // This can be called on the backend                            // in your own APIs                            if password != nil && *password == FAKE_PASSWORD {                                return epmodels.UpdateEmailOrPasswordResponse{}, errors.New("use a different password")                            }                            return ogUpdateEmailOrPassword(userId, email, password, userContext)                        }
                        (*originalImplementation.ResetPasswordUsingToken) = func(token, newPassword string, userContext supertokens.UserContext) (epmodels.ResetPasswordUsingTokenResponse, error) {                            // This is called during the password reset flow                            // when the user enters their new password                            if newPassword == FAKE_PASSWORD {                                return epmodels.ResetPasswordUsingTokenResponse{                                    ResetPasswordInvalidTokenError: &struct{}{},                                }, nil                            }                            return ogResetPasswordUsingToken(token, newPassword, userContext)                        }
                        (*originalImplementation.EmailPasswordSignIn) = func(email, password string, userContext supertokens.UserContext) (tpepmodels.SignInResponse, error) {                            // This is called in the email password sign in API                            if password == FAKE_PASSWORD {                                return tpepmodels.SignInResponse{                                    WrongCredentialsError: &struct{}{},                                }, nil                            }                            return ogEmailPasswordSignIn(email, password, userContext)                        }
                        return originalImplementation                    },                },            }),        },    })}from supertokens_python import init, InputAppInfofrom supertokens_python.recipe import thirdpartyemailpasswordfrom supertokens_python.recipe.thirdpartyemailpassword.interfaces import APIInterface, RecipeInterface, EmailPasswordSignInOkResult, EmailPasswordSignInWrongCredentialsError, ResetPasswordUsingTokenOkResult, ResetPasswordUsingTokenInvalidTokenError, UpdateEmailOrPasswordOkResult, UpdateEmailOrPasswordEmailAlreadyExistsError, UpdateEmailOrPasswordUnknownUserIdErrorfrom typing import Dict, Any, Union
FAKE_PASSWORD = "asokdA87fnf30efjoiOI**cwjkn"
def apis_override(original_impl: APIInterface):    # ... from previous code snippets...    return original_impl
def functions_override(original_impl: RecipeInterface):    og_emailpassword_sign_in = original_impl.emailpassword_sign_in    og_update_email_or_password = original_impl.update_email_or_password    og_reset_password_using_token = original_impl.reset_password_using_token
    async def update_email_or_password(        user_id: str,        email: Union[str, None],        password: Union[str, None],        user_context: Dict[str, Any],    ) -> Union[        UpdateEmailOrPasswordOkResult,        UpdateEmailOrPasswordEmailAlreadyExistsError,        UpdateEmailOrPasswordUnknownUserIdError,    ]:        # This can be called on the backend        # in your own APIs        if (password == FAKE_PASSWORD):            raise Exception("Please use a different password")        return await og_update_email_or_password(user_id, email, password, user_context)
    async def reset_password_using_token(        token: str, new_password: str, user_context: Dict[str, Any]    ) -> Union[        ResetPasswordUsingTokenOkResult, ResetPasswordUsingTokenInvalidTokenError    ]:        # This is called during the password reset flow        # when the user enters their new password        if (new_password == FAKE_PASSWORD):            return ResetPasswordUsingTokenInvalidTokenError()        return await og_reset_password_using_token(token, new_password, user_context)
    async def emailpassword_sign_in(        email: str, password: str, user_context: Dict[str, Any]    ) -> Union[EmailPasswordSignInOkResult, EmailPasswordSignInWrongCredentialsError]:        # This is called in the email password sign in API        if (password == FAKE_PASSWORD):            return EmailPasswordSignInWrongCredentialsError()        return await og_emailpassword_sign_in(email, password, user_context)
    original_impl.update_email_or_password = update_email_or_password    original_impl.reset_password_using_token = reset_password_using_token    original_impl.emailpassword_sign_in = emailpassword_sign_in    return original_impl
init(    app_info=InputAppInfo(        api_domain="...", app_name="...", website_domain="..."),    framework='...',      recipe_list=[        thirdpartyemailpassword.init(            override=thirdpartyemailpassword.InputOverrideConfig(                apis=apis_override,                functions=functions_override            ),        )    ])