Files
zitadel/apps/docs/content/guides/integrate/service-accounts/client-credentials.mdx
T
Florian ForsterandGitHub 2763e93a61 docs: shorten page titles for SEO (#11750)
## What

Shorten the `title` frontmatter on 20 docs pages so that the rendered
`<title>` tag stays within the 70-character SEO limit.

The root layout appends ` | ZITADEL Docs` (15 chars) to every page
title, meaning the raw frontmatter `title` must be ≤ 55 characters. A
site scan flagged all 20 pages for the "Title too long" warning (titles
ranged from 71 to 92 characters in the final rendered tag).

## Why

Search engines may truncate or ignore `<title>` tags longer than 70
characters, hurting click-through rates and keyword relevance in search
results.

## How

Each title was rewritten to:
- Fit within 55 characters (leaving room for ` | ZITADEL Docs`)
- Front-load the primary search keyword (product name, protocol, or
feature)
- Include "ZITADEL" where users realistically search for `{feature}
ZITADEL`
- Avoid generic filler words ("Configure", "Set up", "Support for")

All 20 files already have a `sidebar_label` field that preserves the
original descriptive title for sidebar navigation — no navigation
changes result from this PR.

## Pages updated

| Page | Before (chars) | After (chars) |
|---|---|---|
| concepts/features/passkeys | 82 | 64 |
| guides/integrate/identity-providers/openldap | 72 | 58 |
| guides/solution-scenarios/b2b | 78 | 59 |
| guides/integrate/services/cloudflare-oidc | 86 | 54 |
| guides/integrate/login/hosted-login | 71 | 55 |
| guides/integrate/service-accounts/private-key-jwt | 76 | 56 |
| guides/integrate/service-accounts/client-credentials | 78 | 60 |
| guides/integrate/services/google-cloud | 92 | 57 |
| guides/solution-scenarios/saas | 88 | 65 |
| guides/migrate/sources/auth0 | 73 | 65 |
| guides/integrate/login-ui/oidc-standard | 81 | 55 |
| guides/integrate/login-ui/username-password | 73 | 59 |
| guides/integrate/login-ui/device-auth | 78 | 60 |
| guides/integrate/identity-providers/linkedin_oauth | 72 | 58 |
| guides/integrate/identity-providers/pingfederate-saml | 74 | 61 |
| guides/integrate/service-accounts/personal-access-token | 82 | 62 |
| legal/service-description/cloud-service-description | 76 | 61 |
| guides/integrate/login/login-users | 83 | 55 |
| guides/integrate/identity-providers/migrate | 74 | 65 |
| guides/manage/console/projects-overview | 71 | 62 |

All final `<title>` values are between 54 and 66 characters (well under
the 70-char limit).
2026-03-04 11:14:11 +00:00

110 lines
5.3 KiB
Plaintext

---
title: OAuth Client Credentials for Service Accounts
description: "Authenticate service accounts using the industry-standard OAuth 2.0 Client Credentials flow."
sidebar_label: Client credential authentication
---
This guide demonstrates how developers can leverage Client Credential authentication to secure communication between [service accounts](/guides/manage/console/users-overview#service-accounts) and client applications within ZITADEL.
In ZITADEL, the Client Credentials Flow can be used for this [non-interactive authentication](./authenticate-service-accounts) as alternative to the [JWT profile authentication](./authenticate-service-accounts).
## Steps to authenticate a Service Account with client credentials
### 1. Create a Service Account with a client secret
1. Navigate to Service Accounts
2. Click on **New**
3. Enter a username and a display name
4. Click on **Create**
5. Open **Actions** in the top right corner and click on **Generate Client Secret**
6. Copy the **ClientID** and **ClientSecret** from the dialog
<Callout>
Make sure to copy in particular the ClientSecret. You won't be able to retrieve it again.
If you lose it, you will have to generate a new one.
</Callout>
![](../../../../public/img/console_serviceaccounts_secret.gif)
### 2. Authenticating a service account and request a token
In this step, we will authenticate a service account and receive an access_token to use against the ZITADEL API.
You will need to craft a POST request to ZITADEL's token endpoint:
```bash
curl --request POST \
--url https://${CUSTOM_DOMAIN}/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data scope='openid profile' \
--user "$CLIENT_ID:$CLIENT_SECRET"
```
* `CUSTOM_DOMAIN` should be set to your [Custom Domain](/concepts/features/custom-domain)
* `grant_type` should be set to `client_credentials`
* `scope` should contain any [Scopes](/apis/openidoauth/scopes) you want to include, but must include `openid`. For this example, please include `profile`
* `CLIENT_ID` and `CLIENT_SECRET` should be set with the values shown in Management Console when generating a new secret to enable [basic authentication](/apis/openidoauth/authn-methods)
If you want to access ZITADEL APIs, make sure to include the required scopes `urn:zitadel:iam:org:project:id:zitadel:aud`.
Read our guide [how to access ZITADEL APIs](../zitadel-apis/access-zitadel-apis) to learn more.
**Important Note:** If the service account token needs to be validated using token introspection, ensure you include the `urn:zitadel:iam:org:project:id:{projectid}:aud` scope in your token request.
Without this, token introspection will fail.
You should receive a successful response with `access_token`, `token_type` and time to expiry in seconds as `expires_in`.
```bash
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "MtjHodGy4zxKylDOhg6kW90WeEQs2q...",
"token_type": "Bearer",
"expires_in": 43199
}
```
Per default a service account will get an opaque access token.
If you want to get a JSON Web Token (JWT) as an access token for your user, you can change the token type in the general settings of your service account.
To learn more about opaque and JWT tokens read our [Opaque Tokens in ZITADEL: Enhancing Application Security](/concepts/knowledge/opaque-tokens) Guide
![](../../../../public/img/console_service_account_tokentype.png)
### 3. Include the access token in the authorization header
When making API requests on behalf of the service account, include the generated token in the "Authorization" header with the "Bearer" prefix.
```bash
curl --request POST \
--url $YOUR_API_ENDOINT \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer MtjHodGy4zxKylDOhg6kW90WeEQs2q...'
```
## Accessing ZITADEL APIs
You might want to access ZITADEL APIs to manage resources, such as users, or to validate tokens sent to your backend service.
Follow our guides on [how to access ZITADEL API](../zitadel-apis/access-zitadel-apis) to use the ZITADEL APIs with your service account using client credentials.
### Token introspection
Your API endpoint might receive tokens from users and need to validate the token with ZITADEL.
In this case, your API needs to authenticate with ZITADEL and then do a token introspection.
Follow our [guide on token introspection with client credentials](../token-introspection/basic-auth) to learn more.
## Security considerations
* **Store private keys securely:** **Never share or embed the private key in your code or application.** Consider using secure key management solutions.
* **Set appropriate expiration times:** Limit the validity period of tokens to minimize the impact of potential compromise.
By following these steps and adhering to security best practices, you can effectively secure service account and client application communication within ZITADEL using client credential authentication.
## Notes
* Read about the [different methods to authenticate service accounts](./authenticate-service-accounts)
* [Service Account API reference](/reference/api/user)
* [OIDC client secret basic](/apis/openidoauth/authn-methods#client-secret-basic) authentication method reference
* [Access ZITADEL APIs](../zitadel-apis/access-zitadel-apis)
* Validate access tokens with [token introspection with basic auth](../token-introspection/basic-auth)