Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: rewrite Optimize API auth guide #4315

Merged
merged 2 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 128 additions & 50 deletions optimize/apis-tools/optimize-api/optimize-api-authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,140 @@ title: "Authentication"
description: "Connect business process-related event data and variable data held in external systems from third-party systems to Optimize, and more."
---

Most requests of the Public REST API need to include a bearer token
as an [`Authorization`](https://tools.ietf.org/html/rfc7235#section-4.2) request header.

Given a valid token `mySecret`, the header would need to be set as follows:

```
Authorization: Bearer mySecret
```

The token used to access the Optimize API can be a configurable shared secret (except in Camunda 8 SaaS mode) or a JWT compliant with the OAuth2 Protocol (all modes).

Refer to [Public API Configuration](../../self-managed/optimize-deployment/configuration/system-configuration.md#public-api) for the particular configuration to access the public API using a token.

## How to obtain the access token for Camunda 8

You must obtain a token to use the Optimize API. When you create an Optimize [client]($docs$/guides/setup-client-connection-credentials/), you get all the information needed to connect to Optimize.

See our guide on [building your own client]($docs$/apis-tools/build-your-own-client/).

The following settings are needed:

| Name | Description | Default value |
| ------------------------ | ----------------------------------------------- | --------------------- |
| client id | Name of your registered client | - |
| client secret | Password for your registered client | - |
| audience | Permission name; if not given use default value | `optimize.camunda.io` |
| authorization server url | Token issuer server | - |

Send a token issue _POST_ request to the authentication server with the following content:

```json
{
"client_id": "<client-id>",
"client_secret": "<client-secret>",
"audience": "<audience>",
"grant_type": "client_credentials"
}
```

See the following example with _curl_:
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

All Optimize API requests except [the health readiness endpoint](./health-readiness.md) require authentication. To authenticate, generate a [JSON Web Token (JWT)](https://jwt.io/introduction/) and include it in each request.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
All Optimize API requests except [the health readiness endpoint](./health-readiness.md) require authentication. To authenticate, generate a [JSON Web Token (JWT)](https://jwt.io/introduction/) and include it in each request.
All Optimize API requests except the [health readiness](./health-readiness.md) endpoint require authentication. To authenticate, generate a [JSON Web Token (JWT)](https://jwt.io/introduction/) and include it in each request.

Suggestion to just have the endpoint name in the link.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No preference on my end, I'll adjust across all APIs in a follow-up.


## Generating a token
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Generating a token
## Generate a token

Suggestion to get away from using gerunds and make it more active, I think I suggested this in other reviews so not sure whether this was adopted - ignore if not, to keep consistent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignoring for now for consistency; I'd like to get through all these rewrites (only one more after this!), and we can standardize this later.


<Tabs groupId="environment" defaultValue="saas" queryString values={
[
{label: 'SaaS', value: 'saas' },
{label: 'Self-Managed', value: 'self-managed' },
]}>
<TabItem value='saas'>

1. [Create client credentials]($docs$/guides/setup-client-connection-credentials/) in the **Clusters > Cluster name > API** tab of [Camunda Console](https://console.camunda.io/).
2. Add permissions to this client for **Optimize**.
3. Upon creating the client, capture the following values required to generate a token:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
3. Upon creating the client, capture the following values required to generate a token:
3. After creating the client, capture the following values required to generate a token:

Suggestion, "upon" doesn't do well in translation here (future proofing).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolution from 4138: it should read "Once you have created the client, capture...".

I'll do this in my follow-up.

<!-- this comment convinces the markdown processor to still treat the table as a table, but without adding surrounding paragraphs. 🤷 -->
| Name | Environment variable name | Default value |
| ------------------------ | -------------------------------- | -------------------------------------------- |
| Client ID | `ZEEBE_CLIENT_ID` | - |
| Client Secret | `ZEEBE_CLIENT_SECRET` | - |
| Authorization Server URL | `ZEEBE_AUTHORIZATION_SERVER_URL` | `https://login.cloud.camunda.io/oauth/token` |
| Optimize REST Address | `CAMUNDA_OPTIMIZE_BASE_URL` | - |
<!-- this comment convinces the markdown processor to still treat the table as a table, but without adding surrounding paragraphs. 🤷 -->
:::tip
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
:::tip
:::caution

Seeing as this is a crucial step if they don't capture the secret, should we make the admonition a caution?

Copy link
Collaborator Author

@pepopowitz pepopowitz Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No preference; I will adjust across all auth guides in a follow-up.

When client credentials are created, the `Client Secret` is only shown once. Save this `Client Secret` somewhere safe.
:::
4. Execute an authentication request to the token issuer:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but I notice we use "execute" a lot, and I'm not sure if we should be replacing this term with "run" or something similar, perhaps not here but wanted to capture this somewhere for discussion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No preference; let me know of any specific changes you'd like me to make in a follow-up.

```bash
curl --request POST ${ZEEBE_AUTHORIZATION_SERVER_URL} \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'audience=optimize.camunda.io' \
--data-urlencode "client_id=${ZEEBE_CLIENT_ID}" \
--data-urlencode "client_secret=${ZEEBE_CLIENT_SECRET}"
```
5. A successful authentication response looks like the following:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this should be a step, as technically each numbered bullet should be an action, so perhaps this belongs in the next step, or as a sub paragraph or something in the previous step? Without seeing the actual doc, I can't envisage what this looks like, so it might not be better when actually rendered, but jsut something I wanted to note.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good call. Here's what it looks like currently:

image

That number 5 could definitely be a separate paragraph under number 4. I'll adjust these across all auth guides in a follow-up.

```json
{
"access_token": "<TOKEN>",
"expires_in": 300,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0
}
```
6. Capture the value of the `access_token` property and store it as your token.

</TabItem>

<TabItem value='self-managed'>

1. [Configure the `api.audience` setting](/self-managed/optimize-deployment/configuration/system-configuration.md#public-api) in your Optimize installation to match the audience property of the **Optimize API** [API in Identity]($docs$/self-managed/identity/user-guide/additional-features/adding-an-api/).
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is different from other API Auth guides, and I don't feel great about requesting that someone re-configure their environment in order to get an auth token....but as discussed in Slack, the out-of-the-box configuration of a Self-Managed instance doesn't actually work for client_credentials authentication.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should "audience" property here be in code (not sure, just asking)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know either, but if someone does and gives me specific changes, I'll take care of them in my follow-up.

2. [Add an M2M application in Identity]($docs$/self-managed/identity/user-guide/additional-features/incorporate-applications/).
3. [Add permissions to this application]($docs$/self-managed/identity/user-guide/additional-features/incorporate-applications/) for **Optimize API**.
4. Capture the `Client ID` and `Client Secret` from the application in Identity.
5. [Generate a token]($docs$/self-managed/identity/user-guide/authorizations/generating-m2m-tokens/) to access the REST API. Provide the `client_id` and `client_secret` from the values you previously captured in Identity.
```shell
curl --location --request POST 'http://localhost:18080/auth/realms/camunda-platform/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "client_secret=${CLIENT_SECRET}" \
--data-urlencode 'grant_type=client_credentials'
```
6. A successful authentication response looks like the following:
```json
{
"access_token": "<TOKEN>",
"expires_in": 300,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0
}
```
7. Capture the value of the `access_token` property and store it as your token.

:::note
The Optimize API can also be configured in a Self-Managed environment to authenticate with a single shared access token. Refer to [Public API Configuration](/self-managed/optimize-deployment/configuration/system-configuration.md#public-api) for the configuration required to access the public API using a specific token.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The Optimize API can also be configured in a Self-Managed environment to authenticate with a single shared access token. Refer to [Public API Configuration](/self-managed/optimize-deployment/configuration/system-configuration.md#public-api) for the configuration required to access the public API using a specific token.
The Optimize API can also be configured in a Self-Managed environment to authenticate using a single shared access token. See [Public API Configuration](/self-managed/optimize-deployment/configuration/system-configuration.md#public-api) for the configuration required to access the public API using a specific token.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll adjust this across all auth guides in a follow-up.

:::

</TabItem>

</Tabs>

## Using a token

Include the previously captured token as an authorization header in each request: `Authorization: Bearer <TOKEN>`.

For example, to send a request to the Optimize API's ["Get dashboard IDs" endpoint](./dashboard/get-dashboard-ids.md):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
For example, to send a request to the Optimize API's ["Get dashboard IDs" endpoint](./dashboard/get-dashboard-ids.md):
For example, to send a request to the Optimize API's ["Get dashboard IDs"](./dashboard/get-dashboard-ids.md) endpoint:

Also, should this endpoint name be in quotes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. I can make these changes in a follow-up, if we decide they're needed.


<Tabs groupId="environment" defaultValue="saas" queryString values={
[
{label: 'SaaS', value: 'saas' },
{label: 'Self-Managed', value: 'self-managed' },
]}>

<TabItem value='saas'>

:::tip
The `${CAMUNDA_TASKLIST_BASE_URL}` variable below represents the URL of the Optimize API. You can capture this URL when creating an API client. You can also construct it as `https://${REGION}.optimize.camunda.io/${CLUSTER_ID}`.
:::

</TabItem>

<TabItem value='self-managed'>

:::tip
The `${CAMUNDA_OPTIMIZE_BASE_URL}` variable below represents the URL of the Optimize API. You can configure this value in your Self-Managed installation. The default value is `http://localhost:8083`.
:::

</TabItem>

</Tabs>

```shell
curl -X POST --header 'content-type: application/json' --data '{"client_id": "<client-id>", "client_secret":"<client-secret>","audience":"<audience>","grant_type":"client_credentials"}' https://<authorization server url>
curl --header "Authorization: Bearer ${TOKEN}" \
-G --data-urlencode "collectionId=${COLLECTION_ID}" \
${CAMUNDA_OPTIMIZE_BASE_URL}/api/public/dashboard
```

If the authentication is successful, the authentication server sends back the access token, when it expires, scope, and type:
A successful response includes [dashboard IDs](./dashboard/get-dashboard-ids.md). For example:

```json
{
"access_token": "ey...",
"scope": "...",
"expires_in": 86400,
"token_type": "Bearer"
}
[
{
"id": "11111111-1111-1111-1111-111111111111"
},
{
"id": "22222222-2222-2222-2222-222222222222"
}
]
```

## Use it in Postman
## Token expiration

Work with this API in our [Postman collection](https://www.postman.com/camundateam/workspace/camunda-8-postman/collection/24684262-a1103c05-7ed8-4fd4-8716-9005583ce23a?action=share&creator=26079299).
Access tokens expire according to the `expires_in` property of a successful authentication response. After this duration, in seconds, you must request a new access token.
Original file line number Diff line number Diff line change
Expand Up @@ -4,62 +4,140 @@ title: "Authentication"
description: "Connect business process-related event data and variable data held in external systems from third-party systems to Optimize, and more."
---

Most requests of the Public REST API need to include a bearer token
as an [`Authorization`](https://tools.ietf.org/html/rfc7235#section-4.2) request header.

Given a valid token `mySecret`, the header would need to be set as follows:

```
Authorization: Bearer mySecret
```

The token used to access the Optimize API can be a configurable shared secret (except in Camunda 8 SaaS mode) or a JWT compliant with the OAuth2 Protocol (all modes).

Refer to [Public API Configuration](../../self-managed/optimize-deployment/configuration/system-configuration.md#public-api) for the particular configuration to access the public API using a token.

## How to obtain the access token for Camunda 8

You must obtain a token to use the Optimize API. When you create an Optimize [client]($docs$/guides/setup-client-connection-credentials/), you get all the information needed to connect to Optimize.

See our guide on [building your own client]($docs$/apis-tools/build-your-own-client/).

The following settings are needed:

| Name | Description | Default value |
| ------------------------ | ----------------------------------------------- | --------------------- |
| client id | Name of your registered client | - |
| client secret | Password for your registered client | - |
| audience | Permission name; if not given use default value | `optimize.camunda.io` |
| authorization server url | Token issuer server | - |

Send a token issue _POST_ request to the authentication server with the following content:

```json
{
"client_id": "<client-id>",
"client_secret": "<client-secret>",
"audience": "<audience>",
"grant_type": "client_credentials"
}
```

See the following example with _curl_:
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

All Optimize API requests except [the health readiness endpoint](./health-readiness.md) require authentication. To authenticate, generate a [JSON Web Token (JWT)](https://jwt.io/introduction/) and include it in each request.

## Generating a token

<Tabs groupId="environment" defaultValue="saas" queryString values={
[
{label: 'SaaS', value: 'saas' },
{label: 'Self-Managed', value: 'self-managed' },
]}>
<TabItem value='saas'>

1. [Create client credentials]($docs$/guides/setup-client-connection-credentials/) in the **Clusters > Cluster name > API** tab of [Camunda Console](https://console.camunda.io/).
2. Add permissions to this client for **Optimize**.
3. Upon creating the client, capture the following values required to generate a token:
<!-- this comment convinces the markdown processor to still treat the table as a table, but without adding surrounding paragraphs. 🤷 -->
| Name | Environment variable name | Default value |
| ------------------------ | -------------------------------- | -------------------------------------------- |
| Client ID | `ZEEBE_CLIENT_ID` | - |
| Client Secret | `ZEEBE_CLIENT_SECRET` | - |
| Authorization Server URL | `ZEEBE_AUTHORIZATION_SERVER_URL` | `https://login.cloud.camunda.io/oauth/token` |
| Optimize REST Address | `CAMUNDA_OPTIMIZE_BASE_URL` | - |
<!-- this comment convinces the markdown processor to still treat the table as a table, but without adding surrounding paragraphs. 🤷 -->
:::tip
When client credentials are created, the `Client Secret` is only shown once. Save this `Client Secret` somewhere safe.
:::
4. Execute an authentication request to the token issuer:
```bash
curl --request POST ${ZEEBE_AUTHORIZATION_SERVER_URL} \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'audience=optimize.camunda.io' \
--data-urlencode "client_id=${ZEEBE_CLIENT_ID}" \
--data-urlencode "client_secret=${ZEEBE_CLIENT_SECRET}"
```
5. A successful authentication response looks like the following:
```json
{
"access_token": "<TOKEN>",
"expires_in": 300,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0
}
```
6. Capture the value of the `access_token` property and store it as your token.

</TabItem>

<TabItem value='self-managed'>

1. [Configure the `api.audience` setting](/self-managed/optimize-deployment/configuration/system-configuration.md#public-api) in your Optimize installation to match the audience property of the **Optimize API** [API in Identity]($docs$/self-managed/identity/user-guide/additional-features/adding-an-api/).
2. [Add an M2M application in Identity]($docs$/self-managed/identity/user-guide/additional-features/incorporate-applications/).
3. [Add permissions to this application]($docs$/self-managed/identity/user-guide/additional-features/incorporate-applications/) for **Optimize API**.
4. Capture the `Client ID` and `Client Secret` from the application in Identity.
5. [Generate a token]($docs$/self-managed/identity/user-guide/authorizations/generating-m2m-tokens/) to access the REST API. Provide the `client_id` and `client_secret` from the values you previously captured in Identity.
```shell
curl --location --request POST 'http://localhost:18080/auth/realms/camunda-platform/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode "client_secret=${CLIENT_SECRET}" \
--data-urlencode 'grant_type=client_credentials'
```
6. A successful authentication response looks like the following:
```json
{
"access_token": "<TOKEN>",
"expires_in": 300,
"refresh_expires_in": 0,
"token_type": "Bearer",
"not-before-policy": 0
}
```
7. Capture the value of the `access_token` property and store it as your token.

:::note
The Optimize API can also be configured in a Self-Managed environment to authenticate with a single shared access token. Refer to [Public API Configuration](/self-managed/optimize-deployment/configuration/system-configuration.md#public-api) for the configuration required to access the public API using a specific token.
:::

</TabItem>

</Tabs>

## Using a token

Include the previously captured token as an authorization header in each request: `Authorization: Bearer <TOKEN>`.

For example, to send a request to the Optimize API's ["Get dashboard IDs" endpoint](./dashboard/get-dashboard-ids.md):

<Tabs groupId="environment" defaultValue="saas" queryString values={
[
{label: 'SaaS', value: 'saas' },
{label: 'Self-Managed', value: 'self-managed' },
]}>

<TabItem value='saas'>

:::tip
The `${CAMUNDA_TASKLIST_BASE_URL}` variable below represents the URL of the Optimize API. You can capture this URL when creating an API client. You can also construct it as `https://${REGION}.optimize.camunda.io/${CLUSTER_ID}`.
:::

</TabItem>

<TabItem value='self-managed'>

:::tip
The `${CAMUNDA_OPTIMIZE_BASE_URL}` variable below represents the URL of the Optimize API. You can configure this value in your Self-Managed installation. The default value is `http://localhost:8083`.
:::

</TabItem>

</Tabs>

```shell
curl -X POST --header 'content-type: application/json' --data '{"client_id": "<client-id>", "client_secret":"<client-secret>","audience":"<audience>","grant_type":"client_credentials"}' https://<authorization server url>
curl --header "Authorization: Bearer ${TOKEN}" \
-G --data-urlencode "collectionId=${COLLECTION_ID}" \
${CAMUNDA_OPTIMIZE_BASE_URL}/api/public/dashboard
```

If the authentication is successful, the authentication server sends back the access token, when it expires, scope, and type:
A successful response includes [dashboard IDs](./dashboard/get-dashboard-ids.md). For example:

```json
{
"access_token": "ey...",
"scope": "...",
"expires_in": 86400,
"token_type": "Bearer"
}
[
{
"id": "11111111-1111-1111-1111-111111111111"
},
{
"id": "22222222-2222-2222-2222-222222222222"
}
]
```

## Use it in Postman
## Token expiration

Work with this API in our [Postman collection](https://www.postman.com/camundateam/workspace/camunda-8-postman/collection/24684262-a1103c05-7ed8-4fd4-8716-9005583ce23a?action=share&creator=26079299).
Access tokens expire according to the `expires_in` property of a successful authentication response. After this duration, in seconds, you must request a new access token.
Loading