> For the complete documentation index, see [llms.txt](https://docs.yield.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.yield.fi/earn-with-yieldfi/integration-sdk/authentication/authentication.md).

# Authentication

This guide covers the complete wallet authentication flow using EVM wallets.

### Step-by-Step Authentication

#### Step 1: Generate Nonce

First, request a nonce (unique message) for the user's address:

```typescript
import { YieldFiSDK } from "yieldfi-sdk";

const sdk = await YieldFiSDK.create({
  gatewayUrl: "https://gw.yield.fi",
});

// Generate nonce for user's address
const nonce = await sdk.auth.generateNonce({
  address: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
});

console.log(nonce.message);
// "Sign this message to authenticate with YieldFi.\n\nAddress: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb\nNonce: abc123..."
```

#### Step 2: Sign Message with Wallet

Sign the message using the user's wallet. Here are examples for different wallet providers:

**Using ethers.js v6**

```typescript
import { ethers } from "ethers";

// Connect to MetaMask or other EIP-1193 provider
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const address = await signer.getAddress();

// Sign the message
const signature = await signer.signMessage(nonce.message);
```

**Using MetaMask Directly**

```typescript
// Request account access
const accounts = await window.ethereum.request({
  method: "eth_requestAccounts",
});
const address = accounts[0];

// Sign the message
const signature = await window.ethereum.request({
  method: "personal_sign",
  params: [nonce.message, address],
});
```

**Using WalletConnect**

```typescript
import { WalletConnectConnector } from "@web3-react/walletconnect-connector";

// After connecting with WalletConnect
const provider = new ethers.providers.Web3Provider(connector.provider);
const signer = provider.getSigner();
const signature = await signer.signMessage(nonce.message);
```

#### Step 3: Login with Signature

Submit the signature to complete authentication:

```typescript
const authResponse = await sdk.auth.login({
  address: address,
  signature: signature,
  message: nonce.message,
});

console.log(authResponse.accessToken); // JWT access token
console.log(authResponse.refreshToken); // Refresh token
console.log(authResponse.user); // User information
```

#### Step 4: Store Tokens

Store the tokens securely in your application:

```typescript
// Browser localStorage (for web apps)
localStorage.setItem("accessToken", authResponse.accessToken);
localStorage.setItem("refreshToken", authResponse.refreshToken);
localStorage.setItem("user", JSON.stringify(authResponse.user));

// Or sessionStorage (cleared on tab close)
sessionStorage.setItem("accessToken", authResponse.accessToken);

// Or secure HTTP-only cookies (for server-side apps)
// Set via your backend API
```

### Complete Example

Here's a complete React component example:

```typescript
import { useState } from "react";
import { YieldFiSDK } from "yieldfi-sdk";
import { ethers } from "ethers";

function LoginButton() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const handleLogin = async () => {
    try {
      setLoading(true);
      setError(null);

      // Initialize SDK
      const sdk = await YieldFiSDK.create({
        gatewayUrl: "https://gw.yield.fi",
      });

      // Connect to wallet
      const provider = new ethers.BrowserProvider(window.ethereum);
      await provider.send("eth_requestAccounts", []);
      const signer = await provider.getSigner();
      const address = await signer.getAddress();

      // Generate nonce
      const nonce = await sdk.auth.generateNonce({ address });

      // Sign message
      const signature = await signer.signMessage(nonce.message);

      // Login
      const authResponse = await sdk.auth.login({
        address,
        signature,
        message: nonce.message,
      });

      // Store tokens
      localStorage.setItem("accessToken", authResponse.accessToken);
      localStorage.setItem("refreshToken", authResponse.refreshToken);
      localStorage.setItem("user", JSON.stringify(authResponse.user));

      console.log("Login successful!", authResponse.user);
    } catch (err: any) {
      setError(err.message || "Login failed");
      console.error("Login error:", err);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <button onClick={handleLogin} disabled={loading}>
        {loading ? "Connecting..." : "Connect Wallet"}
      </button>
      {error && <p style={{ color: "red" }}>{error}</p>}
    </div>
  );
}
```

### Error Handling

Handle common authentication errors:

```typescript
import {
  AuthenticationError,
  ValidationError,
  NetworkError,
} from "yieldfi-sdk";

try {
  const authResponse = await sdk.auth.login({
    address,
    signature,
    message: nonce.message,
  });
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Invalid signature, expired nonce, etc.
    console.error("Authentication failed:", error.message);
  } else if (error instanceof ValidationError) {
    // Invalid input (missing address, signature, etc.)
    console.error("Validation error:", error.message);
  } else if (error instanceof NetworkError) {
    // Network issues
    console.error("Network error:", error.message);
  }
}
```

### Security Best Practices

1. **Always verify the message** - Users should verify the message they're signing matches what they expect
2. **Use HTTPS** - Always use HTTPS in production to protect tokens
3. **Secure storage** - Consider using secure storage mechanisms (HTTP-only cookies for server-side apps)
4. **Token expiration** - Implement token refresh logic (see Token Management)
5. **Logout on errors** - Clear tokens if authentication fails

### Next Steps

* Token Management - Learn how to refresh and manage tokens
* User Consent - Manage user consent records
