Kysoql
Authentication flows

First-party passwordless login

Use Salesforce OAuth 2.0 for First-Party Applications passwordless email or SMS OTP login.

The first-party passwordless flow sends an OTP to the user's verified email address or phone number, then resumes the authorization challenge with the OTP to obtain an authorization code.

Initialize passwordless login

import { SalesforceAuth } from "@kysoql/auth";

export function beginPasswordless(
  username: string,
  clientAssertion: string,
  codeChallenge: string,
) {
  const auth = new SalesforceAuth({
    loginUrl: "https://customers.example.my.site.com/customers",
    clientId: "external-client-app-id",
  });

  return auth.firstPartyAuthorizationChallenge({
    parameters: {
      username,
      login_type: "email",
      client_assertion: clientAssertion,
      client_id: "external-client-app-id",
      code_challenge: codeChallenge,
      scope: "api refresh_token",
    },
  });
}

A successful initialization is still a challenge response: Salesforce returns an auth_session and a login state indicating that the OTP was sent.

Submit the OTP

import { SalesforceAuth } from "@kysoql/auth";

export function submitPasswordlessOtp(authSession: string, otp: string) {
  const auth = new SalesforceAuth({
    loginUrl: "https://customers.example.my.site.com/customers",
    clientId: "external-client-app-id",
  });

  return auth.firstPartyAuthorizationChallenge({
    parameters: {
      auth_session: authSession,
      login_otp: otp,
    },
  });
}

When Salesforce returns kind: "authorized", exchange the authorization code through auth.exchangeAuthorizationCode() using the matching PKCE verifier.

For identifier-based discovery instead of a Salesforce username, follow Salesforce's login_hint/customdata requirements for this flow.

On this page