> For the complete documentation index, see [llms.txt](https://docs.autentique.com.br/api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.autentique.com.br/api/integration-basics/oauth2/authorizing-a-user.md).

# Authorizing a user

In this step, your integration sends the user to Autentique. The user signs in, reviews the requested permissions, and decides whether to grant access.

Before continuing, create an OAuth application and have the following values available:

* the Client ID;
* the registered redirect URL;
* the permissions you will request.

Do not send the Client Secret to the browser. Your backend will use it only when exchanging the authorization code for tokens.

### Protect every authorization attempt

Before redirecting the user, create three values:

| Value            | Purpose                                                                                              |
| ---------------- | ---------------------------------------------------------------------------------------------------- |
| `state`          | Ties the callback to the attempt started by your integration and helps prevent forged requests.      |
| `code_verifier`  | A temporary secret created specifically for that authorization attempt.                              |
| `code_challenge` | A value derived from the `code_verifier` and sent to Autentique without exposing the original value. |

Create new values for every attempt. The `code_verifier` must contain 43 to 128 characters, and the challenge must use S256.

The following example uses Web Crypto and works in JavaScript runtimes that provide `crypto.subtle`:

```javascript
const base64url = (bytes) =>
  btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');

const randomValue = (length = 32) =>
  base64url(crypto.getRandomValues(new Uint8Array(length)));

export async function createOAuthSession() {
  const state = randomValue();
  const codeVerifier = randomValue(64); // 86 characters, within the PKCE limit
  const digest = await crypto.subtle.digest(
    'SHA-256',
    new TextEncoder().encode(codeVerifier),
  );

  return {
    state,
    codeVerifier,
    codeChallenge: base64url(new Uint8Array(digest)),
  };
}
```

Store `state` and `codeVerifier` in a temporary server-side session tied to the user who started the connection. Set a short expiration and remove the session after processing the callback.

If your architecture generates these values in the browser, immediately move them to the temporary server-side session. Do not reuse the values or keep `codeVerifier` in browser storage.

### Build the authorization URL

The authorization endpoint is:

```
https://api.autentique.com.br/oauth/authorize
```

Send the following parameters:

| Parameter               | Value                                            |
| ----------------------- | ------------------------------------------------ |
| `client_id`             | The OAuth application's Client ID.               |
| `redirect_uri`          | The URL registered for the OAuth application.    |
| `response_type`         | Use `code`.                                      |
| `scope`                 | Requested permissions, separated by spaces.      |
| `state`                 | The temporary value created by your integration. |
| `code_challenge`        | The challenge derived from the `code_verifier`.  |
| `code_challenge_method` | Use `S256`.                                      |

Example:

```javascript
const url = new URL('https://api.autentique.com.br/oauth/authorize');
url.search = new URLSearchParams({
  client_id: process.env.AUTENTIQUE_CLIENT_ID,
  redirect_uri: process.env.AUTENTIQUE_REDIRECT_URI,
  response_type: 'code',
  scope: 'user:read documents:read',
  state: oauthSession.state,
  code_challenge: oauthSession.codeChallenge,
  code_challenge_method: 'S256',
  // prompt: 'consent',
}).toString();

return url.toString();
```

The `scope` value must contain only permissions configured for the OAuth application. Separate multiple permissions with spaces.

Use `prompt=consent` only when you need to display the consent screen again.

Redirect the user's browser to the generated URL. Do not make an AJAX request to the authorization endpoint.

### Receive the callback

After the user makes a decision, Autentique redirects the browser to the registered URL.

If access is approved, the callback contains `code` and `state`:

```
https://app.example.com/integrations/autentique/callback?code=CODE&state=VALUE
```

Before using the authorization code:

1. Find the temporary session for that authorization attempt.
2. Compare the returned `state` with the stored value.
3. Confirm that the session has not expired.
4. Remove the session or mark it as used.

If `state` is missing or does not match, end the attempt. Do not exchange the authorization code for tokens.

The authorization code is temporary, single-use, and tied to the OAuth application, redirect URL, and `code_verifier` for that attempt.

### Handle denied authorization

If the user denies access or authorization cannot be completed, the callback may contain:

* `error`;
* `error_description`;
* `state`.

For example:

```
https://app.example.com/integrations/autentique/callback?error=access_denied&state=VALUE
```

Validate `state` for error responses as well. Then tell the user that the connection was not completed and let them try again if they choose.

Do not treat a denial as an unexpected failure or automatically start another authorization attempt.

After validating the callback, continue to **Obtaining and using tokens**.
