Avnology ID
SDKsTypeScript SDKAuthentication

Passwordless Authentication

Magic link and SMS OTP passwordless login flows with the TypeScript SDK.

Passwordless Authentication

The SDK supports two passwordless authentication methods: magic links (email) and SMS OTP (phone). Both eliminate the need for users to remember passwords.

Send a magic link to the user's email. Clicking the link authenticates them and redirects to your application.

loginWithMagicLink(params: MagicLinkParams): Promise<{ flowId: string }>

Parameters

NameTypeRequiredDescription
emailstringyesUser's email address
returnUrlstringnoURL to redirect to after clicking the link

Returns

Promise<{ flowId: string }> -- Flow ID for tracking. The actual magic link is sent via email.

Basic usage

import { AvnologyId } from "@avnology/sdk-typescript";

const client = new AvnologyId({
  baseUrl: "https://api.id.avnology.com",
  clientId: "app_abc123",
});

// Send magic link
const { flowId } = await client.loginWithMagicLink({
  email: "[email protected]",
  returnUrl: "https://myapp.com/dashboard",
});

showMessage(
  "We sent a login link to [email protected]. " +
  "Click the link in your email to sign in."
);

When the user clicks the magic link, they are redirected to your returnUrl with the session already established.

// On your callback/return page
const session = await client.getSession();
if (session) {
  console.log("Logged in via magic link:", session.identity.email);
  router.navigate("/dashboard");
} else {
  showError("Magic link expired or invalid. Please try again.");
  router.navigate("/login");
}

SMS OTP login

loginWithSms()

Send a one-time password via SMS to the user's phone number.

loginWithSms(params: SmsLoginParams): Promise<{ flowId: string }>

Parameters

NameTypeRequiredDescription
phonestringyesPhone number in E.164 format (e.g., "+15550100")

Returns

Promise<{ flowId: string }> -- Flow ID required to verify the code.

verifySmsCode()

Verify the SMS OTP code to complete authentication.

verifySmsCode(params: VerifySmsCodeParams): Promise<Session>

Parameters

NameTypeRequiredDescription
flowIdstringyesFlow ID from loginWithSms()
codestringyes6-digit code sent via SMS

Returns

Promise<Session> -- The authenticated session.

Full flow

import {
  AvnologyId,
  InvalidCodeError,
  ExpiredFlowError,
  RateLimitError,
} from "@avnology/sdk-typescript";

const client = new AvnologyId({
  baseUrl: "https://api.id.avnology.com",
  clientId: "app_abc123",
});

// Step 1: Send SMS code
try {
  const { flowId } = await client.loginWithSms({
    phone: "+15550100",
  });

  showMessage("Enter the 6-digit code sent to your phone.");

  // Step 2: Verify the code (user enters it)
  const code = await getUserInput("Verification code:");
  const session = await client.verifySmsCode({ flowId, code });

  console.log("Logged in:", session.identity.phone);
  redirectToDashboard();
} catch (error) {
  if (error instanceof InvalidCodeError) {
    showError(`Invalid code. ${error.attemptsRemaining} attempts remaining.`);
  } else if (error instanceof ExpiredFlowError) {
    showError("Code expired. Please request a new one.");
  } else if (error instanceof RateLimitError) {
    showError(`Too many attempts. Wait ${error.retryAfter} seconds.`);
  }
}

Resend SMS code

// If the user didn't receive the code, resend it
const { flowId: newFlowId } = await client.loginWithSms({
  phone: "+15550100",
});
showMessage("A new code has been sent to your phone.");

Passwordless registration

Both magic link and SMS OTP can be used for registration as well. If the user does not have an account, one is created automatically during the passwordless flow.

// This creates a new account if one doesn't exist
const { flowId } = await client.loginWithSms({
  phone: "+15550100",
});
const session = await client.verifySmsCode({ flowId, code: "482901" });

// The session will have a newly created identity if this was a new user
if (!session.identity.name?.first) {
  // Redirect to profile completion page
  router.navigate("/onboarding");
}

When to use which method

MethodBest forConsiderations
Magic linkDesktop web, email-first flowsUser must switch to email client
SMS OTPMobile apps, phone-first flowsRequires valid phone number; SMS has delivery costs
PasskeyMaximum security, repeat usersRequires device with biometric/PIN support
PasswordBroadest compatibilityWeakest security, breach risk

Common errors

Error classHTTP statusWhen
InvalidCodeError400Wrong SMS verification code
ExpiredFlowError410Magic link or SMS code expired
RateLimitError429Too many SMS/email requests
ValidationError422Invalid phone number format
MethodDisabledError403Passwordless is disabled for this app/org

See also

  • Login -- All login methods
  • Register -- Email/password registration
  • MFA -- Add MFA to passwordless accounts

On this page