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

# Server-to-Server Authentication

> Authenticate Privacy Boost users with API credentials for backend integrations

# Server-to-Server Authentication

The `api_secret` auth method is designed for server-to-server integrations where your backend controls the authentication flow. Instead of relying on a third-party auth provider, your backend authenticates directly with the Privacy Boost API using a `client_id` and `client_secret` pair — similar to OAuth 2.0 client credentials.

This is the right choice when:

* Your backend already manages user authentication and you don't use a third-party auth provider
* You need programmatic access (scripts, bots, automated systems)
* You want full control over who can authenticate without depending on an external JWKS endpoint

## How It Works

<img className="block dark:hidden" src="https://mintcdn.com/sunnysidelabs/npTSPV0krdyxjvTn/images/sdk/api-secret-flow.svg?fit=max&auto=format&n=npTSPV0krdyxjvTn&q=85&s=a027146968fe289de68a7c321051ed3e" alt="API Secret Authentication Flow" width="720" height="360" data-path="images/sdk/api-secret-flow.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/sunnysidelabs/npTSPV0krdyxjvTn/images/sdk/api-secret-flow-dark.svg?fit=max&auto=format&n=npTSPV0krdyxjvTn&q=85&s=570023f85f73b75d8598f974f06f4099" alt="API Secret Authentication Flow" width="720" height="360" data-path="images/sdk/api-secret-flow-dark.svg" />

## Setup

### 1. Get API Credentials

Contact the Privacy Boost team to configure your app with the `api_secret` auth method. You'll receive:

* **App ID** — Your application identifier (e.g., `app_abc123xyz`)
* **Client ID** — A unique identifier for your credentials (e.g., `pb_cred_abc123xyz...`)
* **Client Secret** — A secret key for authenticating requests

<Warning>
  Store your `client_secret` securely. It should never be exposed in client-side code, committed to version control, or logged. Use environment variables or a secrets manager.
</Warning>

### 2. Store Credentials Securely

```bash theme={null}
# Environment variables (development)
export PB_CLIENT_ID="pb_cred_abc123xyz..."
export PB_CLIENT_SECRET="your-secret-here"

# Or use a secrets manager in production (AWS Secrets Manager, HashiCorp Vault, etc.)
```

## Client-Side Integration

### Implement a Token Provider

