import ThirdPartyPasswordlessNode from "supertokens-node/recipe/thirdpartypasswordless"; import { appInfo } from "./appInfo"; import { TypeInput } from "supertokens-node/types"; import { UserDatabaseRepository, UserRepository, UserRow } from "@/server/new/repositories"; import { container } from "@/server/ioc.container"; import fetch from "node-fetch"; let setUserIdMapping = async (input: { externalUserId: string; supertokensUserId: string }): Promise => { const response = await fetch(`http://localhost:3567/recipe/userid/map`, { method: "post", body: JSON.stringify({ superTokensUserId: input.supertokensUserId, externalUserId: input.externalUserId }), headers: { "Content-Type": "application/json", rid: "useridmapping" } }); const data = await response.json(); console.log(data); }; let getThirdPartyUserFromDB = async (input: { email?: string }) => { const userRepository: UserRepository = container.get(UserDatabaseRepository); let user: UserRow; if (input.email) { user = await userRepository.findOneByEmailOrNull(input.email); if (user.email === input.email) { return user; } return undefined; } }; let { Google, Apple, Facebook } = ThirdPartyPasswordlessNode; export const backendConfig = (): TypeInput => { return { framework: "express", supertokens: { connectionURI: "http://localhost:3567" }, appInfo, recipeList: [ ThirdPartyPasswordlessNode.init({ flowType: "USER_INPUT_CODE_AND_MAGIC_LINK", contactMethod: "EMAIL", override: { functions: (originalImplementation) => { return { ...originalImplementation, consumeCode: async (input) => { console.log("INPUT: ", input); // use listCodesByPreAuthSessionId to retrieve details about the current user let codeResponse = await ThirdPartyPasswordlessNode.listCodesByPreAuthSessionId({ preAuthSessionId: input.preAuthSessionId }); // if both email and phoneNumber are undefined throw RESTART_FLOW_ERROR if (codeResponse?.email === undefined && codeResponse?.phoneNumber === undefined) { return { status: "RESTART_FLOW_ERROR" }; } // Box 2: retrieve the db user data with the input email and phone number if they exist let dbUserInfo = await getThirdPartyUserFromDB({ email: codeResponse?.email }); // Box 3: check if a user with the email or phoneNumber exists in auth0 if (dbUserInfo !== undefined) { // Box 4: call the SuperTokens consumeCode implementation let response = await originalImplementation.consumeCode(input); if (response.status != "OK") { return response; } // Box 5: is the user in the response a new Supertokens user if (response.createdNewUser) { // Box 6: map the Auth0 userId to the SuperTokens userId, to learn more about user mapping please check the User Id Mapping section. // If you have not stored the users Auth0 userId in your tables, you can ignore this step await setUserIdMapping({ externalUserId: dbUserInfo.id, supertokensUserId: response.user.id }); // Box 7: Set the newly created flag value to false in the response response.createdNewUser = false; } // Box 8: Set the userId in the response to use the Auth0 userId, to learn more about user mapping please check the User Id Mapping section. // If you have not stored the users Auth0 userId, you can ignore this step response.user.id = dbUserInfo.id; console.log("response: ", response); return response; } else { return originalImplementation.consumeCode(input); } } }; } }, providers: [ Google({ clientId: "55514083636-teo9b5achutv7ns4ph3g39kla63tr2vc.apps.googleusercontent.com", clientSecret: "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" }), Facebook({ clientSecret: "5c84f79a621c0ab132173e58e3da96b5", clientId: "772658092884638" }), Apple({ clientId: "4398792-io.supertokens.example.service", clientSecret: { keyId: "7M48Y4RYDL", privateKey: "-----BEGIN PRIVATE KEY-----\nMIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgu8gXs+XYkqXD6Ala9Sf/iJXzhbwcoG5dMh1OonpdJUmgCgYIKoZIzj0DAQehRANCAASfrvlFbFCYqn3I2zeknYXLwtH30JuOKestDbSfZYxZNMqhF/OzdZFTV0zc5u5s3eN+oCWbnvl0hM+9IW0UlkdA\n-----END PRIVATE KEY-----", teamId: "YWQCXGJRJL" } }) ] }) ], isInServerlessEnv: true }; };