website/docs: Add improved akql docs (#22693)

This commit is contained in:
Connor Peshek
2026-06-04 14:32:16 -05:00
committed by GitHub
parent af79cdd1ec
commit b35219e23a
11 changed files with 357 additions and 111 deletions
@@ -85,7 +85,9 @@ export class EventMatcherPolicyForm extends BasePolicyForm<EventMatcherPolicy> {
<a
rel="noopener noreferrer"
target="_blank"
href=${docLink("/sys-mgmt/events/logging-events/#advanced-queries")}
href=${docLink(
"/sys-mgmt/akql/#use-akql-in-an-event-matcher-policy",
)}
>
${msg("See documentation for examples.")}
</a>
+9 -9
View File
@@ -29,15 +29,15 @@ You can also bind a **user** or **group** directly in the same places where you
Use the built-in policy types when they already match what you need. Reach for an expression policy when the built-in types are too limited.
| Policy type | Use it when | Notes |
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| [Event Matcher](./types/event-matcher.md) | You want to react to specific authentik events, usually for notifications or automations. | Matches event action, app, model, and client IP. See [Notifications](../../sys-mgmt/events/notifications.md). |
| [Expression](./types/expression/index.mdx) | You need custom logic that is not covered by a more specialized policy type. | Most flexible option. Runs Python and can inspect flow context, prompt data, user data, request metadata, and more. |
| [GeoIP](./types/geoip.md) | You want to allow or deny requests based on country, ASN, or travel patterns. | Can also check recent login distance and impossible-travel scenarios. |
| [Password](./types/password.md) | You want to validate password complexity, HIBP exposure, or zxcvbn strength. | Commonly attached to a prompt stage's **Validation Policies**. |
| [Password Expiry](./types/password-expiry.md) | You want to expire passwords after a fixed number of days. | Can either deny login or mark the password unusable so the user must update it. |
| [Password Uniqueness](./types/password-uniqueness.md) | You want to prevent password reuse. | Enterprise feature. |
| [Reputation](./types/reputation.md) | You want to react to failed logins or suspicious sign-in activity. | Useful for showing CAPTCHA or another challenge only to low-reputation requests. |
| Policy type | Use it when | Notes |
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| [Event Matcher](./types/event-matcher.md) | You want to react to specific authentik events, usually for notifications or automations. | Matches event action, app, model, client IP, and [AKQL queries](../../sys-mgmt/akql.mdx#use-akql-in-an-event-matcher-policy). |
| [Expression](./types/expression/index.mdx) | You need custom logic that is not covered by a more specialized policy type. | Most flexible option. Runs Python and can inspect flow context, prompt data, user data, request metadata, and more. |
| [GeoIP](./types/geoip.md) | You want to allow or deny requests based on country, ASN, or travel patterns. | Can also check recent login distance and impossible-travel scenarios. |
| [Password](./types/password.md) | You want to validate password complexity, HIBP exposure, or zxcvbn strength. | Commonly attached to a prompt stage's **Validation Policies**. |
| [Password Expiry](./types/password-expiry.md) | You want to expire passwords after a fixed number of days. | Can either deny login or mark the password unusable so the user must update it. |
| [Password Uniqueness](./types/password-uniqueness.md) | You want to prevent password reuse. | Enterprise feature. |
| [Reputation](./types/reputation.md) | You want to react to failed logins or suspicious sign-in activity. | Useful for showing CAPTCHA or another challenge only to low-reputation requests. |
## Deprecated policy types
@@ -6,7 +6,7 @@ tags:
- notifications
---
Use an Event Matcher policy when you want to match authentik events against a small set of built-in fields instead of writing a custom expression.
Use an Event Matcher policy when you want to match authentik events with built-in fields or an [AKQL query](../../../sys-mgmt/akql.mdx#use-akql-in-an-event-matcher-policy).
This policy is most commonly used with [Notification Rules](../../../sys-mgmt/events/notifications.md).
@@ -19,17 +19,19 @@ Use an Event Matcher policy when you want to match against events such as:
- activity from a specific authentik app
- activity from a specific client IP
For more complex matching, such as network ranges or logic across multiple event fields, use an [Expression policy](./expression/index.mdx) instead.
For complex Python logic or network range matching, use an [Expression policy](./expression/index.mdx) instead.
## What it matches
An Event Matcher policy can match on:
An Event Matcher policy can match on these built-in fields:
- action
- app
- model
- exact client IP
It can also match on the **Query** field, which uses AKQL. For the available event fields, operators, and examples, see the [AKQL reference](../../../sys-mgmt/akql.mdx).
Any field you leave empty is treated as a wildcard. Any field you configure must match for the policy to pass.
:::info Event Context
+1 -1
View File
@@ -11,7 +11,7 @@ slug: "/releases/2025.8"
![Screenshot of the admin interface showing events plotted on a histogram chart and on a map](../../sys-mgmt/events/event-map-chart.png)
- **Advanced search**: :ak-enterprise Search for [users](../../users-sources/user/user_basic_operations.md#advanced-queries) and [event logs](../../sys-mgmt/events/logging-events.mdx#advanced-queries) with custom query language to filter on their properties and attributes.
- **Advanced search**: :ak-enterprise Search with [AKQL](../../sys-mgmt/akql.mdx) to filter users and event logs by their properties and attributes.
- **Email stage rate limiting**: The email stage can now be configured to set a maximum number of emails that can be sent within a specified time period.
+2 -2
View File
@@ -9,7 +9,7 @@ slug: "/releases/2026.5"
- **Account Lockdown**: :ak-enterprise A new panic button for compromised accounts that can immediately cut off access, revoke tokens, end sessions, and leave an audit trail.
- **Conditional Access**: :ak-enterprise New connectors verify device compliance and feed it into conditional access flows: Fleet (via Fleet certificates and an mTLS stage, without the authentik agent) and Google Chrome (via Chrome Enterprise Device Trust).
- **`AKQL` is now open source**: The `AKQL` search query language for logs and users, previously enterprise-only, is now free for everyone to use.
- **`AKQL` is now open source**: The `AKQL` search query language, previously enterprise-only, is now free for everyone to use.
- **Command Palette and wizard upgrades**: A new `Cmd + K` command palette to search the authentik UI, alongside reworked wizards including a new user creation wizard, improved binding wizard, and new invitation wizard.
- **Performance improvements**: The new Rust worker entrypoint drops memory usage by approximately 200 MB per worker container, and opens one fewer PostgreSQL connection per worker. The Admin interface is less resource-intensive through lazy-loaded modals.
@@ -67,7 +67,7 @@ Keep in mind that hints are advisory — they only affect the browser UI, not po
### `AKQL` is now open source
The `AKQL` search query language was previously an enterprise-only feature for [querying logs](../../sys-mgmt/events/logging-events.mdx#advanced-queries) and [users](../../users-sources/user/user_basic_operations.md#advanced-queries). `AKQL` is now free for everyone to use, allowing searches based on specific attributes such as `context.geo.country = "Germany"`.
The `AKQL` search query language was previously an enterprise-only feature. `AKQL` is now free for everyone to use, allowing searches based on specific attributes such as `context.geo.country = "Germany"`. For the full syntax and a list of where you can use it, see the [AKQL reference](../../sys-mgmt/akql.mdx).
### OAuth2 configurable grant types
+1
View File
@@ -726,6 +726,7 @@ const items = [
"sys-mgmt/events/event-actions",
],
},
"sys-mgmt/akql",
"sys-mgmt/certificates",
"sys-mgmt/settings",
"sys-mgmt/service-accounts",
+329
View File
@@ -0,0 +1,329 @@
---
title: AKQL search syntax
sidebar_label: AKQL search
description: Use AKQL to filter events, users, groups, and event matcher policies.
---
import { KeyBindingsTable } from "@goauthentik/docusaurus-theme/components/KeyBindingsTable";
AKQL (authentik Query Language) is the advanced search syntax used in the authentik Admin interface and API. Use AKQL to filter long lists, such as events, users, and groups, with structured expressions like `action = "login"` or `context.geo.country = "Germany"`.
AKQL is built on [DjangoQL](https://github.com/ivelum/djangoql).
## Where AKQL is available
AKQL is available on lists and fields backed by the query language:
- **Events** > **Logs**: See [Logging events](./events/logging-events.mdx#advanced-queries).
- **Directory** > **Users**: See [Manage users](../users-sources/user/user_basic_operations.md#advanced-queries).
- **Directory** > **Groups**: See [Manage groups](../users-sources/groups/manage_groups.mdx#advanced-queries).
- **Event Matcher policies**: the **Query** field on an [Event Matcher policy](../customize/policies/types/event-matcher.md#what-it-matches).
- **REST API list endpoints**: the `search` query parameter on endpoints that return an AKQL autocomplete schema. See [Use AKQL through the API](#use-akql-through-the-api).
Each area exposes its own searchable fields. See [Searchable fields](#searchable-fields).
:::info Plain search fallback
If the search string is not a valid AKQL expression, authentik falls back to a plain case-insensitive substring search across that list's default search fields. For example, `bob` runs as plain search, while `username = "bob"` runs as AKQL.
:::
## Query structure
An AKQL query is built from comparisons in this format:
```text
<field> <operator> <value>
```
**Example**:
```text
username = "bob"
```
You can combine comparisons with `and` and `or`, and use parentheses to group conditions.
### Fields
A field is an attribute that you can filter on, such as `username`, `action`, or `is_active`. The available fields depend on the list that you search.
For related objects and JSON values, use dot notation. For example, use `user.username` for a nested user value on an event, and `context.geo.country` for a value inside the event context.
### Operators
The valid operators depend on the field type.
| Operator | Meaning | Field types |
| ---------------- | -------------------------------------- | ----------------------- |
| `=` | Equal to | All field types |
| `!=` | Not equal to | All field types |
| `>` | Greater than | Numbers, dates, strings |
| `>=` | Greater than or equal to | Numbers, dates, strings |
| `<` | Less than | Numbers, dates, strings |
| `<=` | Less than or equal to | Numbers, dates, strings |
| `~` | Contains, case-insensitive | Strings, dates |
| `!~` | Does not contain, case-insensitive | Strings, dates |
| `startswith` | Starts with, case-insensitive | Strings |
| `not startswith` | Does not start with, case-insensitive | Strings |
| `endswith` | Ends with, case-insensitive | Strings |
| `not endswith` | Does not end with, case-insensitive | Strings |
| `in (...)` | Matches any value in the list | All field types |
| `not in (...)` | Matches none of the values in the list | All field types |
:::info `~` is not a regular expression
The `~` and `!~` operators perform a case-insensitive substring match, not a regular-expression match. For example, `username ~ "adm"` matches `akadmin` and `administrator`.
:::
### Values
Values are typed. The way you write the value tells AKQL how to interpret it.
| Type | Syntax | Examples |
| ------- | ----------------------------------------- | -------------------- |
| String | Double quotes or single quotes | `"bob"`, `'login'` |
| Integer | Whole number | `42`, `-7` |
| Float | Decimal or exponent number | `3.14`, `1e3` |
| Boolean | `True` or `False` | `is_active = False` |
| Null | `None` | `email = None` |
| List | Comma-separated values inside parentheses | `("ana", "akadmin")` |
Keep the following rules in mind:
- Operators and keywords such as `and`, `or`, `not`, `in`, `startswith`, and `endswith` are lowercase.
- Boolean and null values use `True`, `False`, and `None`.
- Strings support escape sequences such as `\"`, `\\`, `\n`, `\t`, and `\u00e9`.
- You can compare a field to `None` only when that field is nullable.
### Combine conditions
Use `and` and `or` to combine comparisons.
**Examples**:
```text
action = "login" and user.username = "bob"
```
```text
action = "login" or action = "logout"
```
```text
(action = "login" or action = "logout") and user.username = "bob"
```
:::tip
When you mix `and` and `or`, use parentheses so the grouping is clear.
:::
AKQL does not support a standalone `not` operator for a whole expression. Use `!=` for "not equal to" and `!~` for "does not contain". The `not` keyword is valid only in `not in`, `not startswith`, and `not endswith`.
## Field types
Each searchable field has a type. The field type determines which operators and values it accepts.
### Choice fields
Choice fields, such as an event's `action` or a user's `type`, accept only a fixed set of values. The Admin interface suggests valid values as you type.
### Date and time fields
Date and time fields, such as an event's `created` timestamp, use quoted timestamp values.
Supported formats:
- `"YYYY-MM-DD"`, for example `"2024-01-30"`.
- `"YYYY-MM-DD HH:MM"`, for example `"2024-01-30 09:00"`.
- `"YYYY-MM-DD HH:MM:SS"`, for example `"2024-01-30 09:00:15"`.
**Examples**:
```text
created > "2024-01-01"
```
```text
created >= "2024-01-30 09:00" and created < "2024-01-30 17:00"
```
The `~` operator on a date field performs a substring match on the text form of the timestamp. This is useful for matching a whole day.
```text
created ~ "2024-01-30"
```
### JSON and nested fields
Some searchable fields, such as a user's `attributes` or an event's `context`, contain JSON objects. Use dot notation to query values inside them.
**Examples**:
```text
attributes.department = "engineering"
```
```text
context.geo.country = "Germany"
```
For related objects and JSON objects, query a nested value such as `user.username`, `brand.name`, or `context.http_request.path`. A comparison against the root object, such as `user = "bob"`, is not valid AKQL.
Autocomplete suggests a known subset of nested paths. You can still query other JSON key paths that exist in the stored data.
## Searchable fields
The fields available to AKQL are specific to each list.
### Events
Available in **Events** > **Logs** and in the **Query** field on Event Matcher policies.
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------------------------ |
| `action` | Choice | The [event action](./events/event-actions.md), such as `login`. |
| `event_uuid` | String | The event's unique identifier. |
| `app` | String | The application or authentik component that emitted the event. |
| `client_ip` | String | The client IP address associated with the event. |
| `user.pk` | Integer | The acting user's primary key. |
| `user.username` | String | The acting user's username. |
| `user.email` | String | The acting user's email address. |
| `brand.pk` | String | The primary key of the [brand](../customize/branding.md) active for the event. |
| `brand.app` | String | The brand's app label. |
| `brand.name` | String | The brand's name. |
| `brand.model_name` | String | The brand's model name. |
| `context.*` | JSON | Arbitrary event context. |
| `created` | Date/time | When the event occurred. |
Common event context paths include:
- `context.http_request.path`, `context.http_request.method`, `context.http_request.request_id`, `context.http_request.user_agent`, and `context.http_request.args.*`.
- `context.geo.country`, `context.geo.city`, and other geolocation keys when [GeoIP](./ops/geoip.mdx) is configured.
- `context.authorized_application.name` and other details for the application involved in the event.
### Users
Available in **Directory** > **Users**.
| Field | Type | Description |
| -------------- | ------- | ----------------------------------------------------------------------- |
| `username` | String | The user's username. |
| `name` | String | The user's display name. |
| `email` | String | The user's email address. |
| `path` | String | The user's path within the directory. |
| `is_active` | Boolean | Whether the account is active. |
| `type` | Choice | The user type, such as `internal` or `external`. |
| `attributes.*` | JSON | Any [custom attribute](../users-sources/user/user_ref.mdx) on the user. |
### Groups
Available in **Directory** > **Groups**.
| Field | Type | Description |
| -------------- | ------- | ------------------------------------------ |
| `name` | String | The group's name. |
| `is_superuser` | Boolean | Whether the group grants superuser access. |
| `attributes.*` | JSON | Any custom attribute on the group. |
## Examples
### Event examples
```text
action = "login"
```
```text
app startswith "authentik"
```
```text
user.username in ("ana", "akadmin")
```
```text
context.geo.country = "Germany"
```
### User examples
```text
is_active = False
```
```text
email endswith "@authentik.company"
```
```text
attributes.department = "engineering"
```
### Group examples
```text
is_superuser = True
```
```text
attributes.role = "admin"
```
## Use AKQL through the API
API list endpoints that support AKQL accept the query in the `search` query parameter. URL-encode the query string.
**Example**:
```http
GET /api/v3/core/users/?search=username%20%3D%20%22bob%22
```
The response pagination object includes an `autocomplete` field that describes the searchable schema for the endpoint. The Admin interface uses this schema for autocomplete suggestions.
## Use AKQL in an Event Matcher policy
Use the **Query** field on an [Event Matcher policy](../customize/policies/types/event-matcher.md) to match events with AKQL.
1. In the Admin interface, navigate to **Customization** > **Policies**.
2. Create or edit an **Event Matcher Policy**.
3. In the **Query** field, enter a query that uses the [event fields](#events).
**Example**:
```text
action = "login_failed" and context.geo.country != "United States"
```
The policy passes when the event matches the query. If you configure other fields on the policy, such as **Action** or **App**, the event must match those fields and the AKQL query.
## Autocomplete and keyboard shortcuts
AKQL search fields offer autocomplete suggestions for fields, operators, and values where suggestions are available.
:::info
If an operator or value does not appear in the autocomplete menu, enter it manually.
:::
The following keyboard shortcuts are available in AKQL search fields:
<KeyBindingsTable
aria-label="Keyboard shortcuts for AKQL search"
bindings={[
[
"Autocomplete",
[
["Select next suggestion", <kbd aria-label="Down arrow">↓</kbd>],
["Select previous suggestion", <kbd aria-label="Up arrow">↑</kbd>],
["Accept the current suggestion", <kbd aria-label="Tab key">Tab</kbd>],
["Accept the current suggestion", <kbd aria-label="Enter key">Enter</kbd>],
["Dismiss suggestions", <kbd aria-label="Escape key">ESC</kbd>],
],
],
[
"Search",
[
["Submit the current query", <kbd aria-label="Enter key">Enter</kbd>],
["Clear the current query", <kbd aria-label="Escape key">ESC</kbd>],
],
],
]}
/>
@@ -2,8 +2,6 @@
title: Logging events
---
import { KeyBindingsTable } from "@goauthentik/docusaurus-theme/components/KeyBindingsTable";
Logs are a vital tool for system diagnostics, event auditing, user management, reporting, and more. They capture detailed information about each event including the client's IP address, the user involved, the date and time, and the specific action taken.
Event logging in authentik is highly configurable. You can set the [retention period](./index.md#event-retention-and-forwarding) for storing and displaying events, specify which events should trigger a [notification](./notifications.md), and access low-level details about when and where each event occurred.
@@ -49,76 +47,4 @@ To review, download, or delete past data exports, navigate to **Events** > **Dat
## Advanced queries for event logs {#advanced-queries}
You can construct advanced queries to find specific event logs. In the Admin interface, navigate to **Events** > **Logs**, and then use the auto-complete in the **Search** field or enter your own queries to return results with greater specificity.
- **Field**: `action`, `event_uuid`, `app`, `client_ip`, `user`, `brand`, `context`, `created`
- **Operators**: `=`, `!=`, `~`, `!~`, `startswith`, `not startswith`, `endswith`, `not endswith`, `in`, `not in`
- **Values**: `True`, `False`, `None`, and more
### Examples
The following are examples of advanced queries:
```sh Search event by application name
app startswith "N"
```
```sh Search event by action
action = "login"
```
```sh Search event by authorized application context
authorized_application.name = "My app"
```
```sh Search event by country
context.geo.country = "Germany"
```
```sh Search event by IP address
client_ip = "10.0.0.1"
```
```sh Search event by brand
brand.name = "my brand"
```
```sh Search event by user
user.username in ("ana", "akadmin")
```
For more examples, refer to the list of [Event actions](./event-actions.md) and the related examples for each type of event.
:::info
1. If the list of operators does not appear in a drop-down menu you will need to manually enter it.
2. For queries that include `user`, `brand`, or `context` you need to use a compound term such as `user.username` or `brand.name`.
:::
### Keyboard shortcuts for advanced queries
The following keyboard shortcuts can be used in the advanced query search:
<KeyBindingsTable
aria-label="Keyboard shortcuts for the Query Language (QL) search"
bindings={[
[
"Autocomplete",
[
["Select next suggestion", <kbd aria-label="Down arrow">↓</kbd>],
["Select previous suggestion", <kbd aria-label="Up arrow">↑</kbd>],
["Accept the current suggestion", <kbd aria-label="Enter key">Enter</kbd>],
["Dismiss suggestions", <kbd aria-label="Escape key">ESC</kbd>],
],
],
[
"Search",
[
["Submit the current query", <kbd aria-label="Enter key">Enter</kbd>],
["Clear the current query", <kbd aria-label="Escape key">ESC</kbd>],
],
],
]}
/>
You can use AKQL to filter event logs in **Events** > **Logs**. For the event fields, operators, examples, and keyboard shortcuts, see the [AKQL reference](../akql.mdx).
@@ -27,7 +27,7 @@ You will need to create a policy (either the **Event Matcher** policy or a custo
### Event Matcher policy
For simple event matching you can create and configure an [Event Matcher Policy](../../customize/policies/types/event-matcher.md) to define which events (known as _Actions_ in the policy) will trigger a notification. For example, whenever a user deletes a model object, or whenever any user fails to successfully log in.
For simple event matching, create and configure an [Event Matcher policy](../../customize/policies/types/event-matcher.md) to define which events trigger a notification. Use the policy's [AKQL query](../akql.mdx#use-akql-in-an-event-matcher-policy) when you need to match event context fields such as `context.geo.country` or `context.authorized_application.name`.
Be aware that an event has to match all configured fields in the policy, otherwise the notification rule will not trigger.
@@ -27,6 +27,10 @@ To create a super-user, you need to add the user to a group that has super-user
Super-user permission is inherited by all descendant groups. Make sure you review every member of every descendant group to prevent accidentally granting super-user permission.
:::
## Advanced queries for groups {#advanced-queries}
You can use AKQL to filter the group list in **Directory** > **Groups**. For the group fields, operators, examples, and keyboard shortcuts, see the [AKQL reference](../../sys-mgmt/akql.mdx).
## Modify a group
To edit the group's name, parent groups, whether the group grants superuser permissions, associated roles, and any custom attributes, click the Edit icon beside the role's name. Make the changes and then click **Update**.
@@ -31,25 +31,7 @@ To create a super-user, you need to add the user to a group that has super-user
## Advanced queries for users {#advanced-queries}
You can create advanced queries to locate specific users within the list shown under **Directory** > **Users** in the Admin interface. Use the auto-complete in the **Search** field or enter your own queries to return results with greater specificity.
- **Field**: `username`, `path`, `name`, `email`, `path`, `is_active`, `type`, `attributes`
- **Operators**: `=`, `!=`, `~`, `!~`, `startswith`, `not startswith`, `endswith`, `not endswith`, `in`, `not in`
- **Values**: `True`, `False`, `None`, and more
- **Example queries**:
- search user by status: `is_active = False`
- search user by username: `username = "bob"`
- search user by email address: `email = "bob@authentik.company"`
- search user by attribute: `attribute.my_custom_attribute = "foo"`
:::info
1. To dismiss the drop-down menu option, click **ESC**.
2. If the list of operators does not appear in a drop-down menu you will need to manually enter it.
:::
You can use AKQL to filter the user list in **Directory** > **Users**. For the user fields, operators, examples, and keyboard shortcuts, see the [AKQL reference](../../sys-mgmt/akql.mdx).
## View user details