> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# External JWT sign-in

> auth.externalJwt.signIn — exchange a JWT from your configured external issuer for a Dynamic user JWT

Method on the `externalJwt` flow of a [createAuthClient](/node/reference/auth/create-auth-client) client. `signIn` exchanges a JWT signed by the environment's configured external issuer (Bring Your Own Auth) for a Dynamic user JWT.

The environment must have [third-party auth](/overview/authentication/bring-your-own-auth) configured in the dashboard (issuer, JWKS URL, audience); Bring Your Own Auth is an enterprise feature. The SDK never mints or verifies the external JWT — you supply it, it is used once for the exchange, and it is never persisted or logged. Dynamic verifies it server-side against the environment's configuration. See [Sign In with an External JWT](/node/agents/sign-in-with-an-external-jwt) for the agent flow.

## signIn

### Function Signature

```typescript theme={"system"}
auth.externalJwt.signIn(params: {
  jwt: string;
  sessionPublicKey?: string;
}): Promise<AuthResult>
```

### Parameters

* **`jwt`** (`string`) - A JWT signed by the environment's configured external issuer, with at least `iss`, `sub`, and `exp` claims. Each distinct `sub` is a distinct Dynamic user with its own wallets. Used once for the exchange — never persist or log it.
* **`sessionPublicKey`** (`string`, optional) - Compressed P-256 public key hex from [generateSessionKeyPair](/node/reference/auth/generate-session-key-pair). Binds the session key into the minted JWT — required if you will use a session signer with [authenticateJwt](/node/reference/auth/authenticate-jwt) for `backUpToDynamic` flows.

### Returns

* **`Promise<AuthResult>`** - `{ jwt, expiresAt, userId }`. Pass `jwt` to `authenticateJwt`; never log it.

## Example

```typescript theme={"system"}
import { createAuthClient, generateSessionKeyPair } from '@dynamic-labs-wallet/node';

const auth = createAuthClient({ environmentId: 'your-environment-id' });
const { publicKeyHex, privateKeyJwk } = await generateSessionKeyPair();

// A JWT signed by your configured external issuer, attesting to the agent's identity.
const { jwt, expiresAt } = await auth.externalJwt.signIn({
  jwt: externalJwtFromYourIssuer,
  sessionPublicKey: publicKeyHex,
});
```

## Error Handling

A blank `jwt` throws `"externalJwt.signIn requires a jwt"` before any network call.

```typescript theme={"system"}
try {
  const result = await auth.externalJwt.signIn({ jwt: externalJwt, sessionPublicKey });
} catch (error) {
  // - Invalid or expired external JWT (401): "external JWT sign-in failed: the
  //   code or signature is invalid or expired"
  // - Third-party auth not configured for the environment: the server's error
  //   and status, e.g. "This feature is not enabled (status 422)"
  // - MFA-required account: "account requires MFA, which the headless auth
  //   client does not support"
  // - Cookie-auth environment: sign-in returned no JWT in the response body
  console.error('Sign-in failed:', error);
}
```

Sign-in endpoints are rate limited per IP address (429 when exceeded) — see [Rate Limit Policies](/overview/rate-limits).

## Related Functions

* [`createAuthClient()`](/node/reference/auth/create-auth-client) - Create the auth client
* [Email OTP sign-in](/node/reference/auth/email-otp-sign-in) - Email-based alternative
* [Wallet sign-in](/node/reference/auth/wallet-sign-in) - Private-key-based alternative
* [`authenticateJwt()`](/node/reference/auth/authenticate-jwt) - Use the minted JWT
