Post signin / signup callbacks
#
1) On the frontend- ReactJS
- Angular
- Vue
Important
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 ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
ThirdPartyPasswordless.init({
contactMethod: "EMAIL_OR_PHONE",
onHandleEvent: async (context) => {
if (context.action === "SESSION_ALREADY_EXISTS") {
// TODO:
} else if (context.action === "PASSWORDLESS_RESTART_FLOW") {
// TODO:
} else if (context.action === "PASSWORDLESS_CODE_SENT") {
// TODO:
} else if (context.action === "SUCCESS") {
if (context.isNewUser) {
if ("phoneNumber" in context.user) {
const { phoneNumber } = context.user;
} else {
const { email } = context.user;
}
// TODO: Sign up
} else {
// TODO: Sign in
}
}
}
}),
Session.init()
]
});
info
Please refer to this page to learn more about the onHandleEvent
hook.
Important
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 ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
ThirdPartyPasswordless.init({
contactMethod: "EMAIL_OR_PHONE",
onHandleEvent: async (context) => {
if (context.action === "SESSION_ALREADY_EXISTS") {
// TODO:
} else if (context.action === "PASSWORDLESS_RESTART_FLOW") {
// TODO:
} else if (context.action === "PASSWORDLESS_CODE_SENT") {
// TODO:
} else if (context.action === "SUCCESS") {
if (context.isNewUser) {
if ("phoneNumber" in context.user) {
const { phoneNumber } = context.user;
} else {
const { email } = context.user;
}
// 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 ThirdPartyPasswordless from "supertokens-auth-react/recipe/thirdpartypasswordless";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
ThirdPartyPasswordless.init({
contactMethod: "EMAIL_OR_PHONE",
onHandleEvent: async (context) => {
if (context.action === "SESSION_ALREADY_EXISTS") {
// TODO:
} else if (context.action === "PASSWORDLESS_RESTART_FLOW") {
// TODO:
} else if (context.action === "PASSWORDLESS_CODE_SENT") {
// TODO:
} else if (context.action === "SUCCESS") {
if (context.isNewUser) {
if ("phoneNumber" in context.user) {
const { phoneNumber } = context.user;
} else {
const { email } = context.user;
}
// 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 backendFor this, you'll have to override the consumeCode
and thirdPartySignInUp
recipe functions in the init
function call.
- NodeJS
- GoLang
- Python
- Other Frameworks
Important
import SuperTokens from "supertokens-node";
import ThirdPartyPasswordless from "supertokens-node/recipe/thirdpartypasswordless";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
ThirdPartyPasswordless.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,
// override the thirdparty sign in / up API
thirdPartySignInUp: async function (input) {
// TODO: Some pre sign in / up logic
let response = await originalImplementation.thirdPartySignInUp(input);
if (response.status === "OK") {
let { id, email } = 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 (response.createdNewUser) {
// TODO: Post sign up logic
} else {
// TODO: Post sign in logic
}
}
return response;
},
consumeCode: async (input) => {
// First we call the original implementation of consumeCodePOST.
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, phoneNumber } = response.user;
} else {
const { id, email } = response.user;
}
if (response.createdNewUser) {
// TODO: post sign up logic
} else {
// TODO: post sign in logic
}
}
return response;
}
}
}
}
}),
Session.init({ /* ... */ })
]
});
import (
"fmt"
"github.com/supertokens/supertokens-golang/recipe/passwordless/plessmodels"
"github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless"
"github.com/supertokens/supertokens-golang/recipe/thirdpartypasswordless/tplmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
thirdpartypasswordless.Init(tplmodels.TypeInput{
Override: &tplmodels.OverrideStruct{
Functions: func(originalImplementation tplmodels.RecipeInterface) tplmodels.RecipeInterface {
// create a copy of the original function
originalConsumeCode := *originalImplementation.ConsumeCode
originalThirdPartySignInUp := *originalImplementation.ThirdPartySignInUp
// override the thirdparty sign in / up function
(*originalImplementation.ThirdPartySignInUp) = func(thirdPartyID string, thirdPartyUserID string, email string, oAuthTokens map[string]interface{}, rawUserInfoFromProvider tpmodels.TypeRawUserInfoFromProvider, tenantId string, userContext *map[string]interface{}) (tplmodels.ThirdPartySignInUp, error) {
// TODO: some pre sign in / up logic
resp, err := originalThirdPartySignInUp(thirdPartyID, thirdPartyUserID, email, oAuthTokens, rawUserInfoFromProvider, tenantId, userContext)
if err != nil {
return tplmodels.ThirdPartySignInUp{}, 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
}
// override the passwordless sign in up function
(*originalImplementation.ConsumeCode) = func(userInput *plessmodels.UserInputCodeWithDeviceID, linkCode *string, preAuthSessionID string, tenantId string, userContext supertokens.UserContext) (tplmodels.ConsumeCodeResponse, error) {
// First we call the original implementation of ConsumeCodeUp.
response, err := originalConsumeCode(userInput, linkCode, preAuthSessionID, tenantId, userContext)
if err != nil {
return tplmodels.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 thirdpartypasswordless
from supertokens_python.recipe.thirdpartypasswordless.interfaces import APIInterface, PasswordlessAPIOptions, ConsumeCodePostOkResult, ThirdPartyAPIOptions, ThirdPartySignInUpPostOkResult
from typing import Union, Dict, Any
from supertokens_python.recipe.thirdparty.provider import Provider, RedirectUriInfo
def override_thirdpartypasswordless_apis(original_implementation: APIInterface):
original_thirdparty_sign_in_up_post = original_implementation.thirdparty_sign_in_up_post
original_consume_code_post = original_implementation.consume_code_post
async def thirdparty_sign_in_up_post(
provider: Provider,
redirect_uri_info: Union[RedirectUriInfo, None],
oauth_tokens: Union[Dict[str, Any], None],
tenant_id: str,
api_options: ThirdPartyAPIOptions,
user_context: Dict[str, Any]
):
# call the default behaviour as show below
result = await original_thirdparty_sign_in_up_post(provider, redirect_uri_info, oauth_tokens, tenant_id, api_options, user_context)
if isinstance(result, ThirdPartySignInUpPostOkResult):
if result.created_new_user:
pass # TODO: some post sign up logic
else:
pass # TODO: some post sign in logic
return result
async def consume_code_post(pre_auth_session_id: str,
user_input_code: Union[str, None],
device_id: Union[str, None],
link_code: Union[str, None],
tenant_id: str,
api_options: PasswordlessAPIOptions,
user_context: Dict[str, Any]):
# First we call the original implementation of consume_code_post.
response = await original_consume_code_post(pre_auth_session_id, user_input_code, device_id, link_code, tenant_id, api_options, user_context)
# Post sign up response, we check if it was successful
if isinstance(response, ConsumeCodePostOkResult):
_ = response.user.user_id
__ = response.user.email
___ = response.user.phone_number
if response.created_new_user:
pass # TODO: Post sign up logic
else:
pass # TODO: Post sign in logic
return response
original_implementation.thirdparty_sign_in_up_post = thirdparty_sign_in_up_post
original_implementation.consume_code_post = consume_code_post
return original_implementation
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework='...',
recipe_list=[
thirdpartypasswordless.init(
contact_config=...,
flow_type="...",
override=thirdpartypasswordless.InputOverrideConfig(
apis=override_thirdpartypasswordless_apis
),
)
]
)
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.