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

# Authenticate with OAuth 2.0

> Register an OAuth application, run the authorization code flow, and handle token refresh and scopes for user-facing apps on ION.

Use OAuth 2.0 when the caller is a user-facing application, such as a web app, desktop tool, or mobile client. OAuth lets ION enforce that user's permissions rather than a service account's. For system-to-system integrations, use an [API key](/api-reference/authentication/api-keys) instead.

## Register an OAuth application

Before users can sign in to your application, an org admin must register the application with ION. Run this mutation to register it:

```graphql theme={null}
mutation RegisterApp {
  registerOauthApp(name: "Acme Production Dashboard", appType: "regular_web") {
    oauthApp {
      id
      clientId
    }
  }
}
```

After registration, configure callback URLs, allowed origins, and logout URLs:

```graphql theme={null}
mutation AddCallback {
  addOauthRedirectUri(
    oauthAppId: 42
    uri: "https://app.example.com/auth/callback"
    uriType: "callback"
  ) {
    redirectUri {
      id
      uri
      uriType
    }
  }
}
```

Three URI types are supported:

| URI type   | Purpose                                                                  |
| ---------- | ------------------------------------------------------------------------ |
| `callback` | Where ION redirects users with the authorization code after they sign in |
| `origin`   | Browser origins allowed to make authenticated requests                   |
| `logout`   | Where ION redirects users after sign-out                                 |

Register every URL your application uses (production, staging, local development) to avoid `redirect_uri` mismatches.

## Run the authorization code flow

Follow the standard OAuth 2.0 authorization code flow:

1. **Redirect the user to the ION authorization endpoint.** Include `client_id`, `redirect_uri`, `response_type=code`, `scope`, and `state`.
2. The user authenticates with their ION credentials or SSO.
3. ION redirects to your `redirect_uri` with an authorization `code` and the `state` you sent.
4. **Exchange the code** at the token endpoint for an `access_token`, and optionally a `refresh_token`.
5. **Use the access token** on subsequent API calls.

The authorization and token endpoint URLs depend on your org's auth provider configuration. ION surfaces them in the OAuth app registration response. If you're integrating against ION for the first time, ask your CSM for the endpoint values that match your environment.

## Handle token expiration and refresh

Access tokens have a short lifetime, typically one hour. Two patterns handle expiration:

* **Short-lived integrations.** Let the token expire. Re-run the auth flow the next time the user opens the app.
* **Long-lived integrations.** Request the `offline_access` scope at authorization. Then exchange refresh tokens for new access tokens transparently.

Always re-validate tokens before relying on them. Clock skew, server-side revocation, or org membership changes can invalidate a token mid-flight.

## Scopes

Scopes constrain what an OAuth-issued token can do. Standard scopes include the following:

| Scope            | Allows                                         |
| ---------------- | ---------------------------------------------- |
| `openid`         | Receive an ID token alongside the access token |
| `profile`        | Read the user's profile                        |
| `email`          | Read the user's email                          |
| `offline_access` | Receive a refresh token                        |

ION applies the user's existing role and permission grants on top of the scope. A scope cannot grant a user more access than their role allows.

## Related

* [Authentication](/api-reference/authentication/overview)
* [Manage API keys](/api-reference/authentication/api-keys)
* [Error codes](/api-reference/error-codes)
