# Authorization code grant flow without proof key for code exchange

## Introduction

While the traditional authorization code flow remains a valid method for web applications, it is highly recommended to adopt Proof Key for Code Exchange (PKCE). By using PKCE, you ensure a more robust and secure implementation of the OAuth 2.0 protocol.

But the OAuth 2.0 specification allows to obtain a token pair via authorization code flow even without PKCE as well. If the external system/application is unable to enhance to support PKCE, then this method can be used.

It consists of the following steps:

---

## Step 1: Authorizing the user

The URL of the Pagero Login page is:

- <https://sso.pageroonline.com/oauth/v2/oauth-authorize>

Request method: **GET**

Required query parameters:

| Parameter       | Description                                                                                                                                                                                                                                                            |
|-----------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `response_type` | Should be set to `code` to generate an `authorization_code`.                                                                                                                                                                                                           |
| `redirect_uri`  | The client URI where the user will be redirected after successfully providing credentials. This URI must be the one that was agreed upon when the client was registered. <br> **Note:** This URI should be URL-encoded with `UTF-8` to ensure it is correctly processed. |
| `client_id`     | The client ID.                                                                                                                                                                                                                                                         |

Optional query parameters:

 Parameter | Description
-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| `state`   | Returned to the client in the final redirect to track the session or prevent unauthorized requests.                                                                                                                                                                                                              |
| `scope`   | The scopes must be separated by spaces. These scopes must be a subset of the scopes configured on the client. <br> **Possible values**: <br> - `all`: Default value <br> - `openid`: If set, it will provide an additional `id_token` property along with the `access_token` and `refresh_token` in the response |
| `prompt`  | Specifies whether the authorization server prompts the user login for re-authentication. <br> **Possible values**: <br> - `login`: Force the user to re-authenticate, ensuring that the person using the application is the legitimate owner of the account.                                                     |

#### Example

- <https://sso.pageroonline.com/oauth/v2/oauth-authorize?response_type=code&client_id=test-client&redirect_uri=https://urltoclient:4443>

---

## Step 2: Obtaining authorization code

Upon successful login, the `authorization_code` is posted back as a query parameter to the url defined in the `redirect_uri` query parameter.

Response Structure:

| Parameter  | Description                                                                                          |
|------------|------------------------------------------------------------------------------------------------------|
| `state`    | Matches the value provided in the initial request. Used to align the request with the redirect response.|
| `iss`      | Identifier of the authorization server where the request was sent.                                    |
| `code`     | A code used for authorization, utilized in the token request.                                         |

#### Example

- <https://urltoclient:4443/?code=0F7ijeaW4BCwhvyg6ozY9PeLsFF6KUi1&state=exampleState&iss=https%3A%2F%2Fauthorization-server.com>

---

## Step 3: Exchanging to a token

Using the `authorization_code`, it’s now possible to obtain an `access_token` and a `refresh_token`.

> [!IMPORTANT]
> The refresh token is issued with a **rolling lifetime of three years**,
> allowing it to generate new access tokens continuously within this period.
> After three years, user authentication will be required to obtain a new refresh token.
>

The URL for doing so is:

- <https://sso.pageroonline.com/oauth/v2/oauth-token>

Request method: **POST**

Required parameters in `application/x-www-form-urlencoded`:

Parameter | Description
------------ | -------------
`grant_type` | Should be `authorization_code`.
`code` | The authorization code.
`redirect_uri` | Must be identical to the redirected uri that was provided in the first step above.
`client_id`* | The client ID.
`client_secret`* | The client secret.

Required headers (if not `client_id` and `client_secret` provided in the body):

Header | Description
------------ | -------------
`Authorization` | Authorization header for basic authorization, where the user should be the client id and password should be the client secret.

Response Structure:

| Parameter       | Description                                                                                                                       |
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `access_token`  | A freshly generated JSON Web Token (JWT)                                                                                          |
| `refresh_token` | A freshly generated refresh token                                                                                                 |
| `expires_in`    | Time in seconds until expiration                                                                                                  |
| `scope`         | A string with space-separated values                                                                                              |
| `token_type`    | Bearer or another type of token                                                                                                   |
| `id_token`*     | A signed JSON Web Token (JWT) containing user information like `email` and this is only present if the `scope` is set to `openid` |

#### Example with header option

```text Example with curl
curl https://sso.pageroonline.com/oauth/v2/oauth-token \
  -d 'grant_type=authorization_code' \
  -d 'code=0F7ijeaW4BCwhvyg6ozY9PeLsFF6KUi1' \
  -d 'redirect_uri=https://urltoclient:4443' \
  --user 'client-id:client-secret'  
```

The response will contain a JSON body that looks like this (when `scope` is set to `all`):

```json
{
  "token_type": "bearer",
  "access_token": "eyJraWQiOiIxNTUzNzgyMDQxIiwieDV0IjoiYldvWF...",
  "refresh_token": "_1XBPWQQ_e61b091b-9139-4268-a7c7-765d2d418d52",
  "scope": "",
  "claims": "publicid",
  "expires_in": 600
}
 ```

> [!NOTE]
> The `access_token` value is redacted for brevity. The actual JWT that is issued will be longer.

---

## Making an API request using an access token

When making an API request, the access token should be provided in an Authentication header as a bearer token.

```text Example with curl
curl https://api.pageroonline.com/someresource \
  -H 'Authorization: Bearer eyJraWQiOiIxNTUzNzgyMDQxIiwieDV0IjoiYldvWF...'
```
