Authenticate a User with Email
This flow can both be used to login a user with only an email address, or to recover the account of a user that has lost their passkey credential with their email address. The end result is a valid TurnkeyClient
which can also be used to add another authenbticator if needed.
1. Initialize Turnkey
import { Turnkey, TurnkeySDKBrowserConfig } from "@turnkey/sdk-browser";
import turnkeyConfig from "./turnkey.json"
const turnkey = new Turnkey(turnkeyConfig);
2. Initialize the Iframe Client
Note that the iframe client must be initialized with the dom element where the iframe will be injected. If you are using the react-sdk you can import the authIframeClient
from the useTurnkey()
hook without this step and the iframe dom element will be managed for you. Note that the iframeClient
must be initialized before calling emailAuth
because you need the iframePublicKey
as a parameter to the emailAuth
call.
import { Turnkey, TurnkeySDKBrowserConfig } from "@turnkey/sdk-browser";
const turnkeyConfig: TurnkeySDKBrowserConfig = {...};
const turnkey = new Turnkey(turnkeyConfig);
const iframeContainerId = "turnkey-auth-iframe-container-id";
// ensure the HTML element exists somewhere in the rendered DOM
<div id={iframeContainerId} />
const authIframeClient = await turnkey.iframeClient(document.getElementById(iframeContainerId))
3. Call emailAuth
from your backend
await turnkey.serverSign(
"emailAuth",
[{
email: <userEmail>,
targetPublicKey: authIframeClient.iframePublicKey,
organizationId: <userSubOrganizationId>
}]
)
If you need to lookup the user subOrganizationId
by email, you can call the getSubOrgIds
method with the filterType
parameter set to "EMAIL"
const subOrgIds = await turnkey.serverSign(
"getSubOrgIds",
[{
filterType: "EMAIL",
filterValue: <userEmail>
}]
)
const userSubOrganizationId = subOrgIds.organizationIds[0];
4. Inject the emailed credentialBundle
into the iframe to authenticate the user
const authenticationResponse = await authIframeClient.injectCredentialBundle(credentialBundle);
if (authenticationResponse) {
// user is authenticated and can perform actions from the `iframeClient`
await authIframeClient.login();
navigate("/authenticated-route");
} else {
// credential bundle does not match emailed credential
navigate("/not-authenticated-route");
}
5. Make read requests on behalf of the authenticated user from the currentUserSession
const currentUserSession = await turnkey.currentUserSession();
const walletsResponse = await currentUserSession.getWallets()
const walletName = walletsResponse.wallets[0].walletName
6. Call the iframeClient
directly for write requests
import { DEFAULT_ETHEREUM_ACCOUNTS } from "@turnkey/sdk-browser";
const newWalletResponse = await authIframeClient.createWallet({
walletName: "New Wallet for User",
accounts: DEFAULT_ETHEREUM_ACCOUNTS
})