import { passkeyClient } from '@better-auth/passkey/client';
import { ssoClient } from '@better-auth/sso/client';
import configuration from '@intlayer/config/built';
import type { IntlayerConfig } from '@intlayer/types';
import { createAuthClient } from 'better-auth/client';
import { magicLinkClient, twoFactorClient } from 'better-auth/client/plugins';
const getAuthClient = (backendURL: string) =>
createAuthClient({
baseURL: backendURL,
withCredentials: true, // makes fetch forward cookies
plugins: [
twoFactorClient({
onTwoFactorRedirect: () => {
// Preserve redirect_url when redirecting to 2FA
const searchParams = new URLSearchParams(window.location.search);
const redirectUrl = searchParams.get('redirect_url');
const twoFaUrl = redirectUrl
? `/auth/2fa?redirect_url=${encodeURIComponent(redirectUrl)}`
: '/auth/2fa';
window.location.href = twoFaUrl;
},
}),
passkeyClient(),
magicLinkClient() as never,
ssoClient(),
],
});
type AuthClient = ReturnType<typeof getAuthClient>;
export interface AuthAPI {
getAuthClient: () => AuthClient;
signInEmail: AuthClient['signIn']['email'];
signUpEmail: AuthClient['signUp']['email'];
signOut: AuthClient['signOut'];
signInSocial: AuthClient['signIn']['social'];
linkSocial: AuthClient['linkSocial'];
changePasswordSession: AuthClient['changePassword'];
requestPasswordResetSession: AuthClient['requestPasswordReset'];
resetPassword: AuthClient['resetPassword'];
verifyEmailSession: AuthClient['verifyEmail'];
getSession: AuthClient['getSession'];
forgetPassword: AuthClient['requestPasswordReset'];
sendVerificationEmail: AuthClient['sendVerificationEmail'];
changeEmail: AuthClient['changeEmail'];
deleteUser: AuthClient['deleteUser'];
revokeSession: AuthClient['revokeSession'];
revokeSessions: AuthClient['revokeSessions'];
revokeOtherSessions: AuthClient['revokeOtherSessions'];
listAccounts: AuthClient['listAccounts'];
unlinkAccount: AuthClient['unlinkAccount'];
refreshToken: AuthClient['refreshToken'];
getAccessToken: AuthClient['getAccessToken'];
accountInfo: AuthClient['accountInfo'];
updateUser: AuthClient['updateUser'];
listSessions: AuthClient['listSessions'];
enableTwoFactor: AuthClient['twoFactor']['enable'];
disableTwoFactor: AuthClient['twoFactor']['disable'];
verifyTotp: AuthClient['twoFactor']['verifyTotp'];
verifyBackupCode: AuthClient['twoFactor']['verifyBackupCode'];
addPasskey: AuthClient['passkey']['addPasskey'];
signInPasskey: AuthClient['signIn']['passkey'];
deletePasskey: AuthClient['passkey']['deletePasskey'];
listPasskeys: () => Promise<any>;
signInMagicLink: (
// Redeclare it because of type inference issues
input: { email: string; callbackURL: string }
) => any;
registerSSO: AuthClient['sso']['register'];
listSSOProviders: () => Promise<any>;
deleteSSOProvider: (args: { providerId: string }) => Promise<any>;
signInSSO: AuthClient['signIn']['sso'];
}
export const getAuthAPI = (intlayerConfig?: IntlayerConfig): AuthAPI => {
const backendURL =
intlayerConfig?.editor?.backendURL ?? configuration?.editor?.backendURL;
if (!backendURL) {
throw new Error(
'Backend URL is not defined in the Intlayer configuration.'
);
}
const client = getAuthClient(backendURL);
const signInEmail: AuthClient['signIn']['email'] = async (...args) => {
return client.signIn.email(...args);
};
const signInSocial: AuthClient['signIn']['social'] = async (...args) => {
return client.signIn.social(...args);
};
const signUpEmail: AuthClient['signUp']['email'] = async (...args) => {
return client.signUp.email(...args);
};
const signOut: AuthClient['signOut'] = async (...args) => {
return client.signOut(...args);
};
const changePasswordSession: AuthClient['changePassword'] = async (
...args
) => {
return client.changePassword(...args);
};
const requestPasswordResetSession: AuthClient['requestPasswordReset'] =
async (...args) => {
return client.requestPasswordReset(...args);
};
// @ts-ignore - resetPassword is not typed
const resetPassword: AuthClient['resetPassword'] = async (...args) => {
return client.resetPassword(...args);
};
const verifyEmailSession: AuthClient['verifyEmail'] = async (...args) => {
return client.verifyEmail(...args);
};
const getSession: AuthClient['getSession'] = async (...args) => {
return client.getSession(...args);
};
const forgetPassword: AuthClient['requestPasswordReset'] = async (
...args
) => {
return client.requestPasswordReset(...args);
};
const sendVerificationEmail: AuthClient['sendVerificationEmail'] = async (
...args
) => {
return client.sendVerificationEmail(...args);
};
const changeEmail: AuthClient['changeEmail'] = async (...args) => {
return client.changeEmail(...args);
};
// @ts-ignore - deleteUser is not typed
const deleteUser: AuthClient['deleteUser'] = async (...args) => {
return client.deleteUser(...args);
};
const revokeSession: AuthClient['revokeSession'] = async (...args) => {
return client.revokeSession(...args);
};
const revokeSessions: AuthClient['revokeSessions'] = async (...args) => {
return client.revokeSessions(...args);
};
const revokeOtherSessions: AuthClient['revokeOtherSessions'] = async (
...args
) => {
return client.revokeOtherSessions(...args);
};
const linkSocial: AuthClient['linkSocial'] = async (...args) => {
return client.linkSocial(...args);
};
const listAccounts: AuthClient['listAccounts'] = async (...args) => {
return client.listAccounts(...args);
};
const unlinkAccount: AuthClient['unlinkAccount'] = async (...args) => {
return client.unlinkAccount(...args);
};
const refreshToken: AuthClient['refreshToken'] = async (...args) => {
return client.refreshToken(...args);
};
const getAccessToken: AuthClient['getAccessToken'] = async (...args) => {
return client.getAccessToken(...args);
};
const accountInfo: AuthClient['accountInfo'] = async (...args) => {
return client.accountInfo(...args);
};
const updateUser: AuthClient['updateUser'] = async (...args) => {
return client.updateUser(...args);
};
const listSessions: AuthClient['listSessions'] = async (...args) => {
return client.listSessions(...args);
};
const enableTwoFactor: AuthClient['twoFactor']['enable'] = async (
...args
) => {
return client.twoFactor.enable(...args) as ReturnType<
AuthClient['twoFactor']['enable']
>;
};
const disableTwoFactor: AuthClient['twoFactor']['disable'] = async (
...args
) => {
return client.twoFactor.disable(...args) as ReturnType<
AuthClient['twoFactor']['disable']
>;
};
const verifyTotp: AuthClient['twoFactor']['verifyTotp'] = async (...args) => {
return client.twoFactor.verifyTotp(...args) as ReturnType<
AuthClient['twoFactor']['verifyTotp']
>;
};
const verifyBackupCode: AuthClient['twoFactor']['verifyBackupCode'] = async (
...args
) => {
return client.twoFactor.verifyBackupCode(...args) as ReturnType<
AuthClient['twoFactor']['verifyBackupCode']
>;
};
const addPasskey: AuthClient['passkey']['addPasskey'] = async (...args) => {
return client.passkey.addPasskey(...args);
};
const signInPasskey: AuthClient['signIn']['passkey'] = async (...args) => {
return client.signIn.passkey(...args);
};
const deletePasskey: AuthClient['passkey']['deletePasskey'] = async (
...args
) => {
return client.passkey.deletePasskey(...args);
};
const listPasskeys = async () => {
// @ts-ignore - listPasskeys may not be typed yet
return client.$fetch('/passkey/list-user-passkeys', {
method: 'GET',
});
};
const signInMagicLink: any = async (...args: any[]) => {
return (client.signIn as any).magicLink(...args);
};
const signInSSO: AuthClient['signIn']['sso'] = async (...args) => {
return client.signIn.sso(...args);
};
const registerSSO: AuthClient['sso']['register'] = async (...args) => {
return client.sso.register(...args);
};
const listSSOProviders = async () => {
// Not implemented yet
};
const deleteSSOProvider = async (args: { providerId: string }) => {
// Not implemented yet
};
return {
getAuthClient: () => client,
signInEmail,
signUpEmail,
signOut,
signInSocial,
linkSocial,
changePasswordSession,
requestPasswordResetSession,
resetPassword,
verifyEmailSession,
getSession,
forgetPassword,
sendVerificationEmail,
changeEmail,
deleteUser,
revokeSession,
revokeSessions,
revokeOtherSessions,
listAccounts,
unlinkAccount,
refreshToken,
getAccessToken,
accountInfo,
updateUser,
listSessions,
enableTwoFactor,
disableTwoFactor,
verifyTotp,
verifyBackupCode,
addPasskey,
signInPasskey,
deletePasskey,
listPasskeys,
signInMagicLink,
signInSSO,
registerSSO,
listSSOProviders,
deleteSSOProvider,
};
};