Functions
regex_match(value: Any, regex: str) -> bool¶
Check if value matches Regular Expression regex.
Example:
return regex_match(request.user.username, '.*admin.*')
regex_replace(value: Any, regex: str, repl: str) -> str¶
Replace anything matching regex within value with repl and return it.
Example:
user_email_local = regex_replace(request.user.email, '(.+)@.+', '')
list_flatten(value: list[Any] | Any) -> Optional[Any]¶
Flatten a list by either returning its first element, None if the list is empty, or the passed in object if it's not a list.
Example:
user = list_flatten(["foo"])
# user = "foo"
ak_call_policy(name: str, **kwargs) -> PolicyResult¶
Call another policy with the name name. The current request is passed to the policy. Keyword arguments can be used to modify the request's context.
Example:
result = ak_call_policy("test-policy")
# result is a PolicyResult object, so you can access `.passing` and `.messages`.
# Starting with authentik 2023.4, you can also access `.raw_result`, which is the raw value returned from the called policy
# `result.passing` will always be a boolean if the policy is passing or not.
return result.passing
result = ak_call_policy("test-policy-2", foo="bar")
# Inside the `test-policy-2` you can then use `request.context["foo"]`
return result.passing
:::info Error handling
If the called policy raises an exception, ak_call_policy does not propagate it. A failing PolicyResult
is returned (.passing will be False), with the error message available in .messages.
If no policy matches name, a ValueError is raised and the calling policy fails.
:::
ak_is_group_member(user: User, **group_filters) -> bool¶
Check if user is member of a group matching **group_filters.
Example:
return ak_is_group_member(request.user, name="test_group")
ak_user_by(**filters) -> Optional[User]¶
Fetch a user matching **filters.
Returns None if no user was found; otherwise, returns the User object.
Example:
# Find user by username
other_user = ak_user_by(username="other_user")
# Find user by custom attribute
other_user = ak_user_by(attributes__<custom_attribute_name>="<value>")
ak_user_has_authenticator(user: User, device_type: Optional[str] = None) -> bool¶
Check if a user has any authenticator devices. Only fully validated devices are counted.
Optionally, you can filter by a specific device type. The following options are valid:
totpduostaticwebauthn
Example:
return ak_user_has_authenticator(request.user)
ak_create_event(action: str, **kwargs) -> None¶
Create a new event with the action set to action. Any additional keyword parameters will be saved in the event context. Additionally, context will be set to the context in which this function is called.
Before saving, any data structures which are not representable in JSON are flattened, and credentials are removed.
The event is saved automatically.
Example:
ak_create_event("my_custom_event", foo=request.user)
ak_create_jwt(user: User, provider: OAuth2Provider | str, scopes: list[str], validity = "seconds=60") -> str | None:ak-version[2025.2]¶
:::info Requires HTTP Request This function will only work when there is an HTTP request in the current context. :::
Create a new JWT signed by the given provider for user.
The provider parameter can either be an instance of OAuth2Provider or the name of a provider instance as a string. Scopes are an array of all scopes that the JWT should have.
The JWT is valid for 60 seconds by default, and this can be customized using the validity parameter. The syntax of the parameter is hours=1,minutes=2,seconds=3. The following keys are allowed:
- Microseconds
- Milliseconds
- Seconds
- Minutes
- Hours
- Days
- Weeks
All values accept floating-point values.
Example:
jwt = ak_create_jwt(request.user, "my-oauth2-provider-name", ["openid", "profile", "email"])
ak_create_jwt_raw(provider: OAuth2Provider | str, validity = "seconds=60", **kwargs) -> str | None:ak-version[2025.12]¶
Similar to ak_create_jwt, however this function does not require an HTTP request and allows for setting custom claims via **kwargs.
The provider parameter can either be an instance of OAuth2Provider or the name of a provider instance as a string. Scopes are an array of all scopes that the JWT should have.
The JWT is valid for 60 seconds by default, and this can be customized using the validity parameter. The syntax of the parameter is hours=1,minutes=2,seconds=3. The following keys are allowed:
- Microseconds
- Milliseconds
- Seconds
- Minutes
- Hours
- Days
- Weeks
All values accept floating-point values.
Example:
jwt = ak_create_jwt_raw("my-oauth2-provider-name", my_claim="my_value")
ak_send_email(address: str | tuple[str, str] | list[str | tuple[str, str]], subject: str, body: str = None, stage: EmailStage = None, template: str = None, context: dict = None, cc: str | tuple[str, str] | list[str | tuple[str, str]] = None, bcc: str | tuple[str, str] | list[str | tuple[str, str]] = None) -> bool:ak-version[2025.10]¶
Send an email using authentik's email system.
The address parameter specifies the recipient email address(es). It can be:
- A single email address as a string:
"user@example.com" - A formatted address string that includes a display name:
"John Doe <user@example.com>":ak-version[2026.11] - A
(name, email)tuple:("John Doe", "user@example.com"):ak-version[2026.11] - A list of any of the above:
["user1@example.com", ("Jane Doe", "user2@example.com")]
When a display name is provided, it is included in the To or CC header of the email, matching the format used by the Email stage. Recipients in bcc are never written to a header, so their display name is only used for the delivery address.
:::info
When using multiple recipients in the address or cc fields, all email addresses will be visible to all recipients. Use bcc to send to multiple recipients without revealing addresses to each other.
:::
The subject parameter sets the email subject line.
You must provide either body (for plain text/HTML content) or template (for template rendering), but not both.
The stage parameter can be an EmailStage instance for custom email settings. If None, global email settings are used.
The template parameter specifies a template name to render. When using templates, you can pass additional context variables via the context parameter.
The cc parameter specifies email address(es) to carbon copy. Same format as address.
The bcc parameter specifies email address(es) to blind carbon copy. Same format as address. Recipients in bcc will not be visible to other recipients.
If the email is queued successfully, the function returns True; otherwise, it returns False.
Examples:
# Send email with plain body to single recipient
ak_send_email("user@example.com", "Welcome!", body="Welcome to our platform!")
# Send email with a display name
ak_send_email((request.user.name, request.user.email), "Welcome!", body="Welcome to our platform!")
ak_send_email("John Doe <user@example.com>", "Welcome!", body="Welcome to our platform!")
# Send email to multiple recipients
ak_send_email(
["user1@example.com", "user2@example.com", "admin@example.com"],
"System Maintenance",
body="Scheduled maintenance will occur tonight."
)
# Send email using a template
ak_send_email("user@example.com", "Password Reset", template="email/password_reset.html")
# Send email with custom context for template to multiple recipients
ak_send_email(
["user@example.com", "admin@example.com"],
"Account Update",
template="email/event_notification.html",
context={
"title": "Profile Updated",
"body": "Your account profile has been successfully updated.",
"key_value": {"Updated Field": "Email Address", "Date": "2025-01-01"}
}
)
# Send email with custom email stage
ak_send_email("admin@example.com", "Report", body="Daily report", stage=my_custom_stage)
# Send email with CC
ak_send_email(
"user@example.com",
"Important Update",
body="Please review this update.",
cc="manager@example.com"
)
# Send email with multiple CC and BCC recipients
ak_send_email(
"user@example.com",
"Confidential Report",
body="Attached is the quarterly report.",
cc=["manager@example.com", "lead@example.com"],
bcc=["audit@example.com", "compliance@example.com"]
)
Comparing IP Addresses¶
To compare IP addresses or check if an IP address is within a given subnet, you can use the functions ip_address('192.0.2.1') and ip_network('192.0.2.0/24'). With these objects you can do arithmetic operations.
You can also check if an IP Address is within a subnet by writing the following:
ip_address('192.0.2.1') in ip_network('192.0.2.0/24')
# evaluates to True
DNS resolution and reverse DNS lookups¶
To resolve a hostname to a list of IP addresses, use the functions resolve_dns(hostname) and resolve_dns(hostname, ip_version).
resolve_dns("google.com") # returns a list of all IPv4 and IPv6 addresses
resolve_dns("google.com", 4) # returns a list of only IPv4 addresses
resolve_dns("google.com", 6) # returns a list of only IPv6 addresses
You can also perform reverse DNS lookups.
:::note Reverse DNS lookups may not return the expected host if the IP address is part of a shared hosting environment. See: https://stackoverflow.com/a/19867936 :::
To perform a reverse DNS lookup use reverse_dns("192.0.2.0"). If no DNS records are found the original IP address is returned.
:::info DNS resolving results are cached in memory. The last 32 unique queries are cached for up to 3 minutes. :::