# First-party username-password (/docs/auth/flows/first-party-username-password)



This flow lets a private first-party Experience Cloud application collect a
user's username/password itself, then send a headless authorization challenge to
Salesforce. It is distinct from Salesforce's retiring legacy OAuth
username-password grant.

<SalesforceReference title="Headless Username-Password Flow for Private Clients" href="https://help.salesforce.com/s/articleView?id=sf.remoteaccess_auth_challenge_username_password.htm&language=en_US&type=5" />

## Request an authorization code [#request-an-authorization-code]

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

export function firstPartyLogin(
  username: string,
  password: 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,
      password,
      client_id: "external-client-app-id",
      client_assertion: clientAssertion,
      code_challenge: codeChallenge,
      scope: "api refresh_token",
    },
  });
}
```

Salesforce can return a resumable `auth_session` when the request needs corrected
or additional data. Kysoql returns that as `kind: "challenge"`. Resubmit only the
fields Salesforce requires for the current continuation step.

Use `uvidHintToken` when the named-user flow continues from a guest session.
Headless user discovery can be implemented with Salesforce's documented
`login_hint` and `customdata` parameters.

After `kind: "authorized"`, exchange `authorizationCode` through
[`auth.exchangeAuthorizationCode()`](/docs/auth/flows/web-server-pkce).
