Post signin / signup callbacks
1) On the frontend#
- ReactJS
 - Angular
 - Vue
 
This method allows you to fire events immediately after a successful sign in. For example to send analytics events post sign in.
// this goes in the auth route config of your frontend app (once the pre built UI script has been loaded)
supertokensUIInit("supertokensui", {
    appInfo: {
        apiDomain: "...",
        appName: "...",
        websiteDomain: "..."
    },
    recipeList: [
        supertokensUIPasswordless.init({
            contactMethod: "EMAIL_OR_PHONE",
            onHandleEvent: async (context) => {
                if (context.action === "PASSWORDLESS_RESTART_FLOW") {
                    // TODO:
                } else if (context.action === "PASSWORDLESS_CODE_SENT") {
                    // TODO:
                } else if (context.action === "SUCCESS") {
                    if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                        if ("phoneNumber" in context.user) {
                            const { phoneNumber } = context.user;
                        } else {
                            const { emails } = context.user;
                        }
                        // TODO: Sign up
                    } else {
                        // TODO: Sign in
                    }
                }
            }
        }),
        supertokensUIThirdParty.init({
            onHandleEvent: async (context) => {
                if (context.action === "SUCCESS") {
                    if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                        // TODO: Sign up
                    } else {
                        // TODO: Sign in
                    }
                }
            }
        }),
        supertokensUISession.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 Passwordless from "supertokens-auth-react/recipe/passwordless";
import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
    appInfo: {
        apiDomain: "...",
        appName: "...",
        websiteDomain: "..."
    },
    recipeList: [
        Passwordless.init({
            contactMethod: "EMAIL_OR_PHONE",
            onHandleEvent: async (context) => {
                if (context.action === "PASSWORDLESS_RESTART_FLOW") {
                    // TODO:
                } else if (context.action === "PASSWORDLESS_CODE_SENT") {
                    // TODO:
                } else if (context.action === "SUCCESS") {
                    if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                        if ("phoneNumber" in context.user) {
                            const { phoneNumber } = context.user;
                        } else {
                            const { emails } = context.user;
                        }
                        // TODO: Sign up
                    } else {
                        // TODO: Sign in
                    }
                }
            }
        }),
        ThirdParty.init({
            onHandleEvent: async (context) => {
                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.
// this goes in the auth route config of your frontend app (once the pre built UI script has been loaded)
supertokensUIInit("supertokensui", {
    appInfo: {
        apiDomain: "...",
        appName: "...",
        websiteDomain: "..."
    },
    recipeList: [
        supertokensUIPasswordless.init({
            contactMethod: "EMAIL_OR_PHONE",
            onHandleEvent: async (context) => {
                if (context.action === "PASSWORDLESS_RESTART_FLOW") {
                    // TODO:
                } else if (context.action === "PASSWORDLESS_CODE_SENT") {
                    // TODO:
                } else if (context.action === "SUCCESS") {
                    if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                        if ("phoneNumber" in context.user) {
                            const { phoneNumber } = context.user;
                        } else {
                            const { emails } = context.user;
                        }
                        // TODO: Sign up
                    } else {
                        // TODO: Sign in
                    }
                }
            }
        }),
        supertokensUIThirdParty.init({
            onHandleEvent: async (context) => {
                if (context.action === "SUCCESS") {
                    if (context.isNewRecipeUser && context.user.loginMethods.length === 1) {
                        // TODO: Sign up
                    } else {
                        // TODO: Sign in
                    }
                }
            }
        }),
        supertokensUISession.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 consumeCode and signInUp recipe functions in the init function call.
- NodeJS
 - GoLang
 - Python
 - Other Frameworks
 
Important
import SuperTokens from "supertokens-node";
import ThirdParty from "supertokens-node/recipe/thirdparty"
import Passwordless from "supertokens-node/recipe/passwordless"
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
    appInfo: {
        apiDomain: "...",
        appName: "...",
        websiteDomain: "..."
    },
    recipeList: [
        ThirdParty.init({
            override: {
                functions: (originalImplementation) => {
                    return {
                        ...originalImplementation,
                        // override the thirdparty sign in / up API
                        signInUp: async function (input) {
                            // TODO: Some pre sign in / up logic
                            let response = await originalImplementation.signInUp(input);
                            if (response.status === "OK") {
                                let { id, emails } = response.user;
                                // This is the response from the OAuth 2 provider that contains their tokens or user info.
                                let providerAccessToken = response.oAuthTokens["access_token"];
                                let firstName = response.rawUserInfoFromProvider.fromUserInfoAPI!["first_name"];
                                if (input.session === undefined) {
                                    if (response.createdNewRecipeUser && response.user.loginMethods.length === 1) {
                                        // TODO: Post sign up logic
                                    } else {
                                        // TODO: Post sign in logic
                                    }
                                }
                            }
                            return response;
                        }
                    }
                }
            }
        }),
        Passwordless.init({
            contactMethod: "EMAIL", // This example will work with any contactMethod
            flowType: "USER_INPUT_CODE_AND_MAGIC_LINK", // This example will work with any flowType
            override: {
                functions: (originalImplementation) => {
                    return {
                        ...originalImplementation,
                        consumeCode: async (input) => {
                            // First we call the original implementation of consumeCode.
                            const response = await originalImplementation.consumeCode(input);
                            // Post sign up response, we check if it was successful
                            if (response.status === "OK") {
                                if ("phoneNumber" in response.user) {
                                    const { id, phoneNumbers } = response.user;
                                } else {
                                    const { id, emails } = response.user;
                                }
                                if (input.session === undefined) {
                                    if (response.createdNewRecipeUser && response.user.loginMethods.length === 1) {
                                        // TODO: post sign up logic
                                    } else {
                                        // TODO: post sign in logic
                                    }
                                }
                            }
                            return response;
                        }
                    }
                }
            }
        }),
        Session.init({ /* ... */ })
    ]
});
import (
    "fmt"
    "github.com/supertokens/supertokens-golang/recipe/passwordless"
    "github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels"
    "github.com/supertokens/supertokens-golang/recipe/thirdparty"
    "github.com/supertokens/supertokens-golang/recipe/thirdparty/tpmodels"
    "github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
    supertokens.Init(supertokens.TypeInput{
        RecipeList: []supertokens.Recipe{
            thirdparty.Init(&tpmodels.TypeInput{
                Override: &tpmodels.OverrideStruct{
                    Functions: func(originalImplementation tpmodels.RecipeInterface) tpmodels.RecipeInterface {
                        // create a copy of the original function
                        originalSignInUp := *originalImplementation.SignInUp
                        // override the thirdparty sign in / up function
                        (*originalImplementation.SignInUp) = func(thirdPartyID, thirdPartyUserID, email string, oAuthTokens tpmodels.TypeOAuthTokens, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext supertokens.UserContext) (tpmodels.SignInUpResponse, error) {
                            // TODO: some pre sign in / up logic
                            resp, err := originalSignInUp(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext)
                            if err != nil {
                                return tpmodels.SignInUpResponse{}, err
                            }
                            if resp.OK != nil {
                                // user object contains the ID and email of the user
                                user := resp.OK.User
                                fmt.Println(user)
                                if resp.OK.CreatedNewUser {
                                    // TODO: Post sign up logic
                                } else {
                                    // TODO: Post sign in logic
                                }
                            }
                            return resp, err
                        }
                        return originalImplementation
                    },
                },
            }),
            passwordless.Init(plessmodels.TypeInput{
                Override: &plessmodels.OverrideStruct{
                    Functions: func(originalImplementation plessmodels.RecipeInterface) plessmodels.RecipeInterface {
                        // create a copy of the original function
                        originalConsumeCode := *originalImplementation.ConsumeCode
                        // override the passwordless sign in up function
                        (*originalImplementation.ConsumeCode) = func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (plessmodels.ConsumeCodeResponse, error) {
                            // First we call the original implementation of ConsumeCode.
                            response, err := originalConsumeCode(userInput, linkCode, preAuthSessionID, tenantId, userContext)
                            if err != nil {
                                return plessmodels.ConsumeCodeResponse{}, err
                            }
                            if response.OK != nil {
                                // sign in was successful
                                // user object contains the ID and email or phone number
                                user := response.OK.User
                                fmt.Println(user)
                                if response.OK.CreatedNewUser {
                                    // TODO: Post sign up logic
                                } else {
                                    // TODO: Post sign in logic
                                }
                            }
                            return response, nil
                        }
                        return originalImplementation
                    },
                },
            }),
        },
    })
}
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import passwordless, session, thirdparty
from supertokens_python.recipe.passwordless.interfaces import RecipeInterface as PasswordlessRecipeInterface, ConsumeCodeOkResult
from supertokens_python.recipe.thirdparty.interfaces import RecipeInterface as ThirdPartyRecipeInterface
from supertokens_python.recipe.thirdparty.types import RawUserInfoFromProvider
from typing import Dict, Any, Union
def override_passwordless_functions(original_implementation: PasswordlessRecipeInterface) -> PasswordlessRecipeInterface:
    original_consume_code = original_implementation.consume_code
    
    async def consume_code(
        pre_auth_session_id: str,
        user_input_code: Union[str, None],
        device_id: Union[str, None],
        link_code: Union[str, None],
        tenant_id: str,
        user_context: Dict[str, Any]
    ):
        # First we call the original implementation of consume_code.
        result = await original_consume_code(pre_auth_session_id, user_input_code, device_id, link_code, tenant_id, user_context)
        # Post sign up response, we check if it was successful
        if isinstance(result, ConsumeCodeOkResult):
            id = result.user.user_id
            print(id)
            if result.user.phone_number is not None:
                phone_number = result.user.phone_number
                print(phone_number)
            else:
                email = result.user.email
                print(email)
            
            if result.created_new_user:
                # TODO: post sign up logic
                pass
            else:
                # TODO: post sign in logic
                pass
        
        return result
                
    original_implementation.consume_code = consume_code
    return original_implementation
def override_thirdparty_functions(original_implementation: ThirdPartyRecipeInterface) -> ThirdPartyRecipeInterface:
    original_thirdparty_sign_in_up = original_implementation.sign_in_up
    async def thirdparty_sign_in_up(
        third_party_id: str,
        third_party_user_id: str,
        email: str,
        oauth_tokens: Dict[str, Any],
        raw_user_info_from_provider: RawUserInfoFromProvider,
        tenant_id: str,
        user_context: Dict[str, Any]
    ):
        result = await original_thirdparty_sign_in_up(third_party_id, third_party_user_id, email, oauth_tokens, raw_user_info_from_provider, tenant_id, user_context)
        # user object contains the ID and email of the user
        user = result.user
        print(user)
        # This is the response from the OAuth 2 provider that contains their tokens or user info.
        provider_access_token = result.oauth_tokens["access_token"]
        print(provider_access_token)
        if result.raw_user_info_from_provider.from_user_info_api is not None:
            first_name = result.raw_user_info_from_provider.from_user_info_api["first_name"]
            print(first_name)
        if result.created_new_user:
            print("New user was created")
            # TODO: Post sign up logic
        else:
            print("User already existed and was signed in")
            # TODO: Post sign in logic
        
        return result
                
    original_implementation.sign_in_up = thirdparty_sign_in_up
    return original_implementation
init(
    app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
    framework='...', 
    recipe_list=[
        passwordless.init(
            contact_config=passwordless.ContactConfig(
                contact_method="EMAIL", # This example will work with any contactMethod
            ),
            flow_type="USER_INPUT_CODE_AND_MAGIC_LINK", # This example will work with any flowType
            override=passwordless.InputOverrideConfig(
                functions=override_passwordless_functions
            ),
        ),
        thirdparty.init(
            override=thirdparty.InputOverrideConfig(
                functions=override_thirdparty_functions
            )
        ),
        session.init(),
    ]
)
Using the code above, if createdNewUser is true, you can (for example):
- Add the user's ID and their info to your own database (in addition to it being stored in SuperTokens).
 - Send analytics events about a sign up.
 - Send a welcome email to the user.
 - You can associate a role to the user.