# Connect and refresh OAuth

Run this integration code on the server unless the example explicitly mounts a browser button. `tokenVault`, `savePendingOAuthState`, `loadQentrahSession`, and event callbacks are application integration points, not exports supplied by the SDK. Implement them with your storage and user-session model.

## OAuth Routes

The Next.js helper is optional. Use it if your app uses Next route handlers.

```ts
// app/api/qentrah/oauth/config.ts
import { createQentrahPartnerAuthHandlers } from "@qentrah/auth-sdk/partner/next";

export const qentrahAuth = createQentrahPartnerAuthHandlers({
  workspaceBaseUrl: process.env.QENTRAH_WORKSPACE_BASE_URL!,
  clientId: process.env.QENTRAH_PARTNER_CLIENT_ID!,
  clientSecret: process.env.QENTRAH_PARTNER_CLIENT_SECRET,
  redirectUri: process.env.QENTRAH_PARTNER_REDIRECT_URI!,
  scopes: ["organization:read", "client:read"],

  sessionStore: {
    async savePendingAuthorization({ pending, request }) {
      await savePendingOAuthState(request, pending);
    },
    async loadPendingAuthorization({ state, request }) {
      return loadPendingOAuthState(request, state);
    },
    async clearPendingAuthorization({ state, request }) {
      await clearPendingOAuthState(request, state);
    },
  },

  tokenStore: {
    async saveTokens({ organizationId, tokenSet, scopes }) {
      await tokenVault.save({
        provider: "qentrah",
        organizationId,
        scopes,
        tokenSet,
      });
    },
  },

  afterSuccessRedirect: "/settings/integrations/qentrah?connected=1",
  afterErrorRedirect: "/settings/integrations/qentrah?error=1",
});
```

```ts
// app/api/qentrah/oauth/start/route.ts
import { qentrahAuth } from "../config";

export const GET = qentrahAuth.start;
```

```ts
// app/api/qentrah/oauth/callback/route.ts
import { qentrahAuth } from "../config";

export const GET = qentrahAuth.callback;
```

For other backend frameworks, use the lower-level helpers from `@qentrah/auth-sdk/partner` and wire the generated redirect URL, pending state storage, callback validation, and token storage into your own routes.

## Refresh Tokens

Refresh from server code, then save the returned token set back to your secure storage.

```ts
import { refreshQentrahPartnerAccessToken } from "@qentrah/auth-sdk/partner";

const tokenSet = await refreshQentrahPartnerAccessToken({
  workspaceBaseUrl: process.env.QENTRAH_WORKSPACE_BASE_URL!,
  clientId: process.env.QENTRAH_PARTNER_CLIENT_ID!,
  clientSecret: process.env.QENTRAH_PARTNER_CLIENT_SECRET,
  refreshToken: savedRefreshToken,
});

await tokenVault.save({ provider: "qentrah", tokenSet });
```