Compare commits

..

20 Commits

Author SHA1 Message Date
Jens Langhammer
e10dfdb33f release: 2025.4.4 2025-07-22 14:28:03 +02:00
Jens L
c3629d12bf security: fix CVE-2025-53942 (#15719)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	authentik/stages/user_login/stage.py
#	authentik/stages/user_login/tests.py
#	website/docs/sidebar.mjs
2025-07-22 14:25:29 +02:00
gcp-cherry-pick-bot[bot]
58f82a08be website/docs: add manual RAC outpost deployment information (cherry-pick #15362) (#15434)
website/docs: add manual RAC outpost deployment information (#15362)

* Add RAC deployment information

* Applied suggestions from Tana

* Language change and punctuation

* Updated URLs to authentik.company

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-07-14 00:38:52 +02:00
Jens L
2bc318d167 website: changelog for security releases (#15291)
* website: changelog for security releases

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* format

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	website/docs/releases/2025/v2025.6.md
2025-06-27 15:43:34 +02:00
Jens Langhammer
b34665fabd release: 2025.4.3 2025-06-27 15:34:22 +02:00
Jens L
0e07414e97 security: fix CVE-2025-52553 (#15289)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	website/sidebars/docs.mjs
2025-06-27 15:28:27 +02:00
gcp-cherry-pick-bot[bot]
dcbf5f323c website/docs: fixes misplaced sentence (cherry-pick #14998) (#15181)
website/docs: fixes misplaced sentence (#14998)

fixes misplaced sentence

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-22 00:58:42 +02:00
gcp-cherry-pick-bot[bot]
c3f1d6587d website/docs: fix egregious maintenance fail (cherry-pick #15176) (#15179)
website/docs: fix egregious maintenance fail (#15176)

fix egregious maintenance fail

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-22 00:58:28 +02:00
gcp-cherry-pick-bot[bot]
7254c11cb9 website/docs: remove commented out config options (cherry-pick #15064) (#15066)
website/docs: remove commented out config options (#15064)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-16 16:56:22 +02:00
gcp-cherry-pick-bot[bot]
ca4e6a10f5 website/docs: also hide the postgres pool_options setting (cherry-pick #15023) (#15033)
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-06-13 15:40:52 +02:00
Simonyi Gergő
bda30c5ad5 release: 2025.4.2 2025-06-04 15:27:50 +02:00
gcp-cherry-pick-bot[bot]
588a7ff2e1 website/docs: release notes for 2025.4.2 (cherry-pick #14868) (#14873)
website/docs: release notes for `2025.4.2` (#14868)

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2025-06-04 15:27:08 +02:00
gcp-cherry-pick-bot[bot]
599d0f701f website/docs: release notes for 2025.4.1 (cherry-pick #14526) (#14872)
website/docs: release notes for 2025.4.1 (#14526)

* website/docs: release notes for 2025.4.1



* format



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-04 15:22:52 +02:00
gcp-cherry-pick-bot[bot]
967e4cce9d website/docs: fix leftover placeholder in release notes (cherry-pick #14377) (#14871)
website/docs: fix leftover placeholder in release notes (#14377)

Update v2025.4.md

changed download URL to match version 2025.4. Otherwise it will give a 404

Signed-off-by: finkerle <145992792+finkerle@users.noreply.github.com>
Co-authored-by: finkerle <145992792+finkerle@users.noreply.github.com>
2025-06-04 15:22:39 +02:00
gcp-cherry-pick-bot[bot]
f1c5f43419 website/docs: fix dry-run release highlight (cherry-pick #14337) (#14870)
website/docs: fix dry-run release highlight (#14337)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-04 15:22:00 +02:00
gcp-cherry-pick-bot[bot]
b5b68fc829 website/docs: clarify 2025.4 breaking Reputation changes (cherry-pick #14284) (#14869)
website/docs: clarify `2025.4` breaking Reputation changes (#14284)

* website/docs: clarify `2025.4` breaking Reputation changes

* Update website/docs/releases/2025/v2025.4.md



* change to bump build checks

* another tweak to bounce after rebase

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-04 15:21:28 +02:00
gcp-cherry-pick-bot[bot]
1d7be5e770 core: Migrate permissions before deleteing OldAuthenticatedSession (cherry-pick #14788) (#14791)
core: Migrate permissions before deleteing OldAuthenticatedSession (#14788)

* add migrate_permissions_before_delete to authentik_core 0047 migration

* fix linting

* new approach

* fixup! new approach

---------

Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-05-30 18:05:52 +02:00
gcp-cherry-pick-bot[bot]
489ef7a0a1 ci: fix broken cache (cherry-pick #14725) (#14792)
ci: fix broken cache (#14725)

* ci: fix broken cache



* fix commit hash



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-05-30 17:28:51 +02:00
gcp-cherry-pick-bot[bot]
668f35cd5b sources/scim: fix all users being added to group when no members are given (cherry-pick #14645) (#14666)
sources/scim: fix all users being added to group when no members are given (#14645)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-05-23 17:24:27 +02:00
gcp-cherry-pick-bot[bot]
42f0528a1d lifecycle: fix arguments not being passed to worker command (cherry-pick #14574) (#14620)
Co-authored-by: Jens L. <jens@goauthentik.io>
fix arguments not being passed to worker command (#14574)
2025-05-22 13:51:08 +02:00
31 changed files with 294 additions and 46 deletions

View File

@@ -1,5 +1,5 @@
[bumpversion]
current_version = 2025.4.1
current_version = 2025.4.4
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?

View File

@@ -36,7 +36,7 @@ runs:
with:
go-version-file: "go.mod"
- name: Setup docker cache
uses: ScribeMD/docker-cache@0.5.0
uses: AndreKurait/docker-cache@0fe76702a40db986d9663c24954fc14c6a6031b7
with:
key: docker-images-${{ runner.os }}-${{ hashFiles('.github/actions/setup/docker-compose.yml', 'Makefile') }}-${{ inputs.postgresql_version }}
- name: Setup dependencies

View File

@@ -2,7 +2,7 @@
from os import environ
__version__ = "2025.4.1"
__version__ = "2025.4.4"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@@ -5,6 +5,7 @@ from contextvars import ContextVar
from functools import partial
from uuid import uuid4
from django.contrib.auth import logout
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpRequest, HttpResponse
@@ -58,6 +59,11 @@ class AuthenticationMiddleware(MiddlewareMixin):
request.user = SimpleLazyObject(lambda: get_user(request))
request.auser = partial(aget_user, request)
user = request.user
if user and user.is_authenticated and not user.is_active:
logout(request)
raise AssertionError()
class ImpersonateMiddleware:
"""Middleware to impersonate users"""

View File

@@ -79,6 +79,7 @@ def _migrate_session(
AuthenticatedSession.objects.using(db_alias).create(
session=session,
user=old_auth_session.user,
uuid=old_auth_session.uuid,
)

View File

@@ -1,10 +1,81 @@
# Generated by Django 5.1.9 on 2025-05-14 11:15
from django.apps.registry import Apps
from django.apps.registry import Apps, apps as global_apps
from django.db import migrations
from django.contrib.contenttypes.management import create_contenttypes
from django.contrib.auth.management import create_permissions
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def migrate_authenticated_session_permissions(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
"""Migrate permissions from OldAuthenticatedSession to AuthenticatedSession"""
db_alias = schema_editor.connection.alias
# `apps` here is just an instance of `django.db.migrations.state.AppConfigStub`, we need the
# real config for creating permissions and content types
authentik_core_config = global_apps.get_app_config("authentik_core")
# These are only ran by django after all migrations, but we need them right now.
# `global_apps` is needed,
create_permissions(authentik_core_config, using=db_alias, verbosity=1)
create_contenttypes(authentik_core_config, using=db_alias, verbosity=1)
# But from now on, this is just a regular migration, so use `apps`
Permission = apps.get_model("auth", "Permission")
ContentType = apps.get_model("contenttypes", "ContentType")
try:
old_ct = ContentType.objects.using(db_alias).get(
app_label="authentik_core", model="oldauthenticatedsession"
)
new_ct = ContentType.objects.using(db_alias).get(
app_label="authentik_core", model="authenticatedsession"
)
except ContentType.DoesNotExist:
# This should exist at this point, but if not, let's cut our losses
return
# Get all permissions for the old content type
old_perms = Permission.objects.using(db_alias).filter(content_type=old_ct)
# Create equivalent permissions for the new content type
for old_perm in old_perms:
new_perm = (
Permission.objects.using(db_alias)
.filter(
content_type=new_ct,
codename=old_perm.codename,
)
.first()
)
if not new_perm:
# This should exist at this point, but if not, let's cut our losses
continue
# Global user permissions
User = apps.get_model("authentik_core", "User")
User.user_permissions.through.objects.using(db_alias).filter(
permission=old_perm
).all().update(permission=new_perm)
# Global role permissions
DjangoGroup = apps.get_model("auth", "Group")
DjangoGroup.permissions.through.objects.using(db_alias).filter(
permission=old_perm
).all().update(permission=new_perm)
# Object user permissions
UserObjectPermission = apps.get_model("guardian", "UserObjectPermission")
UserObjectPermission.objects.using(db_alias).filter(permission=old_perm).all().update(
permission=new_perm, content_type=new_ct
)
# Object role permissions
GroupObjectPermission = apps.get_model("guardian", "GroupObjectPermission")
GroupObjectPermission.objects.using(db_alias).filter(permission=old_perm).all().update(
permission=new_perm, content_type=new_ct
)
def remove_old_authenticated_session_content_type(
apps: Apps, schema_editor: BaseDatabaseSchemaEditor
):
@@ -21,7 +92,12 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(
code=migrate_authenticated_session_permissions,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
code=remove_old_authenticated_session_content_type,
reverse_code=migrations.RunPython.noop,
),
]

View File

@@ -66,7 +66,10 @@ class RACClientConsumer(AsyncWebsocketConsumer):
def init_outpost_connection(self):
"""Initialize guac connection settings"""
self.token = (
ConnectionToken.filter_not_expired(token=self.scope["url_route"]["kwargs"]["token"])
ConnectionToken.filter_not_expired(
token=self.scope["url_route"]["kwargs"]["token"],
session__session__session_key=self.scope["session"].session_key,
)
.select_related("endpoint", "provider", "session", "session__user")
.first()
)

View File

@@ -87,3 +87,22 @@ class TestRACViews(APITestCase):
)
body = loads(flow_response.content)
self.assertEqual(body["component"], "ak-stage-access-denied")
def test_different_session(self):
"""Test request"""
self.client.force_login(self.user)
response = self.client.get(
reverse(
"authentik_providers_rac:start",
kwargs={"app": self.app.slug, "endpoint": str(self.endpoint.pk)},
)
)
self.assertEqual(response.status_code, 302)
flow_response = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
)
body = loads(flow_response.content)
next_url = body["to"]
self.client.logout()
final_response = self.client.get(next_url)
self.assertEqual(final_response.url, reverse("authentik_core:if-user"))

View File

@@ -65,7 +65,10 @@ class RACInterface(InterfaceView):
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
# Early sanity check to ensure token still exists
token = ConnectionToken.filter_not_expired(token=self.kwargs["token"]).first()
token = ConnectionToken.filter_not_expired(
token=self.kwargs["token"],
session__session__session_key=request.session.session_key,
).first()
if not token:
return redirect("authentik_core:if-user")
self.token = token

View File

@@ -97,7 +97,8 @@ class GroupsView(SCIMObjectView):
self.logger.warning("Invalid group member", exc=exc)
continue
query |= Q(uuid=member.value)
group.users.set(User.objects.filter(query))
if query:
group.users.set(User.objects.filter(query))
if not connection:
connection, _ = SCIMSourceGroup.objects.get_or_create(
source=self.source,

View File

@@ -89,6 +89,29 @@ class TestPasswordStage(FlowTestCase):
self.assertEqual(response.status_code, 200)
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
def test_valid_password_inactive(self):
"""Test with a valid pending user and valid password"""
self.user.is_active = False
self.user.save()
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
session = self.client.session
session[SESSION_KEY_PLAN] = plan
session.save()
response = self.client.post(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
# Form data
{"password": self.user.username},
)
self.assertEqual(response.status_code, 200)
self.assertStageResponse(
response,
self.flow,
response_errors={"password": [{"string": "Invalid password", "code": "invalid"}]},
)
def test_invalid_password(self):
"""Test with a valid pending user and invalid password"""
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])

View File

@@ -91,6 +91,7 @@ class UserLoginStageView(ChallengeStageView):
user: User = self.executor.plan.context[PLAN_CONTEXT_PENDING_USER]
if not user.is_active:
self.logger.warning("User is not active, login will not work.")
return self.executor.stage_invalid()
delta = self.set_session_duration(remember)
self.set_session_ip()
# the `user_logged_in` signal will update the user to write the `last_login` field

View File

@@ -6,6 +6,7 @@ from unittest.mock import patch
from django.urls import reverse
from django.utils.timezone import now
from authentik.blueprints.tests import apply_blueprint
from authentik.core.models import AuthenticatedSession, Session
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.flows.markers import StageMarker
@@ -174,6 +175,7 @@ class TestUserLoginStage(FlowTestCase):
component="ak-stage-access-denied",
)
@apply_blueprint("default/flow-default-user-settings-flow.yaml")
def test_inactive_account(self):
"""Test with a valid pending user and backend"""
self.user.is_active = False
@@ -187,8 +189,25 @@ class TestUserLoginStage(FlowTestCase):
response = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
)
self.assertEqual(response.status_code, 200)
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
self.assertStageResponse(
response, self.flow, component="ak-stage-access-denied", error_message="Unknown error"
)
# Check that API requests get rejected
response = self.client.get(reverse("authentik_api:application-list"))
self.assertEqual(response.status_code, 403)
# Check that flow requests requiring a user also get rejected
response = self.client.get(
reverse(
"authentik_api:flow-executor",
kwargs={"flow_slug": "default-user-settings-flow"},
)
)
self.assertStageResponse(
response,
self.flow,
component="ak-stage-access-denied",
error_message="Flow does not apply to current user.",
)

View File

@@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://goauthentik.io/blueprints/schema.json",
"type": "object",
"title": "authentik 2025.4.1 Blueprint schema",
"title": "authentik 2025.4.4 Blueprint schema",
"required": [
"version",
"entries"

View File

@@ -31,7 +31,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.4}
restart: unless-stopped
command: server
environment:
@@ -55,7 +55,7 @@ services:
redis:
condition: service_healthy
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.4}
restart: unless-stopped
command: worker
environment:

View File

@@ -29,4 +29,4 @@ func UserAgent() string {
return fmt.Sprintf("authentik@%s", FullVersion())
}
const VERSION = "2025.4.1"
const VERSION = "2025.4.4"

View File

@@ -83,7 +83,8 @@ if [[ "$1" == "server" ]]; then
run_authentik
elif [[ "$1" == "worker" ]]; then
set_mode "worker"
check_if_root "python -m manage worker"
shift
check_if_root "python -m manage worker $@"
elif [[ "$1" == "worker-status" ]]; then
wait_for_db
celery -A authentik.root.celery flower \

View File

@@ -26,7 +26,7 @@ Parameters:
Description: authentik Docker image
AuthentikVersion:
Type: String
Default: 2025.4.1
Default: 2025.4.4
Description: authentik Docker image tag
AuthentikServerCPU:
Type: Number

View File

@@ -1,5 +1,5 @@
{
"name": "@goauthentik/authentik",
"version": "2025.4.1",
"version": "2025.4.4",
"private": true
}

View File

@@ -1,6 +1,6 @@
[project]
name = "authentik"
version = "2025.4.1"
version = "2025.4.4"
description = ""
authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }]
requires-python = "==3.12.*"

View File

@@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2025.4.1
version: 2025.4.4
description: Making authentication simple.
contact:
email: hello@goauthentik.io

2
uv.lock generated
View File

@@ -165,7 +165,7 @@ wheels = [
[[package]]
name = "authentik"
version = "2025.4.1"
version = "2025.4.4"
source = { editable = "." }
dependencies = [
{ name = "argon2-cffi" },

View File

@@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2025.4.1";
export const VERSION = "2025.4.4";
export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";";

View File

@@ -12,19 +12,17 @@ You can also run the outpost in a separate docker-compose project, you just have
services:
authentik_proxy:
image: ghcr.io/goauthentik/proxy
# Optionally specify which networks the container should be
# might be needed to reach the core authentik server
# Optionally specify the container's network, which must be able to reach the core authentik server.
# networks:
# - foo
ports:
- 9000:9000
- 9443:9443
environment:
AUTHENTIK_HOST: https://your-authentik.tld
AUTHENTIK_HOST: https://authentik.company
AUTHENTIK_INSECURE: "false"
AUTHENTIK_TOKEN: token-generated-by-authentik
# Starting with 2021.9, you can optionally set this too
# when authentik_host for internal communication doesn't match the public URL
# Optional setting to be used when `authentik_host` for internal communication doesn't match the public URL.
# AUTHENTIK_HOST_BROWSER: https://external-domain.tld
```
@@ -34,15 +32,29 @@ services:
services:
authentik_ldap:
image: ghcr.io/goauthentik/ldap
# Optionally specify which networks the container should be
# might be needed to reach the core authentik server
# Optionally specify the container's network, which must be able to reach the core authentik server.
# networks:
# - foo
ports:
- 389:3389
- 636:6636
environment:
AUTHENTIK_HOST: https://your-authentik.tld
AUTHENTIK_HOST: https://authentik.company
AUTHENTIK_INSECURE: "false"
AUTHENTIK_TOKEN: token-generated-by-authentik
```
### RAC outpost
```yaml
services:
rac_outpost:
image: ghcr.io/goauthentik/rac
# Optionally specify the container's network, which must be able to reach the core authentik server.
# networks:
# - foo
environment:
AUTHENTIK_HOST: https://authentik.company
AUTHENTIK_INSECURE: "false"
AUTHENTIK_TOKEN: token-generated-by-authentik
```
@@ -53,14 +65,13 @@ services:
services:
radius_outpost:
image: ghcr.io/goauthentik/radius
# Optionally specify which networks the container should be
# might be needed to reach the core authentik server
# Optionally specify the container's network, which must be able to reach the core authentik server.
# networks:
# - foo
ports:
- 1812:1812/udp
environment:
AUTHENTIK_HOST: https://your-authentik.tld
AUTHENTIK_HOST: https://authentik.company
AUTHENTIK_INSECURE: "false"
AUTHENTIK_TOKEN: token-generated-by-authentik
```

View File

@@ -70,9 +70,6 @@ To check if your config has been applied correctly, you can run the following co
- `AUTHENTIK_POSTGRESQL__USER`: Database user
- `AUTHENTIK_POSTGRESQL__PORT`: Database port, defaults to 5432
- `AUTHENTIK_POSTGRESQL__PASSWORD`: Database password, defaults to the environment variable `POSTGRES_PASSWORD`
{/* TODO: Temporarily deactivated feature, see https://github.com/goauthentik/authentik/issues/14320 */}
{/* - `AUTHENTIK_POSTGRESQL__USE_POOL`: Use a [connection pool](https://docs.djangoproject.com/en/stable/ref/databases/#connection-pool) for PostgreSQL connections. Defaults to `false`. :ak-version[2025.4] */}
- `AUTHENTIK_POSTGRESQL__POOL_OPTIONS`: Extra configuration to pass to the [ConnectionPool object](https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool) when it is created. Must be a base64-encoded JSON dictionary. Ignored when `USE_POOL` is set to `false`. :ak-version[2025.4]
- `AUTHENTIK_POSTGRESQL__USE_PGBOUNCER`: Adjust configuration to support connection to PgBouncer. Deprecated, see below
- `AUTHENTIK_POSTGRESQL__USE_PGPOOL`: Adjust configuration to support connection to Pgpool. Deprecated, see below
- `AUTHENTIK_POSTGRESQL__SSLMODE`: Strictness of ssl verification. Defaults to `"verify-ca"`
@@ -85,7 +82,7 @@ To check if your config has been applied correctly, you can run the following co
The PostgreSQL settings `HOST`, `PORT`, `USER`, and `PASSWORD` support hot-reloading. Adding and removing read replicas doesn't support hot-reloading.
- `AUTHENTIK_POSTGRESQL__DEFAULT_SCHEMA`:ak-version[2024.12]
- `AUTHENTIK_POSTGRESQL__DEFAULT_SCHEMA` :ak-version[2024.12]
The name of the schema used by default in the database. Defaults to `public`.

View File

@@ -14,11 +14,11 @@ slug: "/releases/2025.4"
- **Password History Policy** <span class="badge badge--primary">Enterprise</span> A new policy (the Password Uniqueness policy) can be implemented to prevent users from reusing previous passwords; admins are able to configure how many previous password hashes the system will store and evaluate. This new policy makes it easier to enforce password reuse requirements, such as for FedRAMP compliance.
- **Source Sync Dry Run** :ak-preview Add the option for dry-run syncs for SCIM, Google Workspace, and Entra to preview the results of a sync without affecting live accounts.
- **Provider Sync Dry Run** :ak-preview Add the option for dry-run syncs for SCIM, Google Workspace, and Microsoft Entra providers to preview the results of a sync without affecting live accounts.
## Breaking changes
- **Reputation score limit**: The default value for the new limits on Reputation score is between `-5` and `5`. This might break some current setups which count on the possibility of scores decreasing or increasing beyond these limits. You can set your custom limits under **System > Settings**.
- **Reputation score limit**: The default values for the new upper and lower limits on Reputation score are `-5` and `5`. This could break custom policies that rely on the reputation scores decreasing or increasing beyond these limits. You can set your custom limits under **System > Settings**.
- **Deprecated and frozen `:latest` container image tag after 2025.2**
@@ -26,7 +26,7 @@ slug: "/releases/2025.4"
The tag will not be removed, however it will also not be updated past 2025.2.
We strongly recommended the use of a specific version tag for authentik instances' container images like `:2025.4`.
We strongly recommended the use of a specific version tag for authentik instances' container images, such as `:2025.4`.
- **Helm chart dependencies update**: Following [Bitnami's changes to only publish latest version of containers](https://github.com/bitnami/containers/issues/75671), the Helm chart dependencies (PostgreSQL and Redis) will now be updated with each release.
@@ -71,7 +71,7 @@ Previously, sessions were stored by default in the cache. Now, they are stored i
- **Improve membership resolution for the LDAP Source**: See [description](#highlights) under Highlights. Refer to our [documentation](../../users-sources/sources/directory-sync/active-directory/index.md).
- **Source Sync Dry Run**: See [description](#highlights) under Highlights.
- **Provider Sync Dry Run**: See [description](#highlights) under Highlights.
- **Gateway API support** :ak-preview
@@ -109,7 +109,7 @@ When you upgrade, be aware that the version of the authentik instance and of any
To upgrade, download the new docker-compose file and update the Docker stack with the new version, using these commands:
```shell
wget -O docker-compose.yml https://goauthentik.io/version/xxxx.x/docker-compose.yml
wget -O docker-compose.yml https://goauthentik.io/version/2025.4/docker-compose.yml
docker compose up -d
```
@@ -270,6 +270,31 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2025.4
- Revert "website/docs: Prepare for monorepo. (#14119)" (#14239)
- Revert package-lock.json changes from "web: add `remember me` feature to IdentificationStage (#10397)" (#14212)
## Fixed in 2025.4.1
- brands: fix CSS Migration not updating brands (cherry-pick #14306) (#14308)
- core: bump h11 from 0.14.0 to v0.16.0 (cherry-pick #14352) (#14472)
- core: fix session migration when old session can't be loaded (cherry-pick #14466) (#14480)
- core: fix unable to create group if no enable_group_superuser permission is given (cherry-pick #14510) (#14521)
- core: remove `OldAuthenticatedSession` content type (cherry-pick #14507) (#14509)
- enterprise: fix expired license's users being counted (cherry-pick #14451) (#14496)
- lifecycle: fix ak dump_config (cherry-pick #14445) (#14448)
- outposts: fix tmpdir in containers not being set (cherry-pick #14444) (#14449)
- rbac: fix RoleObjectPermissionTable not showing `add_user_to_group` (cherry-pick #14312) (#14334)
- root: backport SFE Build fix (#14495)
- root: temporarily deactivate database pool option (cherry-pick #14443) (#14479)
- web/flows/sfe: fix global background image not being loaded (cherry-pick #14442) (#14450)
## Fixed in 2025.4.2
- core: Migrate permissions before deleting OldAuthenticatedSession (cherry-pick #14788) (#14791)
- lifecycle: fix arguments not being passed to worker command (cherry-pick #14574) (#14620)
- sources/scim: fix all users being added to group when no members are given (cherry-pick #14645) (#14666)
## Fixed in 2025.4.3
- security: fix CVE-2025-52553 (#15289)
## API Changes
#### What's New

View File

@@ -0,0 +1,27 @@
# CVE-2025-52553
_Reported by [SPIEGEL-Verlag](https://gruppe.spiegel.de)_
## Insufficient Session verification for Remote Access Control endpoint access
### Summary
After authorizing access to a RAC endpoint, authentik creates a token which is used for a single connection and is sent to the client in the URL. This token is intended to only be valid for the session of the user who authorized the connection, however this check is currently missing.
### Patches
authentik 2025.4.3 and 2025.6.3 fix this issue.
### Impact
When for example using RAC during a screenshare, a malicious user could access the same session by copying the URL from the shown browser.
### Workarounds
As a workaround it is recommended to decrease the duration a token is valid for (in the RAC Provider settings, set **Connection expiry** to `minutes=5` for example). We also recommend enabling the option **Delete authorization on disconnect**.
### For more information
If you have any questions or comments about this advisory:
- Email us at [security@goauthentik.io](mailto:security@goauthentik.io).

View File

@@ -0,0 +1,29 @@
# CVE-2025-53942
_Reported by [@pascalwei](https://github.com/pascalwei)_
## Insufficient check for account active status when authenticating with OAuth/SAML Sources
### Summary
Deactivated users that had either enrolled via OAuth/SAML or had their account connected to an OAuth/SAML account can still partially access authentik even if their account is deactivated. They end up in a half-authenticated state where they cannot access the API but crucially they can authorize applications if they know the URL of the application.
### Patches
authentik 2025.4.4 and 2025.6.4 fix this issue.
### Workarounds
Adding an expression policy to the user login stage on the respective authentication flow with the expression of
```py
return request.context["pending_user"].is_active
```
This expression will only activate the user login stage when the user is active.
### For more information
If you have any questions or comments about this advisory:
- Email us at [security@goauthentik.io](mailto:security@goauthentik.io).

View File

@@ -2,18 +2,22 @@
title: Events
---
Events are authentik's built-in logging system. Whenever any of the following actions occur, an event is created:
Events are authentik's built-in logging system. Every event is logged, whether it is initiated by a user or by authentik.
Events can be used to define [notification rules](notifications.md), with specified [transport options](transports.md) of local (in the authentik UI), email or webhook.
Certain information is stripped from events, to ensure no passwords or other credentials are saved in the log.
## Event retention
The event retention is configured in the system settings interface, with the default being set to 365 days.
The event retention is configured in the **System > Settings** area of the Admin interface, with the default being set to 365 days.
If you want to forward these events to another application, forward the log output of all authentik containers. Every event creation is logged with the log level "info". For this configuration, it is also recommended to set the internal retention pretty low (for example, `days=1`).
## Event actions
Whenever any of the following actions occur, an event is created.
### `login`
A user logs in (including the source, if available)

View File

@@ -8,9 +8,7 @@ To prevent infinite loops (events created by policies which are attached to a No
## Filtering Events
Starting with authentik 0.15, you can create notification rules, which can alert you based on the creation of certain events.
Filtering is done by using the Policy Engine. You can do simple filtering using the "Event Matcher Policy" type.
An authentik administrator can create notification rules based on the creation of specified events. Filtering is done by using the Policy Engine. You can do simple filtering using the "Event Matcher Policy" type.
![](./event_matcher.png)

View File

@@ -716,7 +716,11 @@ export default {
{
type: "category",
label: "2025",
items: ["security/cves/CVE-2025-29928"],
items: [
"security/cves/CVE-2025-53942",
"security/cves/CVE-2025-52553",
"security/cves/CVE-2025-29928",
],
},
{
type: "category",