# OAuth2 Apps

OAuth2 Apps enable third-party applications to access Veza resources on behalf of an authenticated user. When a user initiates access from your application, Veza presents a consent screen. After the user grants consent, Veza issues an access token your application can use to call Veza APIs.

OAuth2 Apps use the authorization code flow with PKCE (Proof Key for Code Exchange). PKCE requires a code challenge using the S256 method. Requests without a valid code challenge are rejected.

Use OAuth2 Apps when:

* Building a web application or service that integrates with Veza
* You need delegated user access (the token acts on behalf of the user, not a service account)
* Your application can handle redirect-based flows

OAuth2 Apps are managed from **Administration** > *API Keys* > *OAuth2 Apps*.

## Prerequisites

* Admin role in Veza.
* OAuth2 Authorization Server enabled in **Administration** > *Sign-in Settings*.
* A redirect URI that uses `http` or `https` and belongs to the base URL domain or its subdomains.

## Create an OAuth2 App

1. Open **Administration** > *API Keys* > *OAuth2 Apps*.
2. Click **Add New OAuth2 App**.
3. Enter a **Client Name** to identify the application.
4. Enter the **Base URL** of your application (for example, `https://yourcompany.com`). Redirect URIs must use the same scheme and belong to this domain or its subdomains.
5. Under **Redirect URI Validation**, optionally select **Allow any redirect URI without validation**. This is not recommended for production use. When enabled, any URI can be used as a redirect target.
6. In the **Redirect URIs** field, enter one or more allowed redirect URIs as a comma-separated list (for example, `https://yourcompany.com/callback, https://yourcompany.com/auth`). These values are enforced when the validation checkbox is not selected.
7. Select the **Allowed scopes** that the app is permitted to request.
8. Click **Create**.

After creating the app, Veza displays the **Client ID** and an initial **Client Secret**. Copy both values. The secret will not be shown again.

## Authorization flow

OAuth2 Apps use the authorization code flow with PKCE. The S256 code challenge method is required.

### Step 1: Authorization request

Redirect the user to:

```http
GET https://<tenant>/oauth/authorize
  ?client_id=<client-id>
  &response_type=code
  &redirect_uri=<redirect-uri>
  &scope=<scope>
  &state=<state>
  &code_challenge=<S256-hashed-verifier>
  &code_challenge_method=S256
```

The `state` parameter is a CSRF protection value that your application generates and verifies when Veza redirects back to your redirect URI. Use a unique, unpredictable value for each authorization request.

### Consent screen

Veza presents the user with a consent screen that shows the application name and a description of each requested scope. The user can:

* **Allow**: Grant the application access. Veza redirects to your `redirect_uri` with an authorization `code` and the `state` value you provided.
* **Cancel**: Deny access. Veza redirects to your `redirect_uri` with the standard OAuth2 error parameters `error=access_denied`.

### Step 2: Token exchange

Exchange the authorization code for an access token:

```bash
curl -X POST https://<tenant>/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=<client-id>" \
  -d "client_secret=<client-secret>" \
  -d "code=<authorization-code>" \
  -d "redirect_uri=<redirect-uri>" \
  -d "code_verifier=<original-verifier>"
```

A successful response:

```json
{
  "access_token": "<token>",
  "refresh_token": "<refresh-token>",
  "token_type": "Bearer",
  "expires_in": 43200,
  "scope": "<scope>"
}
```

Access tokens expire after 12 hours. Authorization codes expire after 10 minutes and can only be used once.

### Step 3: Refresh the token

Refresh tokens expire after 30 days. Each refresh request issues a new access token and a new refresh token, revoking the previous pair. Use the new refresh token for subsequent refresh requests.

```bash
curl -X POST https://<tenant>/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "client_id=<client-id>" \
  -d "client_secret=<client-secret>" \
  -d "refresh_token=<refresh-token>"
```

### Use the access token

Include the token as a Bearer token in the `Authorization` header:

```bash
curl -H "Authorization: Bearer <access-token>" \
  https://<tenant>/api/v1/providers
```

### Get user information

If your application requested the `profile` scope, you can retrieve the authenticated user's profile from the UserInfo endpoint:

```bash
curl -H "Authorization: Bearer <access-token>" \
  https://<tenant>/oauth/userinfo
```

A successful response:

```json
{
  "sub": "<user-id>",
  "email": "user@example.com",
  "given_name": "Jane",
  "family_name": "Doe",
  "name": "Jane Doe"
}
```

This endpoint requires a valid access token with the `profile` scope. Requests without the `profile` scope receive a `401 Unauthorized` response.

## Manage client secrets

Client secrets are used alongside the client ID to authenticate token requests. You can create additional secrets for rotation and delete old ones. Each OAuth2 App supports a maximum of 2 client secrets.

1. From the **OAuth2 Apps** list, locate the app and click **Secrets**.
2. Click **Create New Client Secret**.
3. Copy and save the secret value. It will not be shown again. Only the first four characters are displayed for identification after creation.

| Column             | Description                                         |
| ------------------ | --------------------------------------------------- |
| First 4 characters | A partial identifier to distinguish between secrets |
| Created at         | When the secret was generated                       |
| Last used at       | Most recent authentication using this secret        |

Revoked tokens take effect immediately. Veza validates every token against the database on each request, so a deleted or revoked token is rejected on the next use.

To rotate a secret: create a new one, update the application, then wait a few minutes for the new secret to take effect. Verify your application works, then delete the old one.

## Scopes

Scopes control which Veza resources the OAuth2 App can access. Select only the scopes required for your use case.

{% hint style="info" %}
OAuth2 Apps are in early access. Additional scopes will be available in future releases.
{% endhint %}

| Scope                        | Description                                                                                                                                                                 |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `profile`                    | Read the authenticated user's profile information (name, email). Required for integrations that need to identify the user, such as Slack apps that approve access requests. |
| `lcm:access-requests:manage` | Create and manage Lifecycle Management access requests, including approving, rejecting, assigning approvers, and managing watchers.                                         |

{% hint style="info" %}
**Slack App integration**: The [Slack App Veza Action](/4yItIzMvkpAvMVFAamTf/features/access-reviews/configuration/slack-app.md) uses OAuth2 Apps (authorization code flow with PKCE) to authenticate reviewers when they click Approve or Deny from Slack. Configure the OAuth2 App with the `profile` and `lcm:access-requests:manage` scopes and set the redirect URI to `{veza_url}/slackapp/callback`.
{% endhint %}

## Manage OAuth2 Apps

From the **OAuth2 Apps** list, you can:

* **Edit**: Update the app name, base URL, redirect URIs, or allowed scopes.
* **Secrets**: View, create, and delete client secrets.
* **Revoke**: Temporarily disable the app. All active tokens are invalidated immediately.
* **Reinstate**: Re-enable a revoked app so it can authenticate again.
* **Delete**: Permanently remove the app and all associated secrets and tokens.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/developers/api/authentication/oauth2-apps.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
