Merge branch 'main' into core/object-attributes

This commit is contained in:
Jens Langhammer
2026-04-17 18:08:27 +02:00
5 changed files with 87 additions and 40 deletions

6
web/package-lock.json generated
View File

@@ -15005,9 +15005,9 @@
}
},
"node_modules/protocol-buffers-schema": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
"integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==",
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz",
"integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==",
"license": "MIT"
},
"node_modules/proxy-agent": {

View File

@@ -122,6 +122,15 @@ export class IdentificationStage extends BaseStage<
}
}
public override connectedCallback(): void {
super.connectedCallback();
this.addEventListener("focus", this.autofocusTarget.toEventListener());
}
public override firstUpdated(): void {
this.focus();
}
//#endregion
//#region Helper Form
@@ -242,6 +251,7 @@ export class IdentificationStage extends BaseStage<
autocomplete: string,
) {
return html`<input
${this.autofocusTarget.toRef()}
id=${id}
type=${type}
name="uidField"

View File

@@ -205,14 +205,14 @@ return {
}
```
## Signing & Encryption
## Signing and encryption
[JWTs](https://jwt.io/introduction) created by authentik will always be signed.
Selecting **Signing Key** is optional. [JWTs](https://jwt.io/introduction) created by authentik will always be signed.
When a _Signing Key_ is selected in the provider, the JWT will be signed asymmetrically with the private key of the selected certificate, and can be verified using the public key of the certificate. The public key data of the signing key can be retrieved via the JWKS endpoint listed on the provider page.
When **Signing Key** is selected in the provider, authentik signs JWTs asymmetrically with the private key of the selected certificate. Clients can verify those JWTs with the certificate's public key, which is available from the JWKS endpoint listed on the provider page.
When no _Signing Key_ is selected, the JWT will be signed symmetrically with the _Client secret_ of the provider, which can be seen in the provider settings.
When **Signing Key** is not selected, authentik signs JWTs symmetrically with the provider **Client secret**, which is shown in the provider settings.
### Encryption
authentik can also encrypt JWTs (turning them into JWEs) it issues by selecting an _Encryption Key_ in the provider. When selected, all JWTs will be encrypted symmetrically using the selected certificate. authentik uses the `RSA-OAEP-256` algorithm with the `A256CBC-HS512` encryption method.
authentik can also encrypt JWTs (turning them into JWEs) it issues by selecting an **Encryption Key** in the provider. When selected, all JWTs will be encrypted symmetrically using the selected certificate. authentik uses the `RSA-OAEP-256` algorithm with the `A256CBC-HS512` encryption method.

View File

@@ -3,9 +3,9 @@ title: Machine-to-Machine (M2M) authentication
sidebar_label: Machine-to-machine authentication
---
The OAuth 2.0 specification includes the client credentials grant which allows machine-to-machine (M2M) communication authentication, bypassing user involvement. In authentik, machine clients do not authenticate using the typical `client_id` + `client_secret`. This is due to OAuth providers only being able to have a single secret at any given time.
The OAuth 2.0 specification includes the client credentials grant, which allows machine-to-machine (M2M) authentication without user involvement. In authentik, machine clients do not authenticate using the typical `client_id` + `client_secret` combination. This is because OAuth providers can only have a single secret at any given time.
Hence identification is based on a username, and authentication is based on app password tokens.
Instead, identification is based on a username, and authentication is based on app password tokens.
```mermaid
sequenceDiagram
@@ -22,13 +22,13 @@ sequenceDiagram
## Static authentication
All user account types; internal, external and service account, can be used for authentication. These can be created manually beforehand or [automatically during authentication](#automatic-service-account-creation).
All user account types, including internal users, external users, and service accounts, can be used for authentication. These can be created manually beforehand or [automatically during authentication](#automatic-service-account-creation).
authentik treats a grant type of `password` the same as `client_credentials` to support applications which rely on a password grant. Scopes, if required, must be defined in the request, and follow the same behaviour as other OAuth requests.
authentik treats a grant type of `password` the same as `client_credentials` to support applications that rely on a password grant. Scopes, if required, must be defined in the request and follow the same behavior as other OAuth requests.
### Example request
### Request with username and app password
An example request:
**Example**:
```http
POST /application/o/token/ HTTP/1.1
@@ -44,9 +44,11 @@ scope=profile
This will return a JSON response with an `access_token`, which is a signed JWT token. This token can be sent along with requests to other hosts, which can then validate the JWT based on the signing key configured in authentik.
### Base64 encoded username and app password
### Request with Base64-encoded username and app password
It's also possible to encode the username and app password of the user to authenticate with, separated with a colon, into a base64 string and pass it as `client_secret` value, for example:
You can also encode the username and app password of the user to authenticate with, separated by a colon, into a base64 string and pass it as the `client_secret` value.
**Example**:
```http
POST /application/o/token/ HTTP/1.1
@@ -61,7 +63,9 @@ scope=profile
### Automatic service account creation
Alternatively, it's possible to pass the configured `client_secret` value of an OAuth provider, in which case authentik will automatically generate a service account for which the JWT token will be issued, for example:
Alternatively, you can pass the configured `client_secret` value of an OAuth provider. In that case, authentik automatically generates a service account for which the JWT token will be issued.
**Example**:
```http
POST /application/o/token/ HTTP/1.1
@@ -74,19 +78,21 @@ client_secret=<client_secret>&
scope=profile
```
The automatically generated service account will follow this naming scheme: `ak-<provider_name>-client_credentials`. Currently the service account creation settings cannot be altered.
The automatically generated service account follows this naming scheme: `ak-<provider_name>-client_credentials`. Currently, the service account creation settings cannot be altered.
## JWT authentication
For both externally and authentik issued JWTs, authentik will create a service account which is based on the provider name and the subject claim of the token that authentik is given. You may end up with multiple service accounts depending on the tokens that are provided to authentik. These service accounts will expire and be deleted based on the expiry claim (if set) of the token that authentik is given.
For both externally issued and authentik-issued JWTs, authentik creates a service account based on the provider name and the subject claim of the token it receives. You may end up with multiple service accounts depending on the tokens that are provided to authentik. These service accounts expire and are deleted based on the expiry claim, if one is set on the token.
### Externally issued JWTs
You can authenticate and get a token using an existing JWT. For readability we will refer to the JWT issued by the external issuer/platform as input JWT, and the resulting JWT from authentik as the output JWT.
You can authenticate and obtain a token using an existing JWT. For readability, this page refers to the JWT issued by the external issuer or platform as the input JWT, and the resulting JWT from authentik as the output JWT.
To configure this, define a JWKS URL/raw JWKS data in OAuth Sources. If a JWKS URL is specified, authentik will fetch the data and store it in the source, and then select the source in the OAuth2 Provider that will be authenticated against.
To configure this, define a JWKS URL or raw JWKS data in OAuth Sources. If a JWKS URL is specified, authentik fetches the data and stores it in the source. Then select the source in the OAuth2 provider that will be authenticated against.
With this configuration, any JWT issued by the configured sources' certificates can be used to authenticate:
With this configuration, any JWT issued by the configured sources' certificates can be used to authenticate.
**Example**:
```http
POST /application/o/token/ HTTP/1.1
@@ -101,27 +107,31 @@ client_id=<client_id>
Alternatively, you can set the `client_secret` parameter to `<inputJWT>`, for applications that can set the password from a file but not other parameters.
Input JWTs are checked to verify that they are signed by any of the selected _Federated OIDC Sources_, and that their `exp` attribute is not set as now or in the past.
Input JWTs are checked to verify that they are signed by any of the selected **Federated OIDC Sources**, and that their `exp` attribute is not set to the current time or a past time.
To dynamically limit access based on the claims of the tokens, you can use [Expression policies](../../../customize/policies/types/expression/index.mdx), for example:
To dynamically limit access based on the claims of the tokens, you can use [Expression policies](../../../customize/policies/types/expression/index.mdx).
**Example**:
```python
return request.context["oauth_jwt"]["iss"] == "https://my.issuer"
```
Other information that's available in the policy expression context:
Other information is also available in the policy expression context:
- `request.context["oauth_scopes"]` - list of scope names requested
- `request.context["oauth_grant_type"]` - the grant type
- `request.context["oauth_code_verifier"]` - a string or none
If you're authorizing with a JWT, then `request.context["oauth_jwt"]` is available which is the parsed JWT as a dictionary.
If you're authorizing with a JWT, then `request.context["oauth_jwt"]` is also available, which is the parsed JWT as a dictionary.
### authentik-issued JWTs
To allow federation between providers, modify the provider settings of the application (whose token will be used for authentication) to select the provider of the application to which you want to federate.
To allow federation between providers, modify the provider settings of the application whose token will be used for authentication to select the provider of the application to which you want to federate.
With this configuration, any JWT issued by the configured providers can be used to authenticate:
With this configuration, any JWT issued by the configured providers can be used to authenticate.
**Example**:
```http
POST /application/o/token/ HTTP/1.1
@@ -136,29 +146,31 @@ client_id=<client_id>
Alternatively, you can set the `client_secret` parameter to `<inputJWT>`, for applications which can set the password from a file but not other parameters.
Input JWTs must be valid access tokens issued by any of the configured _Federated OIDC Providers_, they must not have been revoked and must not have expired.
Input JWTs must be valid access tokens issued by any of the configured **Federated OIDC Providers**. They must not have been revoked and must not have expired.
To dynamically limit access based on the claims of the tokens, you can use [Expression policies](../../../customize/policies/types/expression/index.mdx), for example:
To dynamically limit access based on the claims of the tokens, you can use [Expression policies](../../../customize/policies/types/expression/index.mdx).
**Example**:
```python
return request.context["oauth_jwt"]["iss"] == "https://my.issuer"
```
Other information that's available in the policy expression context:
Other information is also available in the policy expression context:
- `request.context["oauth_scopes"]` - list of scope names requested
- `request.context["oauth_grant_type"]` - the grant type
- `request.context["oauth_code_verifier"]` - a string or none
If you're authorizing with a JWT, then `request.context["oauth_jwt"]` is available which is the parsed JWT as a dictionary.
If you're authorizing with a JWT, then `request.context["oauth_jwt"]` is also available, which is the parsed JWT as a dictionary.
## Troubleshooting
### More detailed error information
If you receive any error response from authentik it will only be a generic error, error description, and the `request_id`.
If you receive an error response from authentik, it only includes a generic error, an error description, and the `request_id`.
However, more detailed error information can be obtained from the [authentik server container logs](../../../troubleshooting/logs/logs.mdx) by searching for the `request_id` that you're experiencing issues with.
However, you can obtain more detailed error information from the [authentik server container logs](../../../troubleshooting/logs/logs.mdx) by searching for the `request_id` from the response.
### OAuth introspection endpoint
@@ -168,10 +180,8 @@ You are only able to introspect a token from the same provider that was used to
### Event logging
All of these authentication methods will create a login event in the event logs, rather than an authorization event. The event logs will contain different information depending on the scenario:
All of these authentication methods create a login event in the event logs rather than an authorization event. The event logs contain different information depending on the scenario:
| Scenario | Authentication Method | Authentication Arguments |
| ------------------------------------------------------------------------------------------------------------- | --------------------- | -------------------------------------------- |
| [Static authentication using credentials](#static-authentication) | `token` | Dictionary containing the token identifier |
| [Static authentication and automatically generating the service account](#automatic-service-account-creation) | `oauth_client_secret` | N/A |
| [JWT authentication](#jwt-authentication) | `JWT` | Parsed JWT + reference to source or provider |
- [Static authentication using credentials](#static-authentication): Authentication method `token`, with a dictionary containing the token identifier.
- [Static authentication and automatically generating the service account](#automatic-service-account-creation): Authentication method `oauth_client_secret`.
- [JWT authentication](#jwt-authentication): Authentication method `JWT`, with the parsed JWT and a reference to the source or provider.

View File

@@ -73,6 +73,33 @@ return {
}
```
The same LDAP source property mapping type is used for both users and groups. A mapping only applies to groups when you assign it under **Group Property Mappings** on the LDAP source. If you only use the built-in group property mappings, synced groups will keep the automatically populated LDAP attributes, such as `distinguishedName`, but custom LDAP attributes won't be copied unless you add your own group mapping.
### Copy a custom LDAP group attribute
To store a custom LDAP group attribute in authentik's group `attributes`, create an **LDAP Source Property Mapping** and assign it to **Group Property Mappings** on the source:
```python
return {
"attributes": {
"acl": list_flatten(ldap.get("acl")),
},
}
```
If your LDAP server stores the value as JSON text and you want authentik to keep it as structured data instead of a string, decode it in the mapping:
```python
import json
raw_acl = list_flatten(ldap.get("acl"))
return {
"attributes": {
"acl": json.loads(raw_acl) if raw_acl else None,
},
}
```
### Built-in property mappings
LDAP property mappings are used when you define an LDAP source. These mappings define which LDAP property maps to which authentik property. By default, the following mappings are created: