Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

usePhoneOtpAuth

Authenticate users with phone OTP (SMS one-time password) for passwordless login.

Usage

import { usePhoneOtpAuth } from '@openfort/react';
 
function PhoneOtpLogin() {
  const { requestPhoneOtp, logInWithPhoneOtp, isRequesting, isLoading } = usePhoneOtpAuth();
  const [phoneNumber, setPhoneNumber] = useState('');
  const [otp, setOtp] = useState('');
  const [otpSent, setOtpSent] = useState(false);
 
  const handleRequestOtp = async () => {
    const { error } = await requestPhoneOtp({ phoneNumber });
    if (!error) setOtpSent(true);
  };
 
  const handleSignIn = async () => {
    const { user, error } = await logInWithPhoneOtp({ phoneNumber, otp });
    if (user) console.log('Signed in:', user.id);
  };
 
  return (
    <div>
      <input value={phoneNumber} onChange={(e) => setPhoneNumber(e.target.value)} placeholder="+1234567890" />
      {otpSent && (
        <input value={otp} onChange={(e) => setOtp(e.target.value)} placeholder="Enter OTP" />
      )}
      {!otpSent ? (
        <button onClick={handleRequestOtp} disabled={isRequesting}>
          {isRequesting ? 'Sending...' : 'Send OTP'}
        </button>
      ) : (
        <button onClick={handleSignIn} disabled={isLoading}>
          {isLoading ? 'Signing in...' : 'Sign In'}
        </button>
      )}
    </div>
  );
}

Return type

type PhoneOtpAuthReturn = {
  requestPhoneOtp(options: RequestPhoneOtpOptions): Promise<PhoneAuthResult>
  logInWithPhoneOtp(options: LoginWithPhoneOtpOptions): Promise<PhoneAuthResult>
  linkPhoneOtp(options: LoginWithPhoneOtpOptions): Promise<PhoneAuthResult>
  reset(): void
  isRequesting: boolean
  isLoading: boolean
  isError: boolean
  isSuccess: boolean
  isAwaitingInput: boolean
  error?: OpenfortError | null
}
 
type PhoneAuthResult = {
  user?: User
  wallet?: UserWallet
  error?: OpenfortError
}

Hook options

Configure default behavior when initializing the hook.

type UsePhoneHookOptions = {
  // Log out the user if wallet recovery fails. Defaults to true.
  logoutOnError?: boolean
  // Automatically recover the wallet after authentication. Defaults to true.
  recoverWalletAutomatically?: boolean
  onSuccess?: (data: PhoneAuthResult) => void
  onError?: (error: OpenfortError) => void
}

Parameters

requestPhoneOtp

Request an OTP code to be sent to the user's phone via SMS.

type RequestPhoneOtpOptions = {
  phoneNumber: string
  onSuccess?: (data: PhoneAuthResult) => void
  onError?: (error: OpenfortError) => void
}

logInWithPhoneOtp

Sign in with the phone number and OTP code.

type LoginWithPhoneOtpOptions = {
  phoneNumber: string
  otp: string
  // Overrides the hook-level default.
  logoutOnError?: boolean
  // Overrides the hook-level default.
  recoverWalletAutomatically?: boolean
  onSuccess?: (data: PhoneAuthResult) => void
  onError?: (error: OpenfortError) => void
}

linkPhoneOtp

Link a phone number to an existing authenticated user. The user must already be authenticated (for example, via email or OAuth) before linking a phone number.

type LinkPhoneOtpOptions = {
  phoneNumber: string
  otp: string
  onSuccess?: (data: PhoneAuthResult) => void
  onError?: (error: OpenfortError) => void
}

Note: Unlike logInWithPhoneOtp, the linkPhoneOtp function does not create or recover a wallet—it only links the phone number to the existing user account.

Link phone example

import { usePhoneOtpAuth, useUser } from '@openfort/react';
 
function LinkPhoneNumber() {
  const { user } = useUser();
  const { requestPhoneOtp, linkPhoneOtp, isRequesting, isLoading } = usePhoneOtpAuth();
  const [phoneNumber, setPhoneNumber] = useState('');
  const [otp, setOtp] = useState('');
  const [otpSent, setOtpSent] = useState(false);
 
  if (!user) return <p>Please sign in first</p>;
 
  const handleRequestOtp = async () => {
    const { error } = await requestPhoneOtp({ phoneNumber });
    if (!error) setOtpSent(true);
  };
 
  const handleLinkPhone = async () => {
    const { user, error } = await linkPhoneOtp({ phoneNumber, otp });
    if (user) console.log('Phone linked successfully');
  };
 
  return (
    <div>
      <input value={phoneNumber} onChange={(e) => setPhoneNumber(e.target.value)} placeholder="+1234567890" />
      {otpSent && (
        <input value={otp} onChange={(e) => setOtp(e.target.value)} placeholder="Enter OTP" />
      )}
      {!otpSent ? (
        <button onClick={handleRequestOtp} disabled={isRequesting}>
          {isRequesting ? 'Sending...' : 'Send OTP'}
        </button>
      ) : (
        <button onClick={handleLinkPhone} disabled={isLoading}>
          {isLoading ? 'Linking...' : 'Link Phone'}
        </button>
      )}
    </div>
  );
}

Related