Your token provider routes the SDK's login payload through your backend:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const tokenProvider = async (loginPayload: any) => {
    const res = await fetch('https://your-backend.com/api/privacy-boost/auth', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${yourSessionToken}`, // Your own auth
      },
      body: JSON.stringify(loginPayload),
    });

    if (!res.ok) throw new Error('Auth failed');
    return await res.json(); // { token, expiresIn }
  };

  await sdk.auth.authenticate(adapter, {
    type: 'walletDerived',
    tokenProvider,
  });
  ```

  ```swift iOS theme={null}
  class APISecretTokenProvider: TokenProvider {
      func getToken(loginPayloadJson: String) async throws -> TokenResponse {
          var request = URLRequest(url: URL(string: "https://your-backend.com/api/privacy-boost/auth")!)
          request.httpMethod = "POST"
          request.setValue("application/json", forHTTPHeaderField: "Content-Type")
          request.setValue("Bearer \(yourSessionToken)", forHTTPHeaderField: "Authorization")
          request.httpBody = loginPayloadJson.data(using: .utf8)

          let (data, _) = try await URLSession.shared.data(for: request)
          let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
          return TokenResponse(
              token: json["token"] as! String,
              expiresIn: json["expiresIn"] as! UInt64
          )
      }
  }

  try await sdk.authenticate(
      wallet: walletDelegate,
      tokenProvider: APISecretTokenProvider()
  )
  ```

  ```kotlin Android theme={null}
  class APISecretTokenProvider : TokenProvider {
      override suspend fun getToken(loginPayloadJson: String): TokenResponse {
          val response = httpClient.post("https://your-backend.com/api/privacy-boost/auth") {
              contentType(ContentType.Application.Json)
              header("Authorization", "Bearer $yourSessionToken")
              setBody(loginPayloadJson)
          }
          val json = Json.parseToJsonElement(response.bodyAsText()).jsonObject
          return TokenResponse(
              token = json["token"]!!.jsonPrimitive.content,
              expiresIn = json["expiresIn"]!!.jsonPrimitive.long.toULong()
          )
      }
  }

  sdk.authenticate(
      wallet = walletDelegate,
      tokenProvider = APISecretTokenProvider()
  )
  ```
</CodeGroup>

## Backend Endpoint

Your backend endpoint receives the SDK's login payload, adds your API credentials, and forwards to Privacy Boost:

```typescript theme={null}
// Express.js example
app.post('/api/privacy-boost/auth', async (req, res) => {
  // 1. Verify your own user auth (session, JWT, etc.)
  const user = await verifyYourAuth(req.headers.authorization);
  if (!user) return res.status(401).json({ error: 'Unauthorized' });

  // 2. Forward to Privacy Boost with API credentials
  const pbResponse = await fetch(
    'https://optimism.sepolia.privacyboost.io/auth/token',
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        ...req.body,                          // SDK's login payload (mpk, viewauth_signature, nonce, etc.)
        client_id: process.env.PB_CLIENT_ID,  // Your API credential ID
        client_secret: process.env.PB_CLIENT_SECRET, // Your API secret
      }),
    }
  );

  if (!pbResponse.ok) {
    const err = await pbResponse.json();
    return res.status(pbResponse.status).json(err);
  }

  const data = await pbResponse.json();
  res.json({
    token: data.access_token,
    expiresIn: data.expires_in,
  });
});
```

```python theme={null}
# FastAPI example
@app.post("/api/privacy-boost/auth")
async def privacy_boost_auth(request: Request):
    # 1. Verify your own user auth
    user = await verify_your_auth(request.headers.get("authorization"))
    if not user:
        raise HTTPException(status_code=401)

    # 2. Forward to Privacy Boost with API credentials
    payload = await request.json()
    payload["client_id"] = os.environ["PB_CLIENT_ID"]
    payload["client_secret"] = os.environ["PB_CLIENT_SECRET"]

    async with httpx.AsyncClient() as client:
        pb_response = await client.post(
            "https://optimism.sepolia.privacyboost.io/auth/token",
            json=payload,
        )

    data = pb_response.json()
    return {"token": data["access_token"], "expiresIn": data["expires_in"]}
```

## Credential Management

### Rotation

API credentials can be rotated without downtime:

1. Request a new credential from the Privacy Boost team
2. Update your backend to use the new `client_id` and `client_secret`
3. Revoke the old credential

### Expiry

Credentials can optionally have an expiry date. If your credential expires, requests will fail with `invalid_credentials`. Request a new credential before the current one expires.

## Security Best Practices

1. **Never expose credentials in client-side code.** The `client_id` and `client_secret` must only exist on your backend.
2. **Use environment variables or a secrets manager.** Don't hardcode credentials.
3. **Rotate credentials periodically.** Treat them like passwords.
4. **Authenticate your own users first.** Your backend endpoint should verify the caller's identity (session token, JWT, etc.) before forwarding to Privacy Boost. Otherwise, anyone who discovers your endpoint can authenticate.
5. **Use HTTPS only.** All communication between your backend and Privacy Boost must be over HTTPS.

## Next Steps

Continue with setup:

* [Key Management](/sdk/concepts/key-management) — Configure key persistence for returning users
* [Error Handling](/sdk/concepts/error-handling) — Handle auth and operation errors

Or explore other auth methods:

* [Custom JWT](/sdk/guides/custom-jwt) — For Auth0, Firebase, Supabase, Clerk, or OIDC providers
* [Privy](/sdk/guides/privy) — For Privy social login and embedded wallets
