Which UI do you use?
Pre built UI
Custom UI
Post sign in callbacks
1) On the frontend#
- ReactJS
 - Angular
 - Vue
 
Important
SuperTokens does not provide non-React UI components. So we will be using the 
supertokens-auth-react SDK and will inject the React components to show the UI. Therefore, the code snippet below refers to the supertokens-auth-react SDK.This method allows you to fire events immediately after a successful sign in. For example to send analytics events post sign in.
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({
            onHandleEvent: async (context) => {
                if (context.action === "SESSION_ALREADY_EXISTS") {
                    // TODO:
                } else {
                    if (context.action === "SUCCESS") {
                        if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                            // TODO: Sign up
                        } else {
                            // TODO: Sign in
                        }
                    }
                }
            }
        }),
        Session.init()
    ]
});
info
Please refer to this page to learn more about the onHandleEvent hook.
Important
SuperTokens does not provide non-React UI components. So we will be using the 
supertokens-auth-react SDK and will inject the React components to show the UI. Therefore, the code snippet below refers to the supertokens-auth-react SDK.This method allows you to fire events immediately after a successful sign in. For example to send analytics events post sign in.
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({
            onHandleEvent: async (context) => {
                if (context.action === "SESSION_ALREADY_EXISTS") {
                    // TODO:
                } else {
                    if (context.action === "SUCCESS") {
                        if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                            // TODO: Sign up
                        } else {
                            // TODO: Sign in
                        }
                    }
                }
            }
        }),
        Session.init()
    ]
});
info
Please refer to this page to learn more about the onHandleEvent hook.
This method allows you to fire events immediately after a successful sign in. For example to send analytics events post sign in.
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({
            onHandleEvent: async (context) => {
                if (context.action === "SESSION_ALREADY_EXISTS") {
                    // TODO:
                } else {
                    if (context.action === "SUCCESS") {
                        if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                            // TODO: Sign up
                        } else {
                            // TODO: Sign in
                        }
                    }
                }
            }
        }),
        Session.init()
    ]
});
info
Please refer to this page to learn more about the onHandleEvent hook.
2) On the backend#
For this, you'll have to override the signIn recipe function in the init function call.
- NodeJS
 - GoLang
 - Python
 - Other Frameworks
 
Important
For other backend frameworks, you can follow our guide on how to spin up a separate server configured with the SuperTokens backend SDK  to authenticate requests and issue session tokens.
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: {
                functions: (originalImplementation) => {
                    return {
                        ...originalImplementation,
                        signIn: async function (input) {
                            // First we call the original implementation of signIn.
                            let response = await originalImplementation.signIn(input);
                            // Post sign up response, we check if it was successful
                            if (response.status === "OK") {
                                /**
                                * 
                                * response.user contains the following info:
                                * - emails
                                * - id
                                * - timeJoined
                                * - tenantIds
                                * - phone numbers
                                * - third party login info
                                * - all the login methods associated with this user.
                                * - information about if the user's email is verified or not.
                                * 
                                */
                                // TODO: post sign in logic
                            }
                            return response;
                        }
                    }
                }
            }
        }),
        Session.init({ /* ... */ })
    ]
});
import (
    "fmt"
    "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{
                Override: &epmodels.OverrideStruct{
                    Functions: func(originalImplementation epmodels.RecipeInterface) epmodels.RecipeInterface {
                        // create a copy of the originalImplementation func
                        originalSignIn := *originalImplementation.SignIn
                        // override the sign in up function
                        (*originalImplementation.SignIn) = func(email, password, tenantId string, userContext supertokens.UserContext) (epmodels.SignInResponse, error) {
                            // First we call the original implementation of SignIn.
                            response, err := originalSignIn(email, password, tenantId, userContext)
                            if err != nil {
                                return epmodels.SignInResponse{}, err
                            }
                            if response.OK != nil {
                                // sign in was successful
                                // user object contains the ID and email
                                user := response.OK.User
                                // TODO: Post sign in logic.
                                fmt.Println(user)
                            }
                            return response, nil
                        }
                        return originalImplementation
                    },
                },
            }),
        },
    })
}
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import session, emailpassword
from supertokens_python.recipe.emailpassword.interfaces import RecipeInterface, SignInOkResult
from typing import Dict, Any
def override_emailpassword_functions(original_implementation: RecipeInterface) -> RecipeInterface:
    original_sign_in = original_implementation.sign_in
    
    async def sign_in(
        email: str,
        password: str,
        tenant_id: str,
        user_context: Dict[str, Any]
    ):
        result = await original_sign_in(email, password, tenant_id, user_context)
        if isinstance(result, SignInOkResult):
            id = result.user.user_id
            email = result.user.email
            print(id)
            print(email)
            
            # TODO: post sign in logic
        
        return result
                
    original_implementation.sign_in = sign_in
    return original_implementation
init(
    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
    framework='...', 
    recipe_list=[
        emailpassword.init(
            override=emailpassword.InputOverrideConfig(
                functions=override_emailpassword_functions
            ),
        ),
        session.init(),
    ]
)