# Provider OAuth configuration

Configure provider applications for Authlane hosted authorization and callbacks.

OAuth providers redirect to Authlane, where state, PKCE, token exchange, encrypted storage, and
refresh stay inside the control plane.

## Prerequisites

Create separate development and production provider applications and choose the minimum required
provider scopes.

## Implement the workflow

1. Register the exact callback `https://app.authlane.io/api/v1/oauth/{serviceId}/callback`, replacing
   `{serviceId}` with a shipped ID such as `github`.
2. For local development, use `http://localhost:3000/api/v1/oauth/{serviceId}/callback`.
3. Enable the service in the Authlane dashboard and store its client ID, encrypted client secret,
   and approved custom scopes. Services the platform already holds credentials for are available in
   every workspace without this step; registering your own application replaces the platform one,
   and switching a service off in the dashboard keeps it off.
4. Create a short-lived session from your authenticated SaaS backend:

```typescript
import { Authlane } from '@authlane/sdk';

const authlane = new Authlane({
  apiKey: process.env.AUTHLANE_API_KEY!,
});

export async function connectGithub(userId: string) {
  const { data, error } = await authlane.connectSessions.create({
    externalUserId: userId,
    allowedServices: ['github'],
    allowedOrigin: 'https://app.example.com',
    expiresInSeconds: 600,
  });
  if (error) {
    return { data: null, error };
  }
  return { data: data.url, error: null };
}
```

Use `allowedServices: []` only when you intend to snapshot every currently enabled tenant service.

## Expected result

The hosted UI starts authorization with single-use state and PKCE, receives the callback on the
Authlane origin, stores credentials encrypted, and reports the result to the exact parent origin.

## Handle errors

For denied consent, show a retry action. For state mismatch or token exchange failure, discard the
flow and start with a new connect session. Confirm the exact callback, client credentials, provider
scope approval, and public HTTPS origin.

## Security boundary

Provider client secrets, refresh tokens, and ID tokens never reach your widget or SaaS frontend.
Disconnect requires a newly minted connect session after fresh user authentication, with
`reauthenticatedAt` set to that trusted time.

## Next step

Implement [connection lifecycle](/docs/guides/connection-lifecycle) and
[lifecycle webhooks](/docs/guides/webhooks).
