mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-13 09:25:12 +00:00
docs: introduce versioned docs and migrate to fuma (#11166)
## Todos for release - [x] Configure Env in docs project on vercel - [x] Configure Root Path in the docs project on vercel - [ ] Remove old CSP https://github.com/zitadel/website/pull/1592 ## What we did This pull request migrates the project documentation from the old `docs/` directory to the new `apps/docs/` directory, introduces a new documentation system built with Next.js and Fumadocs, and updates all relevant references, configuration files, and documentation to reflect this change. It also adds new configuration and ignore files for the new documentation app, updates CI and linting to exclude the new docs from certain checks, and revises the contributing guidelines accordingly. **Documentation System Migration and New Docs App** * Migrated all documentation from `docs/` to `apps/docs/`, and updated all references in `README.md`, `CONTRIBUTING.md`, and other files to point to the new location. [[1]](diffhunk://#diff-eca12c0a30e25b4b46522ebf89465a03ba72a03f540796c979137931d8f92055L585-L640) [[2]](diffhunk://#diff-eca12c0a30e25b4b46522ebf89465a03ba72a03f540796c979137931d8f92055L660-R607) [[3]](diffhunk://#diff-eca12c0a30e25b4b46522ebf89465a03ba72a03f540796c979137931d8f92055L740-R687) [[4]](diffhunk://#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5L2-R3) [[5]](diffhunk://#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5L30-R30) * Added a new Next.js/Fumadocs-based documentation app under `apps/docs/`, including core app files, layouts, routing, search API, and a comprehensive `README.md` with development and contribution instructions. [[1]](diffhunk://#diff-5a1b07344a2c1b4d3f37b23ff1388b62cd9f57dea3c1cd23d8a0412b7602b132R1-R74) [[2]](diffhunk://#diff-462b9ad1eabbb7d1c29bb9c36e4931eb180fd7190900e6d2babf8f4d66ad1c28R1-R39) [[3]](diffhunk://#diff-e16ae25660ded787b10ac35dea96d5ecaacf895dae0afc8a9bd4382dc79a8c87R1-R7) [apps/docs/app/[[...slug]]/layout.tsxR1-R81](diffhunk://#diff-59e08acde4e805b7aeccef1dcf98f1d71dfc550777e6b9402085cee0e9fa4e0aR1-R81), [apps/docs/app/[[...slug]]/page.tsxR1-R79](diffhunk://#diff-e5df3f80d0fa01e12d63d81f29c57a9d14e846c78fd3beabb2ef768e38fd9580R1-R79), [[4]](diffhunk://#diff-389b34918e040cacaa87cd7201ffa462cc2b0b716736f537e3d3c660ac69353bR1-R7) [[5]](diffhunk://#diff-d3b03416d1c457b19f1c27b26f2db741412df841b875c26ccadc36e4522247f4R1-R29) [[6]](diffhunk://#diff-c8fb8339570a5305809be7c618e14705fd86390dc278e6ce8ba224a7bc8b0c3cR1-R25) **Configuration and Tooling Updates** * Updated `.github/workflows/codeql.yml`, `.golangci.yaml`, and `.github/dependabot.yml` to properly handle the new docs app: excluded `apps/docs` from certain checks, added npm dependency updates for the docs app, and excluded generated content. [[1]](diffhunk://#diff-12783128521e452af0cfac94b99b8d250413c516ec71fe6d97dbea666ff7ba27L8-R14) [[2]](diffhunk://#diff-9917ddc9f1c3304218f7269265b746d997c5c0615478177b5fceecd33ef47cb5R5-R6) [[3]](diffhunk://#diff-9917ddc9f1c3304218f7269265b746d997c5c0615478177b5fceecd33ef47cb5R126-R129) [[4]](diffhunk://#diff-dd4fbda47e51f1e35defb9275a9cd9c212ecde0b870cba89ddaaae65c5f3cd28R89-R106) * Updated `.devcontainer/devcontainer.json` to use the latest Go 1.25.3 version for consistency. **Licensing and Miscellaneous** * Added `apps/docs/` to the list of licensed directories in `LICENSING.md`. These changes ensure the documentation is now maintained in a modern, scalable system and all project tooling is updated to support the new structure. --------- Co-authored-by: Federico Coppede <[email protected]>
This commit is contained in:
co-authored by
Federico Coppede
parent
7b6395c348
commit
d8ea041c56
@@ -0,0 +1,136 @@
|
||||
---
|
||||
title: Authenticate service users and client applications
|
||||
sidebar_label: Authenticate service users
|
||||
---
|
||||
|
||||
import DocCardList from '@/components/docusaurus/doc-card-list';
|
||||
|
||||
This guide explains ZITADEL service users and their role in facilitating secure machine-to-machine communication within your applications.
|
||||
|
||||
## What are Service Users?
|
||||
|
||||
Service users in ZITADEL represent **non-human entities** within your system.
|
||||
They are ideal for scenarios involving secure communication between applications, particularly when interacting with backend services or APIs.
|
||||
Service users in combination with [Manager](/concepts/structure/managers) permissions are used to access ZITADEL's APIs, for example, to manage user resources.
|
||||
Unlike regular human users, service users don't rely on traditional login methods (e.g., username/password) and require alternative authentication mechanisms.
|
||||
|
||||
## Benefits of using Service Users
|
||||
|
||||
### Enhanced security
|
||||
|
||||
* **Principle of Least Privilege:** Grant service users only the minimum permissions they need, minimizing potential damage in case of compromise.
|
||||
* **Distinct Credentials:** Avoid embedding sensitive credentials like API keys directly in code. Service user credentials can be rotated independently.
|
||||
|
||||
### Segregated authorization
|
||||
|
||||
Manage authorization for service users separately from human users, providing an extra layer of control.
|
||||
|
||||
### API and backend access
|
||||
|
||||
Service users offer a secure way to authenticate and access various API endpoints and protected backend services.
|
||||
|
||||
You can [use service users to access ZITADEL APIs](../zitadel-apis/access-zitadel-apis), follow the guides to learn how to access the different ZITADEL APIs.
|
||||
While you can define the scopes and required information in your requests for your applications API endpoints, when using the ZITADEL APIs, you must include the scope `urn:zitadel:iam:org:project:id:zitadel:aud` to gain access.
|
||||
|
||||
### Improved auditability
|
||||
|
||||
Actions performed by service users are clearly identifiable in logs, facilitating easier auditing and tracing.
|
||||
|
||||
Using the [Event API](../zitadel-apis/event-api) you can use these logs for further analysis or to integrate the logs with [external SOC / SIEM](../external-audit-log) systems.
|
||||
|
||||
## Authentication methods
|
||||
|
||||
ZITADEL supports two primary authentication methods for service users:
|
||||
|
||||
### Private key JWT authentication
|
||||
|
||||
#### How private key JWT authentication works
|
||||
|
||||
* Generate a private/public key pair associated with the service user.
|
||||
* Sign JWTs with the private key.
|
||||
* ZITADEL validates the signature using the service user's public key.
|
||||
* JWTs can include expiration dates and scopes to control access.
|
||||
|
||||
Follow our guide on using [private key JWT client authentication](./private-key-jwt) to get started authenticating service users and clients.
|
||||
|
||||
#### Benefits of private key JWT authentication
|
||||
|
||||
* **Decentralized Verification:** No need for constant server calls, improving performance and scalability.
|
||||
* **Flexibility and Control:** Define scopes and expiration within the JWT itself for granular access control.
|
||||
* **Stateless:** The server doesn't need to maintain a session state, simplifying server implementation.
|
||||
|
||||
#### Drawbacks of private key JWT authentication
|
||||
|
||||
* **Complexity:** Slightly more complex to implement compared to other methods, requiring knowledge of JWT and digital signing.
|
||||
* **Revocation:** Invalidating a JWT before its expiry can be challenging; blacklisting mechanisms might be required.
|
||||
|
||||
#### Security considerations when using private key JWT authentication
|
||||
|
||||
* **Secure Key Storage:** The private key used for signing must be stored with the highest level of security. Compromise could allow attackers to forge tokens.
|
||||
* **Short Expirations:** Implementing short expiration durations for JWTs helps limit the impact of stolen tokens.
|
||||
|
||||
### Client credentials grant
|
||||
|
||||
* Presents a client ID and client secret associated with the service user.
|
||||
* Simpler than the JWT profile in specific scenarios.
|
||||
|
||||
Follow our guide on using [client credentials grant](./client-credentials) to get started authenticating service users and clients.
|
||||
|
||||
This method is still available in ZITADEL but is generally considered less secure than JWT due to:
|
||||
|
||||
* **Centralized Validation:** Relies on the server to verify credentials for every request, potentially impacting performance and requiring more server resources.
|
||||
* **Credentials Exposure:** Leaked client ID and secret could be used by attackers to impersonate the service user until rotation occurs.
|
||||
|
||||
### Personal Access Tokens (PATs)
|
||||
|
||||
* **Ready-to-use tokens:** Generated for specific service users and can be directly included in the authorization header of API requests.
|
||||
* **Currently available only for machine users** (service users) and not regular human users.
|
||||
|
||||
Follow our guide on using [personal access tokens](./personal-access-token) to get started authenticating service users and clients.
|
||||
|
||||
PAT offer some benefits, such as:
|
||||
|
||||
* **Ease of Use:** Ready-to-use tokens, eliminating the need for complex signing logic.
|
||||
|
||||
However, PATs also come with limitations:
|
||||
|
||||
* **Centralized Validation:** Similar to Client Credentials, relying on the server for verification could impact performance under high load.
|
||||
* **Revocation:** Requires deleting the PAT directly, potentially causing downtime if not managed carefully.
|
||||
* **Leakage:** PATs are long-lived tokens that can be readily used in API calls, if leaked the attacker can access all resources until the PAT is expired or deleted. Private key JWT and client credentials create a short-lived access token instead.
|
||||
|
||||
## Using Service Users
|
||||
|
||||
1. **Creation:** Access the ZITADEL management console and create a new service user. Assign a descriptive name that reflects its purpose. Follow our detailed guide on [how to create service users](../../manage/console/users).
|
||||
2. **Credentials:** Choose your preferred authentication method (JWT or Client Credentials) and securely store the generated credentials (private key, client secret).
|
||||
3. **Making API Calls:** When your service needs to make an API call:
|
||||
* **For JWT:** Generate and sign a JWT. Include it in the "Authorization" header of your API request.
|
||||
* **For Client Credentials:** Include the client ID and client secret in your API request.
|
||||
* **For PATs:** Include the PAT directly in the "Authorization" header of your API request.
|
||||
4. ZITADEL Verifies the credentials and authorizes the service user to perform the requested action based on its granted permissions.
|
||||
|
||||
We have guides for the different authentication methods:
|
||||
|
||||
- [Private key JWT authentication](./private-key-jwt)
|
||||
- [Client credential authentication](./client-credentials)
|
||||
- [Personal access token authentication](./personal-access-token)
|
||||
|
||||
## Important considerations
|
||||
|
||||
* **Secure Credentials:** Treat service user credentials (private keys, client secrets) with utmost care. Store them securely, similar to any other sensitive information like API keys or passwords.
|
||||
* **Expiry Management:** Set appropriate expiration dates for JWTs and regularly rotate all credentials to maintain strong security practices.
|
||||
* **Permission Granting:** Adhere to the principle of least privilege by granting only the specific permissions required for a service user's function.
|
||||
|
||||
## Choosing the right authentication method
|
||||
|
||||
For most service user scenarios in ZITADEL, [private key JWT authentication](./private-key-jwt) is the recommended choice due to its benefits in security, performance, and control.
|
||||
However, [client credentials authentication](./client-credentials) might be considered in specific situations where simplicity and trust between servers are priorities.
|
||||
|
||||
## Further resources
|
||||
|
||||
* Read about the [different methods to authenticate service users](./authenticate-service-users)
|
||||
* [Service User API reference](/reference/api/user)
|
||||
* [OIDC JWT with private key](/apis/openidoauth/authn-methods#jwt-with-private-key) authentication method reference
|
||||
* [Access ZITADEL APIs](../zitadel-apis/access-zitadel-apis)
|
||||
* Validate access tokens with [token introspection with private key jwt](../token-introspection/private-key-jwt.mdx)
|
||||
|
||||
<DocCardList />
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
title: Configure client credential authentication for service users
|
||||
sidebar_label: Client credential authentication
|
||||
---
|
||||
|
||||
This guide demonstrates how developers can leverage Client Credential authentication to secure communication between [service users](/guides/manage/console/users-overview#service-users-machine-accounts) and client applications within ZITADEL.
|
||||
|
||||
In ZITADEL, the Client Credentials Flow can be used for this [non-interactive authentication](./authenticate-service-users) as alternative to the [JWT profile authentication](./authenticate-service-users).
|
||||
|
||||
## Steps to authenticate a Service User with client credentials
|
||||
|
||||
### 1. Create a Service User with a client secret
|
||||
|
||||
1. Navigate to Service Users
|
||||
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>
|
||||
|
||||

|
||||
|
||||
### 2. Authenticating a service user and request a token
|
||||
|
||||
In this step, we will authenticate a service user 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 user 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 user will get an opaque access token.
|
||||
If you want to get a Jason 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
|
||||
|
||||

|
||||
|
||||
### 3. Include the access token in the authorization header
|
||||
|
||||
When making API requests on behalf of the service user, 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 user 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 user and client application communication within ZITADEL using client credential authentication.
|
||||
|
||||
## Notes
|
||||
|
||||
* Read about the [different methods to authenticate service users](./authenticate-service-users)
|
||||
* [Service User 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)
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Configure personal access token authentication for service users
|
||||
sidebar_label: Personal access token authentication
|
||||
---
|
||||
|
||||
A Personal Access Token (PAT) is a ready to use token which can be used as _Authorization_ header.
|
||||
At the moment ZITADEL only allows PATs for machine accounts (service users).
|
||||
|
||||
It is an alternative to the [private key JWT](./private-key-jwt) and [client credentials](./client-credentials). Read more about the different [authentication methods for service users](./authenticate-service-users).
|
||||
|
||||
## Create a Service User with a PAT
|
||||
|
||||
1. Navigate to Service Users
|
||||
2. Click on **New**
|
||||
3. Enter a user name and a display name
|
||||
4. Click on the Personal Access Token menu point in the detail of your user
|
||||
5. Click on **New**
|
||||
6. You can either set an expiration date or leave it empty if you don't want it to expire
|
||||
7. Copy the token from the dialog (You will not see this again)
|
||||
|
||||

|
||||
|
||||
## Grant role for ZITADEL
|
||||
|
||||
To be able to access the ZITADEL APIs your service user needs permissions to ZITADEL.
|
||||
|
||||
1. Go to the detail page of your organization
|
||||
2. Click in the top right corner the "+" button
|
||||
3. Search for your service user
|
||||
4. Give the user the role you need, for the example we choose Org Owner (More about [ZITADEL Permissions](/guides/manage/console/managers))
|
||||
|
||||

|
||||
|
||||
## 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 user.
|
||||
|
||||
### 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 private key JWT](../token-introspection/private-key-jwt) to learn more.
|
||||
|
||||
## Call ZITADEL API with PAT
|
||||
|
||||
Because the PAT is a ready to use token, you can add it as Authorization Header and send it in your requests to the ZITADEL API.
|
||||
In this example we read the organization of the service user.
|
||||
|
||||
```bash
|
||||
curl --request GET \
|
||||
--url ${CUSTOM_DOMAIN}/management/v1/orgs/me \
|
||||
--header 'Authorization: Bearer {PAT}'
|
||||
```
|
||||
|
||||
## Client application authentication
|
||||
|
||||
The above steps demonstrate service user authentication.
|
||||
If your application also needs to authenticate itself, you can utilize [Client Credentials Grant](./client-credentials).
|
||||
Refer to ZITADEL documentation for details on this alternative method.
|
||||
|
||||
## 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 JWT expiration times:** Limit the validity period of tokens to minimize the impact of potential compromise.
|
||||
* **Implement proper error handling:** Handle situations where JWT verification fails or tokens are expired.
|
||||
|
||||
By following these steps and adhering to security best practices, you can effectively secure service user and client application communication within ZITADEL using private key JWT authentication.
|
||||
@@ -0,0 +1,237 @@
|
||||
---
|
||||
title: Configure private key JWT authentication for service users
|
||||
sidebar_label: Private key JWT authentication
|
||||
---
|
||||
|
||||
This guide explains how developers can use private key JWT authentication to secure communication between service users and client applications in ZITADEL.
|
||||
|
||||
In ZITADEL, the `urn:ietf:params:oauth:grant-type:jwt-bearer` (**"JWT bearer token with private key"**, [RFC7523](https://tools.ietf.org/html/rfc7523)) authorization grant type is used for non-interactive authentication.
|
||||
|
||||
Read more about the [different authentication methods for service users](./authenticate-service-users), including their benefits, drawbacks, and security considerations.
|
||||
|
||||
#### How private key JWT authentication works
|
||||
|
||||
1. Generate a private/public key pair associated with the service user.
|
||||
2. The authorization server stores the public key.
|
||||
3. The authorization server returns the private key as a JSON file.
|
||||
4. The developer configures the client application to use the private key.
|
||||
5. The client creates a JWT assertion with the subject set to the service user and signs the JWT with the private key.
|
||||
6. The client application requests a token from ZITADEL by sending the `client_assertion`.
|
||||
7. The authorization server validates the signature using the service user's public key.
|
||||
8. The authorization server returns an OAuth `access_token`.
|
||||
9. The client sends an API request, including the `access_token` in the Authorization header.
|
||||
10. The resource server validates the JWT with [token introspection](../token-introspection/).
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
A code library or framework that supports JWT generation and verification (such as `pyjwt` for Python or `jsonwebtoken` for Node.js).
|
||||
|
||||
## Steps to authenticate a Service User with private JWT
|
||||
|
||||
Follow these steps to authenticate a service user and obtain an access token for subsequent requests.
|
||||
|
||||
### 1. Create a Service User
|
||||
|
||||
1. Navigate to **Service Users**.
|
||||
2. Click on **New**.
|
||||
3. Enter a username and a display name.
|
||||
4. Click on **Create**.
|
||||
|
||||
### 2. Register a private key for your service user
|
||||
|
||||
You can let ZITADEL generate a private key for you, **or** upload your own (externally generated) public key. Choose one of the following:
|
||||
|
||||
#### Option A: Generate and download a private key from ZITADEL
|
||||
|
||||
1. Open the ZITADEL web console and go to your service user.
|
||||
2. Click on the **Keys** tab.
|
||||
3. Click **New**.
|
||||
4. Optionally set an expiration date for the key, or leave empty for no expiration.
|
||||
5. Click **Download** and save the JSON key file securely.
|
||||
|
||||
#### Option B: Register an existing public key for your service user
|
||||
|
||||
If you already have a key pair, you can upload the public key for your service user. For example, to generate a key pair using OpenSSL:
|
||||
|
||||
```bash
|
||||
# generate key pair
|
||||
openssl genrsa -out privatekey.pem 2048
|
||||
|
||||
# extract public key
|
||||
openssl rsa -in privatekey.pem -pubout -out publickey.pem
|
||||
```
|
||||
|
||||
To upload your public key, use the [User Service Add Key API](/reference/api/user/zitadel.user.v2.UserService.AddKey)
|
||||
|
||||
<Callout>
|
||||
If you generate a key in ZITADEL, make sure to download and securely store the key file right away. For security reasons, ZITADEL cannot show you the private key again after creation. If the key file is lost, you must generate and register a new one.
|
||||
</Callout>
|
||||
|
||||
<Callout title="Expiration">
|
||||
If you set an expiration date when generating a key in ZITADEL, that key will expire at midnight on the specified day.
|
||||
</Callout>
|
||||
|
||||

|
||||
|
||||
If you let ZITADEL generate a key for you and download the JSON file, it will look similar to the example below. In this ZITADEL-generated key file, the `key` property contains the _private_ key for your service account. Store this JSON securely and never share your private key. ZITADEL automatically stores the public key component, so you do not need to upload it.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "serviceaccount",
|
||||
"keyId": "100509901696068329",
|
||||
"key": "-----BEGIN RSA PRIVATE KEY----- [...] -----END RSA PRIVATE KEY-----\n",
|
||||
"userId": "100507859606888466"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Create a JWT and sign it with your private key
|
||||
|
||||
You need to create a JWT with the following header and payload and sign it using the RS256 algorithm.
|
||||
|
||||
Header:
|
||||
|
||||
```json
|
||||
{
|
||||
"alg": "RS256",
|
||||
"kid": "100509901696068329"
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to include the `kid` header with the value of `keyId` from the downloaded JSON.
|
||||
|
||||
Payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"iss": "100507859606888466",
|
||||
"sub": "100507859606888466",
|
||||
"aud": "https://$CUSTOM-DOMAIN",
|
||||
"iat": [Current UTC timestamp, e.g. 1605179982, must be no older than 1 hour],
|
||||
"exp": [Expiration UTC timestamp, e.g. 1605183582]
|
||||
}
|
||||
```
|
||||
|
||||
* `iss`: The entity making the request, i.e., the owner of the private key. Use the `userId` from your downloaded JSON.
|
||||
* `sub`: The application. Set this to the same value as `userId`.
|
||||
* `aud`: Your [Custom Domain](../../../concepts/features/custom-domain).
|
||||
* `iat`: The Unix timestamp when the JWT is created/signed (must be no older than 1 hour).
|
||||
* `exp`: The Unix timestamp when this assertion expires.
|
||||
|
||||
For further details, see the [JWT with private key](/apis/openidoauth/authn-methods#jwt-with-private-key) API reference.
|
||||
|
||||
If you use Go, you can use the [provided tool](https://github.com/zitadel/zitadel-tools) to generate a JWT from the downloaded JSON.
|
||||
There are also [many libraries](https://jwt.io/#libraries-io) available for generating and signing JWTs.
|
||||
|
||||
**Code Example (Python using `pyjwt`):**
|
||||
|
||||
```python
|
||||
import jwt
|
||||
import datetime
|
||||
|
||||
# Replace with your service user ID and private key
|
||||
service_user_id = "your_service_user_id"
|
||||
private_key = "-----BEGIN PRIVATE KEY-----\nYOUR_PRIVATE_KEY\n-----END PRIVATE KEY-----"
|
||||
key_id = "your_key_id"
|
||||
|
||||
# ZITADEL API URL (replace if needed)
|
||||
api_url = "your_custom_domain"
|
||||
|
||||
# Generate JWT claims
|
||||
payload = {
|
||||
"iss": service_user_id,
|
||||
"sub": service_user_id,
|
||||
"aud": api_url,
|
||||
"exp": datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=5),
|
||||
"iat": datetime.datetime.now(datetime.timezone.utc)
|
||||
}
|
||||
|
||||
header = {
|
||||
"alg": "RS256",
|
||||
"kid": key_id
|
||||
}
|
||||
|
||||
# Sign the JWT using the RS256 algorithm
|
||||
encoded_jwt = jwt.encode(payload, private_key, algorithm="RS256", headers=header)
|
||||
|
||||
print(f"Generated JWT: {encoded_jwt}")
|
||||
```
|
||||
|
||||
### 4. Request an OAuth token with the generated JWT
|
||||
|
||||
With the encoded JWT from the previous step, 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=urn:ietf:params:oauth:grant-type:jwt-bearer \
|
||||
--data scope='openid' \
|
||||
--data assertion=eyJ0eXAiOiJKV1QiL...
|
||||
```
|
||||
|
||||
* `grant_type`: Must be set to `urn:ietf:params:oauth:grant-type:jwt-bearer`
|
||||
* `scope`: Include any desired [Scopes](/apis/openidoauth/scopes), but must include `openid`.
|
||||
* `assertion`: The encoded JWT you created and signed with your private key.
|
||||
|
||||
If you want to access ZITADEL APIs, make sure to include the required scope `urn:zitadel:iam:org:project:id:zitadel:aud`.
|
||||
See our guide on [how to access ZITADEL APIs](../zitadel-apis/access-zitadel-apis) for more details.
|
||||
|
||||
**Important Note:** If the service user token must be validated using token introspection, you must include the `urn:zitadel:iam:org:project:id:{projectid}:aud` scope in your token request.
|
||||
If you do not include this, token introspection will fail.
|
||||
|
||||
A successful response will include the `access_token`, `token_type`, and the time to expiry in seconds (`expires_in`):
|
||||
|
||||
```bash
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"access_token": "MtjHodGy4zxKylDOhg6kW90WeEQs2q...",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 43199
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Include the access token in the Authorization header
|
||||
|
||||
When making API requests as the service user, include the generated token in the "Authorization" header with the "Bearer" prefix.
|
||||
|
||||
```bash
|
||||
curl --request POST \
|
||||
--url $YOUR_API_ENDPOINT \
|
||||
--header 'Content-Type: application/x-www-form-urlencoded' \
|
||||
--header 'Authorization: Bearer MtjHodGy4zxKylDOhg6kW90WeEQs2q...'
|
||||
```
|
||||
|
||||
## Accessing ZITADEL APIs
|
||||
|
||||
You may use ZITADEL APIs to manage resources (e.g., users) or to validate tokens received by your backend service.
|
||||
Follow our guide on [how to access ZITADEL API](../zitadel-apis/access-zitadel-apis) with your service user.
|
||||
|
||||
### Token introspection
|
||||
|
||||
If your API endpoint receives tokens from users and needs to validate them with ZITADEL,
|
||||
your API must first authenticate with ZITADEL, then perform a token introspection.
|
||||
See our [guide on token introspection with private key JWT](../token-introspection/private-key-jwt) for details.
|
||||
|
||||
## Client application authentication
|
||||
|
||||
The steps above describe service user authentication.
|
||||
If your application itself also needs authentication, you can use the [Client Credentials Grant](./client-credentials).
|
||||
See the ZITADEL documentation for additional details on this approach.
|
||||
|
||||
## Security considerations
|
||||
|
||||
* **Store private keys securely:** **Never share or embed the private key in your code or application.** Use secure key management solutions whenever possible.
|
||||
* **Set appropriate JWT expiration times:** Limit token validity to reduce risk in the event of a compromise.
|
||||
* **Implement proper error handling:** Handle cases where JWT verification fails or tokens are expired.
|
||||
|
||||
By following these steps and adhering to best practices, you can securely manage service user and client application authentication within ZITADEL using private key JWTs.
|
||||
|
||||
## Notes
|
||||
|
||||
* [JWT with private key](/apis/openidoauth/authn-methods#jwt-with-private-key) API reference
|
||||
* [Accessing ZITADEL API](../zitadel-apis/access-zitadel-apis)
|
||||
* [Token introspection with private key JWT](../token-introspection/private-key-jwt)
|
||||
Reference in New Issue
Block a user