Compare commits

..

2 Commits

Author SHA1 Message Date
b0679bb0fa website/docs: Break line. 2025-04-14 17:16:15 +02:00
153fc7cc3b website/docs: Add whitespace. 2025-04-14 17:07:23 +02:00
119 changed files with 8572 additions and 9345 deletions

View File

@ -7,7 +7,7 @@ from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, DateTimeField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ListSerializer
from rest_framework.serializers import ListSerializer, ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.blueprints.models import BlueprintInstance
@ -15,7 +15,7 @@ from authentik.blueprints.v1.importer import Importer
from authentik.blueprints.v1.oci import OCI_PREFIX
from authentik.blueprints.v1.tasks import apply_blueprint, blueprints_find_dict
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import JSONDictField, ModelSerializer, PassiveSerializer
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.rbac.decorators import permission_required

View File

@ -20,8 +20,6 @@ from rest_framework.serializers import (
raise_errors_on_nested_writes,
)
from authentik.rbac.permissions import assign_initial_permissions
def is_dict(value: Any):
"""Ensure a value is a dictionary, useful for JSONFields"""
@ -31,14 +29,6 @@ def is_dict(value: Any):
class ModelSerializer(BaseModelSerializer):
def create(self, validated_data):
instance = super().create(validated_data)
request = self.context.get("request")
if request and hasattr(request, "user") and not request.user.is_anonymous:
assign_initial_permissions(request.user, instance)
return instance
def update(self, instance: Model, validated_data):
raise_errors_on_nested_writes("update", self, validated_data)

View File

@ -1,17 +1,9 @@
"""Test API Utils"""
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import (
HyperlinkedModelSerializer,
)
from rest_framework.serializers import (
ModelSerializer as BaseModelSerializer,
)
from rest_framework.test import APITestCase
from authentik.core.api.utils import ModelSerializer as CustomModelSerializer
from authentik.core.api.utils import is_dict
from authentik.lib.utils.reflection import all_subclasses
class TestAPIUtils(APITestCase):
@ -22,14 +14,3 @@ class TestAPIUtils(APITestCase):
self.assertIsNone(is_dict({}))
with self.assertRaises(ValidationError):
is_dict("foo")
def test_all_serializers_descend_from_custom(self):
"""Test that every serializer we define descends from our own ModelSerializer"""
# Weirdly, there's only one serializer in `rest_framework` which descends from
# ModelSerializer: HyperlinkedModelSerializer
expected = {CustomModelSerializer, HyperlinkedModelSerializer}
actual = set(all_subclasses(BaseModelSerializer)) - set(
all_subclasses(CustomModelSerializer)
)
self.assertEqual(expected, actual)

View File

@ -4,9 +4,10 @@ from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.fields import CharField, ChoiceField, ListField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from structlog.stdlib import get_logger
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.enterprise.providers.ssf.models import (
DeliveryMethods,
EventTypes,

View File

@ -2,11 +2,11 @@
from rest_framework import mixins
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from structlog.stdlib import get_logger
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.enterprise.api import EnterpriseRequiredMixin
from authentik.enterprise.stages.authenticator_endpoint_gdtc.models import (
AuthenticatorEndpointGDTCStage,

View File

@ -48,7 +48,6 @@ class TestFlowInspector(APITestCase):
"allow_show_password": False,
"captcha_stage": None,
"component": "ak-stage-identification",
"enable_remember_me": False,
"flow_info": {
"background": "/static/dist/assets/images/flow_background.jpg",
"cancel_url": reverse("authentik_flows:cancel"),

View File

@ -356,14 +356,6 @@ def redis_url(db: int) -> str:
def django_db_config(config: ConfigLoader | None = None) -> dict:
if not config:
config = CONFIG
pool_options = False
use_pool = config.get_bool("postgresql.use_pool", False)
if use_pool:
pool_options = config.get_dict_from_b64_json("postgresql.pool_options", True)
if not pool_options:
pool_options = True
db = {
"default": {
"ENGINE": "authentik.root.db",
@ -377,7 +369,6 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
"sslrootcert": config.get("postgresql.sslrootcert"),
"sslcert": config.get("postgresql.sslcert"),
"sslkey": config.get("postgresql.sslkey"),
"pool": pool_options,
},
"CONN_MAX_AGE": config.get_optional_int("postgresql.conn_max_age", 0),
"CONN_HEALTH_CHECKS": config.get_bool("postgresql.conn_health_checks", False),

View File

@ -21,7 +21,6 @@ postgresql:
user: authentik
port: 5432
password: "env://POSTGRES_PASSWORD"
use_pool: False
test:
name: test_authentik
default_schema: public

View File

@ -217,7 +217,6 @@ class TestConfig(TestCase):
"HOST": "foo",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -268,7 +267,6 @@ class TestConfig(TestCase):
"HOST": "foo",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -287,7 +285,6 @@ class TestConfig(TestCase):
"HOST": "bar",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -336,7 +333,6 @@ class TestConfig(TestCase):
"HOST": "foo",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -355,7 +351,6 @@ class TestConfig(TestCase):
"HOST": "bar",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -399,7 +394,6 @@ class TestConfig(TestCase):
"HOST": "foo",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -418,7 +412,6 @@ class TestConfig(TestCase):
"HOST": "bar",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -458,7 +451,6 @@ class TestConfig(TestCase):
"HOST": "foo",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "foo",
"sslkey": "foo",
"sslmode": "foo",
@ -477,7 +469,6 @@ class TestConfig(TestCase):
"HOST": "bar",
"NAME": "foo",
"OPTIONS": {
"pool": False,
"sslcert": "bar",
"sslkey": "foo",
"sslmode": "foo",
@ -493,87 +484,3 @@ class TestConfig(TestCase):
},
},
)
def test_db_pool(self):
"""Test DB Config with pool"""
config = ConfigLoader()
config.set("postgresql.host", "foo")
config.set("postgresql.name", "foo")
config.set("postgresql.user", "foo")
config.set("postgresql.password", "foo")
config.set("postgresql.port", "foo")
config.set("postgresql.test.name", "foo")
config.set("postgresql.use_pool", True)
conf = django_db_config(config)
self.assertEqual(
conf,
{
"default": {
"ENGINE": "authentik.root.db",
"HOST": "foo",
"NAME": "foo",
"OPTIONS": {
"pool": True,
"sslcert": None,
"sslkey": None,
"sslmode": None,
"sslrootcert": None,
},
"PASSWORD": "foo",
"PORT": "foo",
"TEST": {"NAME": "foo"},
"USER": "foo",
"CONN_MAX_AGE": 0,
"CONN_HEALTH_CHECKS": False,
"DISABLE_SERVER_SIDE_CURSORS": False,
}
},
)
def test_db_pool_options(self):
"""Test DB Config with pool"""
config = ConfigLoader()
config.set("postgresql.host", "foo")
config.set("postgresql.name", "foo")
config.set("postgresql.user", "foo")
config.set("postgresql.password", "foo")
config.set("postgresql.port", "foo")
config.set("postgresql.test.name", "foo")
config.set("postgresql.use_pool", True)
config.set(
"postgresql.pool_options",
base64.b64encode(
dumps(
{
"max_size": 15,
}
).encode()
).decode(),
)
conf = django_db_config(config)
self.assertEqual(
conf,
{
"default": {
"ENGINE": "authentik.root.db",
"HOST": "foo",
"NAME": "foo",
"OPTIONS": {
"pool": {
"max_size": 15,
},
"sslcert": None,
"sslkey": None,
"sslmode": None,
"sslrootcert": None,
},
"PASSWORD": "foo",
"PORT": "foo",
"TEST": {"NAME": "foo"},
"USER": "foo",
"CONN_MAX_AGE": 0,
"CONN_HEALTH_CHECKS": False,
"DISABLE_SERVER_SIDE_CURSORS": False,
}
},
)

View File

@ -108,9 +108,6 @@ class PolicyEngine:
self.__cached_policies.append(cached_policy)
return True
def _should_fork(self, binding: PolicyBinding) -> bool:
return binding.policy is not None
def build(self) -> "PolicyEngine":
"""Build wrapper which monitors performance"""
with (
@ -137,7 +134,7 @@ class PolicyEngine:
task = PolicyProcess(binding, self.request, task_end)
task.daemon = False
self.logger.debug("P_ENG: Starting Process", binding=binding, request=self.request)
if not CURRENT_PROCESS._config.get("daemon") or not self._should_fork(binding):
if not CURRENT_PROCESS._config.get("daemon"):
task.run()
else:
task.start()

View File

@ -66,9 +66,7 @@ class GeoIPPolicy(Policy):
if not static_results and not dynamic_results:
return PolicyResult(True)
static_passing = any(r.passing for r in static_results) if static_results else True
dynamic_passing = all(r.passing for r in dynamic_results)
passing = static_passing and dynamic_passing
passing = any(r.passing for r in static_results) and all(r.passing for r in dynamic_results)
messages = chain(
*[r.messages for r in static_results], *[r.messages for r in dynamic_results]
)
@ -115,19 +113,13 @@ class GeoIPPolicy(Policy):
to previous authentication requests"""
# Get previous login event and GeoIP data
previous_logins = Event.objects.filter(
action=EventAction.LOGIN,
user__pk=request.user.pk, # context__geo__isnull=False
action=EventAction.LOGIN, user__pk=request.user.pk, context__geo__isnull=False
).order_by("-created")[: self.history_login_count]
_now = now()
geoip_data: GeoIPDict | None = request.context.get("geoip")
if not geoip_data:
return PolicyResult(False)
if not previous_logins.exists():
return PolicyResult(True)
result = False
for previous_login in previous_logins:
if "geo" not in previous_login.context:
continue
previous_login_geoip: GeoIPDict = previous_login.context["geo"]
# Figure out distance
@ -150,8 +142,7 @@ class GeoIPPolicy(Policy):
(MAX_DISTANCE_HOUR_KM * rel_time_hours) + self.distance_tolerance_km
):
return PolicyResult(False, _("Distance is further than possible."))
result = True
return PolicyResult(result)
return PolicyResult(True)
class Meta(Policy.PolicyMeta):
verbose_name = _("GeoIP Policy")

View File

@ -163,7 +163,7 @@ class TestGeoIPPolicy(TestCase):
result: PolicyResult = policy.passes(self.request)
self.assertFalse(result.passing)
def test_history_impossible_travel_failing(self):
def test_history_impossible_travel(self):
"""Test history checks"""
Event.objects.create(
action=EventAction.LOGIN,
@ -181,24 +181,6 @@ class TestGeoIPPolicy(TestCase):
result: PolicyResult = policy.passes(self.request)
self.assertFalse(result.passing)
def test_history_impossible_travel_passing(self):
"""Test history checks"""
Event.objects.create(
action=EventAction.LOGIN,
user=get_user(self.user),
context={
# Random location in Canada
"geo": {"lat": 55.868351, "long": -104.441011},
},
)
# Same location
self.request.context["geoip"] = {"lat": 55.868351, "long": -104.441011}
policy = GeoIPPolicy.objects.create(check_impossible_travel=True)
result: PolicyResult = policy.passes(self.request)
self.assertTrue(result.passing)
def test_history_no_geoip(self):
"""Test history checks (previous login with no geoip data)"""
Event.objects.create(
@ -213,18 +195,3 @@ class TestGeoIPPolicy(TestCase):
result: PolicyResult = policy.passes(self.request)
self.assertFalse(result.passing)
def test_impossible_travel_no_geoip(self):
"""Test impossible travel checks (previous login with no geoip data)"""
Event.objects.create(
action=EventAction.LOGIN,
user=get_user(self.user),
context={},
)
# Random location in Poland
self.request.context["geoip"] = {"lat": 50.950613, "long": 20.363679}
policy = GeoIPPolicy.objects.create(check_impossible_travel=True)
result: PolicyResult = policy.passes(self.request)
self.assertFalse(result.passing)

View File

@ -1,41 +0,0 @@
"""RBAC Initial Permissions"""
from rest_framework.serializers import ListSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.rbac.api.rbac import PermissionSerializer
from authentik.rbac.models import InitialPermissions
class InitialPermissionsSerializer(ModelSerializer):
"""InitialPermissions serializer"""
permissions_obj = ListSerializer(
child=PermissionSerializer(),
read_only=True,
source="permissions",
required=False,
)
class Meta:
model = InitialPermissions
fields = [
"pk",
"name",
"mode",
"role",
"permissions",
"permissions_obj",
]
class InitialPermissionsViewSet(UsedByMixin, ModelViewSet):
"""InitialPermissions viewset"""
queryset = InitialPermissions.objects.all()
serializer_class = InitialPermissionsSerializer
search_fields = ["name"]
ordering = ["name"]
filterset_fields = ["name"]

View File

@ -1,39 +0,0 @@
# Generated by Django 5.0.13 on 2025-04-07 13:05
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
("authentik_rbac", "0004_alter_systempermission_options"),
]
operations = [
migrations.CreateModel(
name="InitialPermissions",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.TextField(max_length=150, unique=True)),
("mode", models.CharField(choices=[("user", "User"), ("role", "Role")])),
("permissions", models.ManyToManyField(blank=True, to="auth.permission")),
(
"role",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="authentik_rbac.role"
),
),
],
options={
"verbose_name": "Initial Permissions",
"verbose_name_plural": "Initial Permissions",
},
),
]

View File

@ -3,7 +3,6 @@
from uuid import uuid4
from django.contrib.auth.management import _get_all_permissions
from django.contrib.auth.models import Permission
from django.db import models
from django.db.transaction import atomic
from django.utils.translation import gettext_lazy as _
@ -76,35 +75,6 @@ class Role(SerializerModel):
]
class InitialPermissionsMode(models.TextChoices):
"""Determines which entity the initial permissions are assigned to."""
USER = "user", _("User")
ROLE = "role", _("Role")
class InitialPermissions(SerializerModel):
"""Assigns permissions for newly created objects."""
name = models.TextField(max_length=150, unique=True)
mode = models.CharField(choices=InitialPermissionsMode.choices)
role = models.ForeignKey(Role, on_delete=models.CASCADE)
permissions = models.ManyToManyField(Permission, blank=True)
@property
def serializer(self) -> type[BaseSerializer]:
from authentik.rbac.api.initial_permissions import InitialPermissionsSerializer
return InitialPermissionsSerializer
def __str__(self) -> str:
return f"Initial Permissions for Role #{self.role_id}, applying to #{self.mode}"
class Meta:
verbose_name = _("Initial Permissions")
verbose_name_plural = _("Initial Permissions")
class SystemPermission(models.Model):
"""System-wide permissions that are not related to any direct
database model"""

View File

@ -1,13 +1,9 @@
"""RBAC Permissions"""
from django.contrib.contenttypes.models import ContentType
from django.db.models import Model
from guardian.shortcuts import assign_perm
from rest_framework.permissions import BasePermission, DjangoObjectPermissions
from rest_framework.request import Request
from authentik.rbac.models import InitialPermissions, InitialPermissionsMode
class ObjectPermissions(DjangoObjectPermissions):
"""RBAC Permissions"""
@ -55,20 +51,3 @@ def HasPermission(*perm: str) -> type[BasePermission]:
return bool(request.user and request.user.has_perms(perm))
return checker
# TODO: add `user: User` type annotation without circular dependencies.
# The author of this function isn't proficient/patient enough to do it.
def assign_initial_permissions(user, instance: Model):
# Performance here should not be an issue, but if needed, there are many optimization routes
initial_permissions_list = InitialPermissions.objects.filter(role__group__in=user.groups.all())
for initial_permissions in initial_permissions_list:
for permission in initial_permissions.permissions.all():
if permission.content_type != ContentType.objects.get_for_model(instance):
continue
assign_to = (
user
if initial_permissions.mode == InitialPermissionsMode.USER
else initial_permissions.role.group
)
assign_perm(permission, assign_to, instance)

View File

@ -1,116 +0,0 @@
"""Test InitialPermissions"""
from django.contrib.auth.models import Permission
from guardian.shortcuts import assign_perm
from rest_framework.reverse import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Group
from authentik.core.tests.utils import create_test_user
from authentik.lib.generators import generate_id
from authentik.rbac.models import InitialPermissions, InitialPermissionsMode, Role
from authentik.stages.dummy.models import DummyStage
class TestInitialPermissions(APITestCase):
"""Test InitialPermissions"""
def setUp(self) -> None:
self.user = create_test_user()
self.same_role_user = create_test_user()
self.different_role_user = create_test_user()
self.role = Role.objects.create(name=generate_id())
self.different_role = Role.objects.create(name=generate_id())
self.group = Group.objects.create(name=generate_id())
self.different_group = Group.objects.create(name=generate_id())
self.group.roles.add(self.role)
self.group.users.add(self.user, self.same_role_user)
self.different_group.roles.add(self.different_role)
self.different_group.users.add(self.different_role_user)
self.ip = InitialPermissions.objects.create(
name=generate_id(), mode=InitialPermissionsMode.USER, role=self.role
)
self.view_role = Permission.objects.filter(codename="view_role").first()
self.ip.permissions.add(self.view_role)
assign_perm("authentik_rbac.add_role", self.user)
self.client.force_login(self.user)
def test_different_role(self):
"""InitialPermissions for different role does nothing"""
self.ip.role = self.different_role
self.ip.save()
self.client.post(reverse("authentik_api:roles-list"), {"name": "test-role"})
role = Role.objects.filter(name="test-role").first()
self.assertFalse(self.user.has_perm("authentik_rbac.view_role", role))
def test_different_model(self):
"""InitialPermissions for different model does nothing"""
assign_perm("authentik_stages_dummy.add_dummystage", self.user)
self.client.post(
reverse("authentik_api:stages-dummy-list"), {"name": "test-stage", "throw-error": False}
)
role = Role.objects.filter(name="test-role").first()
self.assertFalse(self.user.has_perm("authentik_rbac.view_role", role))
stage = DummyStage.objects.filter(name="test-stage").first()
self.assertFalse(self.user.has_perm("authentik_stages_dummy.view_dummystage", stage))
def test_mode_user(self):
"""InitialPermissions adds user permission in user mode"""
self.client.post(reverse("authentik_api:roles-list"), {"name": "test-role"})
role = Role.objects.filter(name="test-role").first()
self.assertTrue(self.user.has_perm("authentik_rbac.view_role", role))
self.assertFalse(self.same_role_user.has_perm("authentik_rbac.view_role", role))
def test_mode_role(self):
"""InitialPermissions adds role permission in role mode"""
self.ip.mode = InitialPermissionsMode.ROLE
self.ip.save()
self.client.post(reverse("authentik_api:roles-list"), {"name": "test-role"})
role = Role.objects.filter(name="test-role").first()
self.assertTrue(self.user.has_perm("authentik_rbac.view_role", role))
self.assertTrue(self.same_role_user.has_perm("authentik_rbac.view_role", role))
def test_many_permissions(self):
"""InitialPermissions can add multiple permissions"""
change_role = Permission.objects.filter(codename="change_role").first()
self.ip.permissions.add(change_role)
self.client.post(reverse("authentik_api:roles-list"), {"name": "test-role"})
role = Role.objects.filter(name="test-role").first()
self.assertTrue(self.user.has_perm("authentik_rbac.view_role", role))
self.assertTrue(self.user.has_perm("authentik_rbac.change_role", role))
def test_permissions_separated_by_role(self):
"""When the triggering user is part of two different roles with InitialPermissions in role
mode, it only adds permissions to the relevant role."""
self.ip.mode = InitialPermissionsMode.ROLE
self.ip.save()
different_ip = InitialPermissions.objects.create(
name=generate_id(), mode=InitialPermissionsMode.ROLE, role=self.different_role
)
change_role = Permission.objects.filter(codename="change_role").first()
different_ip.permissions.add(change_role)
self.different_group.users.add(self.user)
self.client.post(reverse("authentik_api:roles-list"), {"name": "test-role"})
role = Role.objects.filter(name="test-role").first()
self.assertTrue(self.user.has_perm("authentik_rbac.view_role", role))
self.assertTrue(self.same_role_user.has_perm("authentik_rbac.view_role", role))
self.assertFalse(self.different_role_user.has_perm("authentik_rbac.view_role", role))
self.assertTrue(self.user.has_perm("authentik_rbac.change_role", role))
self.assertFalse(self.same_role_user.has_perm("authentik_rbac.change_role", role))
self.assertTrue(self.different_role_user.has_perm("authentik_rbac.change_role", role))

View File

@ -1,6 +1,5 @@
"""RBAC API urls"""
from authentik.rbac.api.initial_permissions import InitialPermissionsViewSet
from authentik.rbac.api.rbac import RBACPermissionViewSet
from authentik.rbac.api.rbac_assigned_by_roles import RoleAssignedPermissionViewSet
from authentik.rbac.api.rbac_assigned_by_users import UserAssignedPermissionViewSet
@ -22,6 +21,5 @@ api_urlpatterns = [
("rbac/permissions/users", UserPermissionViewSet, "permissions-users"),
("rbac/permissions/roles", RolePermissionViewSet, "permissions-roles"),
("rbac/permissions", RBACPermissionViewSet),
("rbac/roles", RoleViewSet, "roles"),
("rbac/initial_permissions", InitialPermissionsViewSet, "initial-permissions"),
("rbac/roles", RoleViewSet),
]

View File

@ -130,7 +130,6 @@ class OAuthSourceSerializer(SourceSerializer):
"oidc_well_known_url",
"oidc_jwks_url",
"oidc_jwks",
"authorization_code_auth_method",
]
extra_kwargs = {
"consumer_secret": {"write_only": True},

View File

@ -6,15 +6,11 @@ from urllib.parse import parse_qsl
from django.utils.crypto import constant_time_compare, get_random_string
from django.utils.translation import gettext as _
from requests.auth import AuthBase, HTTPBasicAuth
from requests.exceptions import RequestException
from requests.models import Response
from structlog.stdlib import get_logger
from authentik.sources.oauth.clients.base import BaseOAuthClient
from authentik.sources.oauth.models import (
AuthorizationCodeAuthMethod,
)
LOGGER = get_logger()
SESSION_KEY_OAUTH_PKCE = "authentik/sources/oauth/pkce"
@ -59,30 +55,6 @@ class OAuth2Client(BaseOAuthClient):
"""Get client secret"""
return self.source.consumer_secret
def get_access_token_args(self, callback: str, code: str) -> dict[str, Any]:
args = {
"redirect_uri": callback,
"code": code,
"grant_type": "authorization_code",
}
if SESSION_KEY_OAUTH_PKCE in self.request.session:
args["code_verifier"] = self.request.session[SESSION_KEY_OAUTH_PKCE]
if (
self.source.source_type.authorization_code_auth_method
== AuthorizationCodeAuthMethod.POST_BODY
):
args["client_id"] = self.get_client_id()
args["client_secret"] = self.get_client_secret()
return args
def get_access_token_auth(self) -> AuthBase | None:
if (
self.source.source_type.authorization_code_auth_method
== AuthorizationCodeAuthMethod.BASIC_AUTH
):
return HTTPBasicAuth(self.get_client_id(), self.get_client_secret())
return None
def get_access_token(self, **request_kwargs) -> dict[str, Any] | None:
"""Fetch access token from callback request."""
callback = self.request.build_absolute_uri(self.callback or self.request.path)
@ -95,6 +67,13 @@ class OAuth2Client(BaseOAuthClient):
error = self.get_request_arg("error", None)
error_desc = self.get_request_arg("error_description", None)
return {"error": error_desc or error or _("No token received.")}
args = {
"redirect_uri": callback,
"code": code,
"grant_type": "authorization_code",
}
if SESSION_KEY_OAUTH_PKCE in self.request.session:
args["code_verifier"] = self.request.session[SESSION_KEY_OAUTH_PKCE]
try:
access_token_url = self.source.source_type.access_token_url or ""
if self.source.source_type.urls_customizable and self.source.access_token_url:
@ -102,8 +81,8 @@ class OAuth2Client(BaseOAuthClient):
response = self.do_request(
"post",
access_token_url,
auth=self.get_access_token_auth(),
data=self.get_access_token_args(callback, code),
auth=(self.get_client_id(), self.get_client_secret()),
data=args,
headers=self._default_headers,
**request_kwargs,
)

View File

@ -1,25 +0,0 @@
# Generated by Django 5.0.14 on 2025-04-11 18:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_oauth", "0009_migrate_useroauthsourceconnection_identifier"),
]
operations = [
migrations.AddField(
model_name="oauthsource",
name="authorization_code_auth_method",
field=models.TextField(
choices=[
("basic_auth", "HTTP Basic Authentication"),
("post_body", "Include the client ID and secret as request parameters"),
],
default="basic_auth",
help_text="How to perform authentication during an authorization_code token request flow",
),
),
]

View File

@ -21,11 +21,6 @@ if TYPE_CHECKING:
from authentik.sources.oauth.types.registry import SourceType
class AuthorizationCodeAuthMethod(models.TextChoices):
BASIC_AUTH = "basic_auth", _("HTTP Basic Authentication")
POST_BODY = "post_body", _("Include the client ID and secret as request parameters")
class OAuthSource(NonCreatableType, Source):
"""Login using a Generic OAuth provider."""
@ -66,14 +61,6 @@ class OAuthSource(NonCreatableType, Source):
oidc_jwks_url = models.TextField(default="", blank=True)
oidc_jwks = models.JSONField(default=dict, blank=True)
authorization_code_auth_method = models.TextField(
choices=AuthorizationCodeAuthMethod.choices,
default=AuthorizationCodeAuthMethod.BASIC_AUTH,
help_text=_(
"How to perform authentication during an authorization_code token request flow"
),
)
@property
def source_type(self) -> type["SourceType"]:
"""Return the provider instance for this source"""

View File

@ -1,69 +0,0 @@
from django.test import RequestFactory, TestCase
from guardian.shortcuts import get_anonymous_user
from authentik.lib.generators import generate_id
from authentik.sources.oauth.clients.oauth2 import OAuth2Client
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod, OAuthSource
from authentik.sources.oauth.types.oidc import OpenIDConnectClient
class TestOAuthClient(TestCase):
"""OAuth Source tests"""
def setUp(self):
self.source = OAuthSource.objects.create(
name="test",
slug="test",
provider_type="openidconnect",
authorization_url="",
profile_url="",
consumer_key=generate_id(),
)
self.factory = RequestFactory()
def test_client_post_body_auth(self):
"""Test login_challenge"""
self.source.provider_type = "apple"
self.source.save()
request = self.factory.get("/")
request.session = {}
request.user = get_anonymous_user()
client = OAuth2Client(self.source, request)
self.assertIsNone(client.get_access_token_auth())
args = client.get_access_token_args("", "")
self.assertIn("client_id", args)
self.assertIn("client_secret", args)
def test_client_basic_auth(self):
"""Test login_challenge"""
self.source.provider_type = "reddit"
self.source.save()
request = self.factory.get("/")
request.session = {}
request.user = get_anonymous_user()
client = OAuth2Client(self.source, request)
self.assertIsNotNone(client.get_access_token_auth())
args = client.get_access_token_args("", "")
self.assertNotIn("client_id", args)
self.assertNotIn("client_secret", args)
def test_client_openid_auth(self):
"""Test login_challenge"""
request = self.factory.get("/")
request.session = {}
request.user = get_anonymous_user()
client = OpenIDConnectClient(self.source, request)
self.assertIsNotNone(client.get_access_token_auth())
args = client.get_access_token_args("", "")
self.assertNotIn("client_id", args)
self.assertNotIn("client_secret", args)
self.source.authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
self.source.save()
client = OpenIDConnectClient(self.source, request)
self.assertIsNone(client.get_access_token_auth())
args = client.get_access_token_args("", "")
self.assertIn("client_id", args)
self.assertIn("client_secret", args)

View File

@ -11,7 +11,7 @@ from structlog.stdlib import get_logger
from authentik.flows.challenge import Challenge, ChallengeResponse
from authentik.sources.oauth.clients.oauth2 import OAuth2Client
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod, OAuthSource
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -105,8 +105,6 @@ class AppleType(SourceType):
access_token_url = "https://appleid.apple.com/auth/token" # nosec
profile_url = ""
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def login_challenge(self, source: OAuthSource, request: HttpRequest) -> Challenge:
"""Pre-general all the things required for the JS SDK"""
apple_client = AppleOAuthClient(

View File

@ -6,7 +6,6 @@ from requests import RequestException
from structlog.stdlib import get_logger
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod
from authentik.sources.oauth.types.oidc import OpenIDConnectOAuth2Callback
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -78,8 +77,6 @@ class AzureADType(SourceType):
)
oidc_jwks_url = "https://login.microsoftonline.com/common/discovery/keys"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
mail = info.get("mail", None) or info.get("otherMails", [None])[0]
# Format group info

View File

@ -2,8 +2,8 @@
from typing import Any
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -16,10 +16,15 @@ class FacebookOAuthRedirect(OAuthRedirect):
}
class FacebookOAuth2Callback(OAuthCallback):
"""Facebook OAuth2 Callback"""
@registry.register()
class FacebookType(SourceType):
"""Facebook Type definition"""
callback_view = FacebookOAuth2Callback
redirect_view = FacebookOAuthRedirect
verbose_name = "Facebook"
name = "facebook"
@ -28,8 +33,6 @@ class FacebookType(SourceType):
access_token_url = "https://graph.facebook.com/v7.0/oauth/access_token" # nosec
profile_url = "https://graph.facebook.com/v7.0/me?fields=id,name,email"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
return {
"username": info.get("name"),

View File

@ -5,7 +5,7 @@ from typing import Any
from requests.exceptions import RequestException
from authentik.sources.oauth.clients.oauth2 import OAuth2Client
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod, OAuthSource
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -63,8 +63,6 @@ class GitHubType(SourceType):
)
oidc_jwks_url = "https://token.actions.githubusercontent.com/.well-known/jwks"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(
self,
source: OAuthSource,

View File

@ -7,8 +7,9 @@ and https://docs.gitlab.com/ee/integration/openid_connect_provider.html
from typing import Any
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod, OAuthSource
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -21,10 +22,15 @@ class GitLabOAuthRedirect(OAuthRedirect):
}
class GitLabOAuthCallback(OAuthCallback):
"""GitLab OAuth2 Callback"""
@registry.register()
class GitLabType(SourceType):
"""GitLab Type definition"""
callback_view = GitLabOAuthCallback
redirect_view = GitLabOAuthRedirect
verbose_name = "GitLab"
name = "gitlab"
@ -37,8 +43,6 @@ class GitLabType(SourceType):
oidc_well_known_url = "https://gitlab.com/.well-known/openid-configuration"
oidc_jwks_url = "https://gitlab.com/oauth/discovery/keys"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
return {
"username": info.get("preferred_username"),

View File

@ -2,8 +2,8 @@
from typing import Any
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -16,10 +16,15 @@ class GoogleOAuthRedirect(OAuthRedirect):
}
class GoogleOAuth2Callback(OAuthCallback):
"""Google OAuth2 Callback"""
@registry.register()
class GoogleType(SourceType):
"""Google Type definition"""
callback_view = GoogleOAuth2Callback
redirect_view = GoogleOAuthRedirect
verbose_name = "Google"
name = "google"
@ -30,8 +35,6 @@ class GoogleType(SourceType):
oidc_well_known_url = "https://accounts.google.com/.well-known/openid-configuration"
oidc_jwks_url = "https://www.googleapis.com/oauth2/v3/certs"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
return {
"email": info.get("email"),

View File

@ -6,7 +6,6 @@ from requests.exceptions import RequestException
from structlog.stdlib import get_logger
from authentik.sources.oauth.clients.oauth2 import OAuth2Client
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -60,8 +59,6 @@ class MailcowType(SourceType):
urls_customizable = True
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
return {
"username": info.get("full_name"),

View File

@ -2,10 +2,8 @@
from typing import Any
from requests.auth import AuthBase, HTTPBasicAuth
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod, OAuthSource
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -20,27 +18,10 @@ class OpenIDConnectOAuthRedirect(OAuthRedirect):
}
class OpenIDConnectClient(UserprofileHeaderAuthClient):
def get_access_token_args(self, callback: str, code: str) -> dict[str, Any]:
args = super().get_access_token_args(callback, code)
if self.source.authorization_code_auth_method == AuthorizationCodeAuthMethod.POST_BODY:
args["client_id"] = self.get_client_id()
args["client_secret"] = self.get_client_secret()
else:
args.pop("client_id", None)
args.pop("client_secret", None)
return args
def get_access_token_auth(self) -> AuthBase | None:
if self.source.authorization_code_auth_method == AuthorizationCodeAuthMethod.BASIC_AUTH:
return HTTPBasicAuth(self.get_client_id(), self.get_client_secret())
return None
class OpenIDConnectOAuth2Callback(OAuthCallback):
"""OpenIDConnect OAuth2 Callback"""
client_class = OpenIDConnectClient
client_class = UserprofileHeaderAuthClient
def get_user_id(self, info: dict[str, str]) -> str:
return info.get("sub", None)

View File

@ -2,6 +2,7 @@
from typing import Any
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.oidc import OpenIDConnectOAuth2Callback
from authentik.sources.oauth.types.registry import SourceType, registry
@ -17,11 +18,20 @@ class OktaOAuthRedirect(OAuthRedirect):
}
class OktaOAuth2Callback(OpenIDConnectOAuth2Callback):
"""Okta OAuth2 Callback"""
# Okta has the same quirk as azure and throws an error if the access token
# is set via query parameter, so we reuse the azure client
# see https://github.com/goauthentik/authentik/issues/1910
client_class = UserprofileHeaderAuthClient
@registry.register()
class OktaType(SourceType):
"""Okta Type definition"""
callback_view = OpenIDConnectOAuth2Callback
callback_view = OktaOAuth2Callback
redirect_view = OktaOAuthRedirect
verbose_name = "Okta"
name = "okta"

View File

@ -3,7 +3,7 @@
from typing import Any
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod, OAuthSource
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -41,8 +41,6 @@ class PatreonType(SourceType):
access_token_url = "https://www.patreon.com/api/oauth2/token" # nosec
profile_url = "https://www.patreon.com/api/oauth2/api/current_user"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
return {
"username": info.get("data", {}).get("attributes", {}).get("vanity"),

View File

@ -2,6 +2,8 @@
from typing import Any
from requests.auth import HTTPBasicAuth
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
@ -18,10 +20,21 @@ class RedditOAuthRedirect(OAuthRedirect):
}
class RedditOAuth2Client(UserprofileHeaderAuthClient):
"""Reddit OAuth2 Client"""
def get_access_token(self, **request_kwargs):
"Fetch access token from callback request."
request_kwargs["auth"] = HTTPBasicAuth(
self.source.consumer_key, self.source.consumer_secret
)
return super().get_access_token(**request_kwargs)
class RedditOAuth2Callback(OAuthCallback):
"""Reddit OAuth2 Callback"""
client_class = UserprofileHeaderAuthClient
client_class = RedditOAuth2Client
@registry.register()

View File

@ -10,7 +10,7 @@ from django.urls.base import reverse
from structlog.stdlib import get_logger
from authentik.flows.challenge import Challenge, RedirectChallenge
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod, OAuthSource
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -41,10 +41,6 @@ class SourceType:
oidc_well_known_url: str | None = None
oidc_jwks_url: str | None = None
authorization_code_auth_method: AuthorizationCodeAuthMethod = (
AuthorizationCodeAuthMethod.BASIC_AUTH
)
def icon_url(self) -> str:
"""Get Icon URL for login"""
return static(f"authentik/sources/{self.name}.svg")

View File

@ -4,7 +4,6 @@ from json import dumps
from typing import Any
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod
from authentik.sources.oauth.types.oidc import OpenIDConnectOAuth2Callback
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.redirect import OAuthRedirect
@ -48,8 +47,6 @@ class TwitchType(SourceType):
access_token_url = "https://id.twitch.tv/oauth2/token" # nosec
profile_url = "https://id.twitch.tv/oauth2/userinfo"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
return {
"username": info.get("preferred_username"),

View File

@ -12,6 +12,23 @@ from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
class TwitterClient(UserprofileHeaderAuthClient):
"""Twitter has similar quirks to Azure AD, and additionally requires Basic auth on
the access token endpoint for some reason."""
# Twitter has the same quirk as azure and throws an error if the access token
# is set via query parameter, so we reuse the azure client
# see https://github.com/goauthentik/authentik/issues/1910
def get_access_token(self, **request_kwargs) -> dict[str, Any] | None:
return super().get_access_token(
auth=(
self.source.consumer_key,
self.source.consumer_secret,
)
)
class TwitterOAuthRedirect(OAuthRedirect):
"""Twitter OAuth2 Redirect"""
@ -27,7 +44,7 @@ class TwitterOAuthRedirect(OAuthRedirect):
class TwitterOAuthCallback(OAuthCallback):
"""Twitter OAuth2 Callback"""
client_class = UserprofileHeaderAuthClient
client_class = TwitterClient
def get_user_id(self, info: dict[str, str]) -> str:
return info.get("data", {}).get("id", "")

File diff suppressed because one or more lines are too long

View File

@ -2,4 +2,4 @@
from authentik.stages.dummy.api import DummyStageViewSet
api_urlpatterns = [("stages/dummy", DummyStageViewSet, "stages-dummy")]
api_urlpatterns = [("stages/dummy", DummyStageViewSet)]

View File

@ -36,7 +36,6 @@ class IdentificationStageSerializer(StageSerializer):
"sources",
"show_source_labels",
"pretend_user_exists",
"enable_remember_me",
]

View File

@ -1,21 +0,0 @@
# Generated by Django 5.1.8 on 2025-04-16 17:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_identification", "0015_identificationstage_captcha_stage"),
]
operations = [
migrations.AddField(
model_name="identificationstage",
name="enable_remember_me",
field=models.BooleanField(
default=False,
help_text="Show the user the 'Remember me on this device' toggle, allowing repeat users to skip straight to entering their password.",
),
),
]

View File

@ -76,13 +76,7 @@ class IdentificationStage(Stage):
"is entered."
),
)
enable_remember_me = models.BooleanField(
default=False,
help_text=_(
"Show the user the 'Remember me on this device' toggle, allowing repeat "
"users to skip straight to entering their password."
),
)
enrollment_flow = models.ForeignKey(
Flow,
on_delete=models.SET_DEFAULT,

View File

@ -85,7 +85,6 @@ class IdentificationChallenge(Challenge):
primary_action = CharField()
sources = LoginSourceSerializer(many=True, required=False)
show_source_labels = BooleanField()
enable_remember_me = BooleanField(required=False, default=True)
component = CharField(default="ak-stage-identification")
@ -236,7 +235,6 @@ class IdentificationStageView(ChallengeStageView):
and current_stage.password_stage.allow_show_password,
"show_source_labels": current_stage.show_source_labels,
"flow_designation": self.executor.flow.designation,
"enable_remember_me": current_stage.enable_remember_me,
}
)
# If the user has been redirected to us whilst trying to access an

View File

@ -4,12 +4,11 @@ from drf_spectacular.utils import extend_schema
from rest_framework.decorators import action
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import CharField
from rest_framework.serializers import CharField, ModelSerializer
from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.core.expression.exceptions import PropertyMappingExpressionException
from authentik.flows.api.stages import StageSerializer
from authentik.flows.challenge import HttpChallengeResponse

View File

@ -15,12 +15,12 @@ from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import BasePermission
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import DateTimeField
from rest_framework.serializers import DateTimeField, ModelSerializer
from rest_framework.views import View
from rest_framework.viewsets import ModelViewSet
from authentik.api.authentication import validate_auth
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import User
from authentik.lib.config import CONFIG
from authentik.recovery.lib import create_admin_group, create_recovery_token

View File

@ -1201,46 +1201,6 @@
}
}
},
{
"type": "object",
"required": [
"model",
"identifiers"
],
"properties": {
"model": {
"const": "authentik_rbac.initialpermissions"
},
"id": {
"type": "string"
},
"state": {
"type": "string",
"enum": [
"absent",
"present",
"created",
"must_created"
],
"default": "present"
},
"conditions": {
"type": "array",
"items": {
"type": "boolean"
}
},
"permissions": {
"$ref": "#/$defs/model_authentik_rbac.initialpermissions_permissions"
},
"attrs": {
"$ref": "#/$defs/model_authentik_rbac.initialpermissions"
},
"identifiers": {
"$ref": "#/$defs/model_authentik_rbac.initialpermissions"
}
}
},
{
"type": "object",
"required": [
@ -4868,7 +4828,6 @@
"authentik_providers_scim.scimprovider",
"authentik_providers_scim.scimmapping",
"authentik_rbac.role",
"authentik_rbac.initialpermissions",
"authentik_sources_kerberos.kerberossource",
"authentik_sources_kerberos.kerberossourcepropertymapping",
"authentik_sources_kerberos.userkerberossourceconnection",
@ -7210,16 +7169,12 @@
"authentik_providers_ssf.view_stream",
"authentik_providers_ssf.view_streamevent",
"authentik_rbac.access_admin_interface",
"authentik_rbac.add_initialpermissions",
"authentik_rbac.add_role",
"authentik_rbac.assign_role_permissions",
"authentik_rbac.change_initialpermissions",
"authentik_rbac.change_role",
"authentik_rbac.delete_initialpermissions",
"authentik_rbac.delete_role",
"authentik_rbac.edit_system_settings",
"authentik_rbac.unassign_role_permissions",
"authentik_rbac.view_initialpermissions",
"authentik_rbac.view_role",
"authentik_rbac.view_system_info",
"authentik_rbac.view_system_settings",
@ -7506,64 +7461,6 @@
}
}
},
"model_authentik_rbac.initialpermissions": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 150,
"minLength": 1,
"title": "Name"
},
"mode": {
"type": "string",
"enum": [
"user",
"role"
],
"title": "Mode"
},
"role": {
"type": "string",
"format": "uuid",
"title": "Role"
},
"permissions": {
"type": "array",
"items": {
"type": "integer"
},
"title": "Permissions"
}
},
"required": []
},
"model_authentik_rbac.initialpermissions_permissions": {
"type": "array",
"items": {
"type": "object",
"required": [
"permission"
],
"properties": {
"permission": {
"type": "string",
"enum": [
"add_initialpermissions",
"change_initialpermissions",
"delete_initialpermissions",
"view_initialpermissions"
]
},
"user": {
"type": "integer"
},
"role": {
"type": "string"
}
}
}
},
"model_authentik_sources_kerberos.kerberossource": {
"type": "object",
"properties": {
@ -8436,15 +8333,6 @@
"type": "object",
"additionalProperties": true,
"title": "Oidc jwks"
},
"authorization_code_auth_method": {
"type": "string",
"enum": [
"basic_auth",
"post_body"
],
"title": "Authorization code auth method",
"description": "How to perform authentication during an authorization_code token request flow"
}
},
"required": []
@ -11893,11 +11781,6 @@
"type": "boolean",
"title": "Pretend user exists",
"description": "When enabled, the stage will succeed and continue even when incorrect user info is entered."
},
"enable_remember_me": {
"type": "boolean",
"title": "Enable remember me",
"description": "Show the user the 'Remember me on this device' toggle, allowing repeat users to skip straight to entering their password."
}
},
"required": []
@ -13910,16 +13793,12 @@
"authentik_providers_ssf.view_stream",
"authentik_providers_ssf.view_streamevent",
"authentik_rbac.access_admin_interface",
"authentik_rbac.add_initialpermissions",
"authentik_rbac.add_role",
"authentik_rbac.assign_role_permissions",
"authentik_rbac.change_initialpermissions",
"authentik_rbac.change_role",
"authentik_rbac.delete_initialpermissions",
"authentik_rbac.delete_role",
"authentik_rbac.edit_system_settings",
"authentik_rbac.unassign_role_permissions",
"authentik_rbac.view_initialpermissions",
"authentik_rbac.view_role",
"authentik_rbac.view_system_info",
"authentik_rbac.view_system_settings",

2
go.mod
View File

@ -27,7 +27,7 @@ require (
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2025024.7
goauthentik.io/api/v3 v3.2025024.4
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.29.0
golang.org/x/sync v0.13.0

4
go.sum
View File

@ -300,8 +300,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
goauthentik.io/api/v3 v3.2025024.7 h1:OOBuyLzv+l5rtvrOYzoDs6Hy9cIfkE5sewRqR5ThSRc=
goauthentik.io/api/v3 v3.2025024.7/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2025024.4 h1:fD4K6YcCTdwtkqKbYBdJk3POHVzw+LDdJdZSbOAKbX4=
goauthentik.io/api/v3 v3.2025024.4/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -9,7 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
"aws-cdk": "^2.1010.0",
"aws-cdk": "^2.1007.0",
"cross-env": "^7.0.3"
},
"engines": {
@ -17,9 +17,9 @@
}
},
"node_modules/aws-cdk": {
"version": "2.1010.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1010.0.tgz",
"integrity": "sha512-kYNzBXVUZoRrTuYxRRA2Loz/Uvay0MqHobg8KPZaWylIbw/meUDgtoATRNt+stOdJ9PHODTjWmlDKI+2/KoF+w==",
"version": "2.1007.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1007.0.tgz",
"integrity": "sha512-/UOYOTGWUm+pP9qxg03tID5tL6euC+pb+xo0RBue+xhnUWwj/Bbsw6DbqbpOPMrNzTUxmM723/uMEQmM6S26dw==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@ -10,7 +10,7 @@
"node": ">=20"
},
"devDependencies": {
"aws-cdk": "^2.1010.0",
"aws-cdk": "^2.1007.0",
"cross-env": "^7.0.3"
}
}

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-17 00:09+0000\n"
"POT-Creation-Date: 2025-04-14 00:11+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -169,7 +169,6 @@ msgid "User's display name."
msgstr ""
#: authentik/core/models.py authentik/providers/oauth2/models.py
#: authentik/rbac/models.py
msgid "User"
msgstr ""
@ -1985,10 +1984,6 @@ msgstr ""
msgid "Roles"
msgstr ""
#: authentik/rbac/models.py
msgid "Initial Permissions"
msgstr ""
#: authentik/rbac/models.py
msgid "System permission"
msgstr ""
@ -2254,14 +2249,6 @@ msgstr ""
msgid "No token received."
msgstr ""
#: authentik/sources/oauth/models.py
msgid "HTTP Basic Authentication"
msgstr ""
#: authentik/sources/oauth/models.py
msgid "Include the client ID and secret as request parameters"
msgstr ""
#: authentik/sources/oauth/models.py
msgid "Request Token URL"
msgstr ""
@ -2299,11 +2286,6 @@ msgstr ""
msgid "Additional Scopes"
msgstr ""
#: authentik/sources/oauth/models.py
msgid ""
"How to perform authentication during an authorization_code token request flow"
msgstr ""
#: authentik/sources/oauth/models.py
msgid "OAuth Source"
msgstr ""
@ -3486,14 +3468,6 @@ msgid ""
"seconds=2)."
msgstr ""
#: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr ""
#: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr ""
#: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages."
msgstr ""

View File

@ -9,9 +9,9 @@
# Kyllian Delaye-Maillot, 2023
# Manuel Viens, 2023
# Mordecai, 2023
# nerdinator <florian.dupret@gmail.com>, 2024
# Charles Leclerc, 2025
# Tina, 2025
# nerdinator <florian.dupret@gmail.com>, 2025
# Marc Schmitt, 2025
#
#, fuzzy
@ -19,7 +19,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-15 00:11+0000\n"
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Marc Schmitt, 2025\n"
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
@ -194,7 +194,6 @@ msgid "User's display name."
msgstr "Nom d'affichage de l'utilisateur"
#: authentik/core/models.py authentik/providers/oauth2/models.py
#: authentik/rbac/models.py
msgid "User"
msgstr "Utilisateur"
@ -383,18 +382,6 @@ msgstr "Mappage de propriété"
msgid "Property Mappings"
msgstr "Mappages de propriété"
#: authentik/core/models.py
msgid "session data"
msgstr "Données de session"
#: authentik/core/models.py
msgid "Session"
msgstr "Session"
#: authentik/core/models.py
msgid "Sessions"
msgstr "Sessions"
#: authentik/core/models.py
msgid "Authenticated Session"
msgstr "Session Authentifiée"
@ -2210,10 +2197,6 @@ msgstr "Rôle"
msgid "Roles"
msgstr "Rôles"
#: authentik/rbac/models.py
msgid "Initial Permissions"
msgstr "Permissions initiales"
#: authentik/rbac/models.py
msgid "System permission"
msgstr "Permission système"
@ -2464,9 +2447,6 @@ msgid ""
"attribute. This allows nested group resolution on systems like FreeIPA and "
"Active Directory"
msgstr ""
"Recherche de l'appartenance aux groupes basée sur un attribut utilisateur "
"plutôt que sur un attribut de groupe. Cela permet la résolution des groupes "
"imbriqués sur des systèmes tels que FreeIPA et Active Directory."
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
@ -2484,22 +2464,6 @@ msgstr "Mappage de propriété source LDAP"
msgid "LDAP Source Property Mappings"
msgstr "Mappages de propriété source LDAP"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr "Connexion de l'utilisateur à la source LDAP"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections"
msgstr "Connexions de l'utilisateur à la source LDAP"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection"
msgstr "Connexion du groupe à la source LDAP"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections"
msgstr "Connexions du groupe à la source LDAP"
#: authentik/sources/ldap/signals.py
msgid "Password does not match Active Directory Complexity."
msgstr "Le mot de passe ne correspond pas à la complexité d'Active Directory."
@ -3853,17 +3817,6 @@ msgstr ""
"Les évènements seront supprimés après cet interval. (Format : "
"weeks=3;days=2;hours=3,seconds=2)"
#: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr ""
"La réputation ne peut pas descendre en dessous de cette valeur. Zéro ou "
"négatif."
#: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr ""
"La réputation ne peut pas monter au dessus de cette valeur. Zéro ou positif."
#: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages."
msgstr ""

Binary file not shown.

Binary file not shown.

View File

@ -15,7 +15,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-15 00:11+0000\n"
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: deluxghost, 2025\n"
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
@ -179,7 +179,6 @@ msgid "User's display name."
msgstr "用户的显示名称。"
#: authentik/core/models.py authentik/providers/oauth2/models.py
#: authentik/rbac/models.py
msgid "User"
msgstr "用户"
@ -346,18 +345,6 @@ msgstr "属性映射"
msgid "Property Mappings"
msgstr "属性映射"
#: authentik/core/models.py
msgid "session data"
msgstr "会话数据"
#: authentik/core/models.py
msgid "Session"
msgstr "会话"
#: authentik/core/models.py
msgid "Sessions"
msgstr "会话"
#: authentik/core/models.py
msgid "Authenticated Session"
msgstr "已认证会话"
@ -1256,11 +1243,11 @@ msgstr "正在等待身份验证…"
msgid ""
"You're already authenticating in another tab. This page will refresh once "
"authentication is completed."
msgstr "您正在另一个标签页中验证身份。身份验证完成后,此页面会刷新。"
msgstr ""
#: authentik/policies/templates/policies/buffer.html
msgid "Authenticate in this tab"
msgstr "在此标签页中验证身份"
msgstr ""
#: authentik/policies/templates/policies/denied.html
msgid "Permission denied"
@ -2012,10 +1999,6 @@ msgstr "角色"
msgid "Roles"
msgstr "角色"
#: authentik/rbac/models.py
msgid "Initial Permissions"
msgstr "初始权限"
#: authentik/rbac/models.py
msgid "System permission"
msgstr "系统权限"
@ -2244,7 +2227,7 @@ msgid ""
"Lookup group membership based on a user attribute instead of a group "
"attribute. This allows nested group resolution on systems like FreeIPA and "
"Active Directory"
msgstr "基于用户属性而非组属性查询组成员身份。这允许在 FreeIPA 或 Active Directory 等系统上支持嵌套组决策"
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
@ -2262,22 +2245,6 @@ msgstr "LDAP 源属性映射"
msgid "LDAP Source Property Mappings"
msgstr "LDAP 源属性映射"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr "用户 LDAP 源连接"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections"
msgstr "用户 LDAP 源连接"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection"
msgstr "组 LDAP 源连接"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections"
msgstr "组 LDAP 源连接"
#: authentik/sources/ldap/signals.py
msgid "Password does not match Active Directory Complexity."
msgstr "密码与 Active Directory 复杂度不匹配。"
@ -3538,14 +3505,6 @@ msgid ""
"weeks=3;days=2;hours=3,seconds=2)."
msgstr "事件会在多久后被删除。格式weeks=3;days=2;hours=3,seconds=2。"
#: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr "信誉无法降低到此值以下。可为零或负数。"
#: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr "信誉无法提高到此值以上。可为零或正数。"
#: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages."
msgstr "此选项配置流程执行器页面上的页脚链接。"

View File

@ -14,7 +14,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-15 00:11+0000\n"
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: deluxghost, 2025\n"
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
@ -178,7 +178,6 @@ msgid "User's display name."
msgstr "用户的显示名称。"
#: authentik/core/models.py authentik/providers/oauth2/models.py
#: authentik/rbac/models.py
msgid "User"
msgstr "用户"
@ -345,18 +344,6 @@ msgstr "属性映射"
msgid "Property Mappings"
msgstr "属性映射"
#: authentik/core/models.py
msgid "session data"
msgstr "会话数据"
#: authentik/core/models.py
msgid "Session"
msgstr "会话"
#: authentik/core/models.py
msgid "Sessions"
msgstr "会话"
#: authentik/core/models.py
msgid "Authenticated Session"
msgstr "已认证会话"
@ -2011,10 +1998,6 @@ msgstr "角色"
msgid "Roles"
msgstr "角色"
#: authentik/rbac/models.py
msgid "Initial Permissions"
msgstr "初始权限"
#: authentik/rbac/models.py
msgid "System permission"
msgstr "系统权限"
@ -2243,7 +2226,7 @@ msgid ""
"Lookup group membership based on a user attribute instead of a group "
"attribute. This allows nested group resolution on systems like FreeIPA and "
"Active Directory"
msgstr "基于用户属性而非组属性查询组成员身份。这允许在 FreeIPA 或 Active Directory 等系统上支持嵌套组决策"
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
@ -2261,22 +2244,6 @@ msgstr "LDAP 源属性映射"
msgid "LDAP Source Property Mappings"
msgstr "LDAP 源属性映射"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr "用户 LDAP 源连接"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections"
msgstr "用户 LDAP 源连接"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection"
msgstr "组 LDAP 源连接"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections"
msgstr "组 LDAP 源连接"
#: authentik/sources/ldap/signals.py
msgid "Password does not match Active Directory Complexity."
msgstr "密码与 Active Directory 复杂度不匹配。"
@ -3537,14 +3504,6 @@ msgid ""
"weeks=3;days=2;hours=3,seconds=2)."
msgstr "事件会在多久后被删除。格式weeks=3;days=2;hours=3,seconds=2。"
#: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr "信誉无法降低到此值以下。可为零或负数。"
#: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr "信誉无法提高到此值以上。可为零或正数。"
#: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages."
msgstr "此选项配置流程执行器页面上的页脚链接。"

View File

@ -47,7 +47,7 @@ dependencies = [
"opencontainers",
"packaging",
"paramiko",
"psycopg[c, pool]",
"psycopg[c]",
"pydantic",
"pydantic-scim",
"pyjwt",

View File

@ -24209,270 +24209,6 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/rbac/initial_permissions/:
get:
operationId: rbac_initial_permissions_list
description: InitialPermissions viewset
parameters:
- in: query
name: name
schema:
type: string
- name: ordering
required: false
in: query
description: Which field to use when ordering the results.
schema:
type: string
- name: page
required: false
in: query
description: A page number within the paginated result set.
schema:
type: integer
- name: page_size
required: false
in: query
description: Number of results to return per page.
schema:
type: integer
- name: search
required: false
in: query
description: A search term.
schema:
type: string
tags:
- rbac
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedInitialPermissionsList'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
post:
operationId: rbac_initial_permissions_create
description: InitialPermissions viewset
tags:
- rbac
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InitialPermissionsRequest'
required: true
security:
- authentik: []
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/InitialPermissions'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/rbac/initial_permissions/{id}/:
get:
operationId: rbac_initial_permissions_retrieve
description: InitialPermissions viewset
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Initial Permissions.
required: true
tags:
- rbac
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/InitialPermissions'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
put:
operationId: rbac_initial_permissions_update
description: InitialPermissions viewset
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Initial Permissions.
required: true
tags:
- rbac
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InitialPermissionsRequest'
required: true
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/InitialPermissions'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
patch:
operationId: rbac_initial_permissions_partial_update
description: InitialPermissions viewset
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Initial Permissions.
required: true
tags:
- rbac
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PatchedInitialPermissionsRequest'
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/InitialPermissions'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
delete:
operationId: rbac_initial_permissions_destroy
description: InitialPermissions viewset
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Initial Permissions.
required: true
tags:
- rbac
security:
- authentik: []
responses:
'204':
description: No response body
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/rbac/initial_permissions/{id}/used_by/:
get:
operationId: rbac_initial_permissions_used_by_list
description: Get a list of all objects that use this object
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this Initial Permissions.
required: true
tags:
- rbac
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/UsedBy'
description: ''
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/rbac/permissions/:
get:
operationId: rbac_permissions_list
@ -24634,7 +24370,6 @@ paths:
- authentik_providers_scim.scimmapping
- authentik_providers_scim.scimprovider
- authentik_providers_ssf.ssfprovider
- authentik_rbac.initialpermissions
- authentik_rbac.role
- authentik_sources_kerberos.groupkerberossourceconnection
- authentik_sources_kerberos.kerberossource
@ -24881,7 +24616,6 @@ paths:
- authentik_providers_scim.scimmapping
- authentik_providers_scim.scimprovider
- authentik_providers_ssf.ssfprovider
- authentik_rbac.initialpermissions
- authentik_rbac.role
- authentik_sources_kerberos.groupkerberossourceconnection
- authentik_sources_kerberos.kerberossource
@ -42110,11 +41844,6 @@ components:
format: uuid
required:
- name
AuthorizationCodeAuthMethodEnum:
enum:
- basic_auth
- post_body
type: string
AutoSubmitChallengeResponseRequest:
type: object
description: Pseudo class for autosubmit response
@ -46049,9 +45778,6 @@ components:
$ref: '#/components/schemas/LoginSource'
show_source_labels:
type: boolean
enable_remember_me:
type: boolean
default: true
required:
- flow_designation
- password_fields
@ -46164,10 +45890,6 @@ components:
type: boolean
description: When enabled, the stage will succeed and continue even when
incorrect user info is entered.
enable_remember_me:
type: boolean
description: Show the user the 'Remember me on this device' toggle, allowing
repeat users to skip straight to entering their password.
required:
- component
- meta_model_name
@ -46242,10 +45964,6 @@ components:
type: boolean
description: When enabled, the stage will succeed and continue even when
incorrect user info is entered.
enable_remember_me:
type: boolean
description: Show the user the 'Remember me on this device' toggle, allowing
repeat users to skip straight to entering their password.
required:
- name
ImpersonationRequest:
@ -46256,63 +45974,6 @@ components:
minLength: 1
required:
- reason
InitialPermissions:
type: object
description: InitialPermissions serializer
properties:
pk:
type: integer
readOnly: true
title: ID
name:
type: string
maxLength: 150
mode:
$ref: '#/components/schemas/InitialPermissionsModeEnum'
role:
type: string
format: uuid
permissions:
type: array
items:
type: integer
permissions_obj:
type: array
items:
$ref: '#/components/schemas/Permission'
readOnly: true
required:
- mode
- name
- permissions_obj
- pk
- role
InitialPermissionsModeEnum:
enum:
- user
- role
type: string
InitialPermissionsRequest:
type: object
description: InitialPermissions serializer
properties:
name:
type: string
minLength: 1
maxLength: 150
mode:
$ref: '#/components/schemas/InitialPermissionsModeEnum'
role:
type: string
format: uuid
permissions:
type: array
items:
type: integer
required:
- mode
- name
- role
InstallID:
type: object
properties:
@ -48001,7 +47662,6 @@ components:
- authentik_providers_scim.scimprovider
- authentik_providers_scim.scimmapping
- authentik_rbac.role
- authentik_rbac.initialpermissions
- authentik_sources_kerberos.kerberossource
- authentik_sources_kerberos.kerberossourcepropertymapping
- authentik_sources_kerberos.userkerberossourceconnection
@ -48758,11 +48418,6 @@ components:
oidc_jwks_url:
type: string
oidc_jwks: {}
authorization_code_auth_method:
allOf:
- $ref: '#/components/schemas/AuthorizationCodeAuthMethodEnum'
description: How to perform authentication during an authorization_code
token request flow
required:
- callback_url
- component
@ -48932,11 +48587,6 @@ components:
oidc_jwks_url:
type: string
oidc_jwks: {}
authorization_code_auth_method:
allOf:
- $ref: '#/components/schemas/AuthorizationCodeAuthMethodEnum'
description: How to perform authentication during an authorization_code
token request flow
required:
- consumer_key
- consumer_secret
@ -49740,18 +49390,6 @@ components:
required:
- pagination
- results
PaginatedInitialPermissionsList:
type: object
properties:
pagination:
$ref: '#/components/schemas/Pagination'
results:
type: array
items:
$ref: '#/components/schemas/InitialPermissions'
required:
- pagination
- results
PaginatedInvitationList:
type: object
properties:
@ -52301,27 +51939,6 @@ components:
type: boolean
description: When enabled, the stage will succeed and continue even when
incorrect user info is entered.
enable_remember_me:
type: boolean
description: Show the user the 'Remember me on this device' toggle, allowing
repeat users to skip straight to entering their password.
PatchedInitialPermissionsRequest:
type: object
description: InitialPermissions serializer
properties:
name:
type: string
minLength: 1
maxLength: 150
mode:
$ref: '#/components/schemas/InitialPermissionsModeEnum'
role:
type: string
format: uuid
permissions:
type: array
items:
type: integer
PatchedInvitationRequest:
type: object
description: Invitation Serializer
@ -53039,11 +52656,6 @@ components:
oidc_jwks_url:
type: string
oidc_jwks: {}
authorization_code_auth_method:
allOf:
- $ref: '#/components/schemas/AuthorizationCodeAuthMethodEnum'
description: How to perform authentication during an authorization_code
token request flow
PatchedOutpostRequest:
type: object
description: Outpost Serializer
@ -54492,21 +54104,6 @@ components:
type: string
required:
- id
PermissionRequest:
type: object
description: Global permission
properties:
name:
type: string
minLength: 1
maxLength: 255
codename:
type: string
minLength: 1
maxLength: 100
required:
- codename
- name
PlexAuthenticationChallenge:
type: object
description: Challenge shown to the user in identification stage

79
uv.lock generated
View File

@ -210,7 +210,7 @@ dependencies = [
{ name = "opencontainers" },
{ name = "packaging" },
{ name = "paramiko" },
{ name = "psycopg", extra = ["c", "pool"] },
{ name = "psycopg", extra = ["c"] },
{ name = "pydantic" },
{ name = "pydantic-scim" },
{ name = "pyjwt" },
@ -308,7 +308,7 @@ requires-dist = [
{ name = "opencontainers", git = "https://github.com/BeryJu/oci-python?rev=c791b19056769cd67957322806809ab70f5bead8" },
{ name = "packaging" },
{ name = "paramiko" },
{ name = "psycopg", extras = ["c", "pool"] },
{ name = "psycopg", extras = ["c"] },
{ name = "pydantic" },
{ name = "pydantic-scim" },
{ name = "pyjwt" },
@ -558,30 +558,30 @@ wheels = [
[[package]]
name = "boto3"
version = "1.37.34"
version = "1.37.33"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "botocore" },
{ name = "jmespath" },
{ name = "s3transfer" },
]
sdist = { url = "https://files.pythonhosted.org/packages/39/5d/6b1ca20ba4da350799509a69f2d295ae11d5ec08a98e82f74b5708a8180c/boto3-1.37.34.tar.gz", hash = "sha256:94ca07328474db3fa605eb99b011512caa73f7161740d365a1f00cfebfb6dd90", size = 111701 }
sdist = { url = "https://files.pythonhosted.org/packages/89/74/001695948752bc1b5357677eb2635e059f464b22c3eb5f9411ec4e8c48a3/boto3-1.37.33.tar.gz", hash = "sha256:4390317a1578af73f1514651bd180ba25802dcbe0a23deafa13851d54d3c3203", size = 111676 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/cb/2e/ad43d1e87d46d11dcf4104f97b9a7f6beb38a52a0e752edfadf3eb8b6e38/boto3-1.37.34-py3-none-any.whl", hash = "sha256:586bfa72a00601c04067f9adcbb08ecaf63b05b7d731103f33cb2ce0d6950b1b", size = 139920 },
{ url = "https://files.pythonhosted.org/packages/1f/e7/e660fac728570c926c4a12fa1ae8bffde7300d4817942bbd7871a6ebd4e2/boto3-1.37.33-py3-none-any.whl", hash = "sha256:7b1b1bc69762975824e5a5d570880abebf634f7594f88b3dc175e8800f35be1a", size = 139920 },
]
[[package]]
name = "botocore"
version = "1.37.34"
version = "1.37.33"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jmespath" },
{ name = "python-dateutil" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ca/60/9ec251a0e2d3994f3eac8bd9741576757c3aad189abbdec8fab6011f5a1a/botocore-1.37.34.tar.gz", hash = "sha256:2909b6dbf9c90347c71a6fa0364acee522d6a7664f13d6f7996c9dd1b1f46fac", size = 13817141 }
sdist = { url = "https://files.pythonhosted.org/packages/f4/1d/0c539ae261d2f8fe8b47c358b369ec58645bf0ea96b78825365e48675b67/botocore-1.37.33.tar.gz", hash = "sha256:09b213b0d0500040f85c7daee912ea767c724e43ed61909e624c803ff6925222", size = 13817305 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e8/51/19fff717cc5000708c4ce3d081bb0e63ca117c6823975b33101d52fdd9f5/botocore-1.37.34-py3-none-any.whl", hash = "sha256:bd9af0db1097befd2028ba8525e32cacc04f26ccb9dbd5d48d6ecd05bc16c27a", size = 13483679 },
{ url = "https://files.pythonhosted.org/packages/21/93/425fb149fb969f07804f60cb1931d8aab197eb5f45dce821cbbbffc49207/botocore-1.37.33-py3-none-any.whl", hash = "sha256:4a167dfecae51e9140de24067de1c339acde5ade3dad524a4600ac2c72055e23", size = 13482312 },
]
[[package]]
@ -1370,16 +1370,16 @@ wheels = [
[[package]]
name = "google-auth"
version = "2.39.0"
version = "2.38.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "cachetools" },
{ name = "pyasn1-modules" },
{ name = "rsa" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cb/8e/8f45c9a32f73e786e954b8f9761c61422955d23c45d1e8c347f9b4b59e8e/google_auth-2.39.0.tar.gz", hash = "sha256:73222d43cdc35a3aeacbfdcaf73142a97839f10de930550d89ebfe1d0a00cde7", size = 274834 }
sdist = { url = "https://files.pythonhosted.org/packages/c6/eb/d504ba1daf190af6b204a9d4714d457462b486043744901a6eeea711f913/google_auth-2.38.0.tar.gz", hash = "sha256:8285113607d3b80a3f1543b75962447ba8a09fe85783432a784fdeef6ac094c4", size = 270866 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ce/12/ad37a1ef86006d0a0117fc06a4a00bd461c775356b534b425f00dde208ea/google_auth-2.39.0-py2.py3-none-any.whl", hash = "sha256:0150b6711e97fb9f52fe599f55648950cc4540015565d8fbb31be2ad6e1548a2", size = 212319 },
{ url = "https://files.pythonhosted.org/packages/9d/47/603554949a37bca5b7f894d51896a9c534b9eab808e2520a748e081669d0/google_auth-2.38.0-py2.py3-none-any.whl", hash = "sha256:e7dae6694313f434a2727bf2906f27ad259bae090d7aa896590d86feec3d9d4a", size = 210770 },
]
[[package]]
@ -2009,7 +2009,7 @@ wheels = [
[[package]]
name = "msgraph-sdk"
version = "1.28.0"
version = "1.27.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "azure-identity" },
@ -2019,9 +2019,9 @@ dependencies = [
{ name = "microsoft-kiota-serialization-text" },
{ name = "msgraph-core" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b9/41/40bb3c630ca026182aefd79a9862ef4a1917b1161c83690c858d714788f5/msgraph_sdk-1.28.0.tar.gz", hash = "sha256:b2d64b7bd711ad285fc2c090dd524853a026848732e1c83874fe34561805350d", size = 6121069 }
sdist = { url = "https://files.pythonhosted.org/packages/a5/5d/678e6e95151ebc012a8e00164ea85c3c638c3e9d42baf76bb0efbde4fce2/msgraph_sdk-1.27.0.tar.gz", hash = "sha256:92c3d168a2842eec631c772c2825864aa53ca54ea417935a6a9d2d1e50ede6f5", size = 6121021 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a8/58/d8e9593ea81779d503831b5b06c8d9881d5affefe3df99ca20112c969e6f/msgraph_sdk-1.28.0-py3-none-any.whl", hash = "sha256:bd33b186371dfa8ed6375dfda92eef0931485633e69b06c001ce3c2fd3658f18", size = 25091309 },
{ url = "https://files.pythonhosted.org/packages/0b/ec/a2a7bda2e5828b16cc561aee996b2ee28724e5921bf571ae1846bafde805/msgraph_sdk-1.27.0-py3-none-any.whl", hash = "sha256:d5e91ef46fc7b95ae8e003cc3a27793075f4efeabd65611ccb9dad6976f76e99", size = 25091359 },
]
[[package]]
@ -2084,42 +2084,42 @@ source = { git = "https://github.com/BeryJu/oci-python?rev=c791b19056769cd679573
[[package]]
name = "opentelemetry-api"
version = "1.32.1"
version = "1.32.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "deprecated" },
{ name = "importlib-metadata" },
]
sdist = { url = "https://files.pythonhosted.org/packages/42/40/2359245cd33641c2736a0136a50813352d72f3fc209de28fb226950db4a1/opentelemetry_api-1.32.1.tar.gz", hash = "sha256:a5be71591694a4d9195caf6776b055aa702e964d961051a0715d05f8632c32fb", size = 64138 }
sdist = { url = "https://files.pythonhosted.org/packages/7b/34/e701d77900123af17a11dbaf0c9f527fa7ef94b8f02b2c55bed94477890a/opentelemetry_api-1.32.0.tar.gz", hash = "sha256:2623280c916f9b19cad0aa4280cb171265f19fd2909b0d47e4f06f7c83b02cb5", size = 64134 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/12/f2/89ea3361a305466bc6460a532188830351220b5f0851a5fa133155c16eca/opentelemetry_api-1.32.1-py3-none-any.whl", hash = "sha256:bbd19f14ab9f15f0e85e43e6a958aa4cb1f36870ee62b7fd205783a112012724", size = 65287 },
{ url = "https://files.pythonhosted.org/packages/fe/e8/d05fd19c1c7e7e230ab44c366791179fd64c843bc587c257a56e853893c5/opentelemetry_api-1.32.0-py3-none-any.whl", hash = "sha256:15df743c765078611f376037b0d9111ec5c1febf2ec9440cdd919370faa1ce55", size = 65285 },
]
[[package]]
name = "opentelemetry-sdk"
version = "1.32.1"
version = "1.32.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "opentelemetry-api" },
{ name = "opentelemetry-semantic-conventions" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/a3/65/2069caef9257fae234ca0040d945c741aa7afbd83a7298ee70fc0bc6b6f4/opentelemetry_sdk-1.32.1.tar.gz", hash = "sha256:8ef373d490961848f525255a42b193430a0637e064dd132fd2a014d94792a092", size = 161044 }
sdist = { url = "https://files.pythonhosted.org/packages/e8/0c/842aed73035cab0302ec70057f3180f4f023974d74bd9764ef3046f358fb/opentelemetry_sdk-1.32.0.tar.gz", hash = "sha256:5ff07fb371d1ab1189fa7047702e2e888b5403c5efcbb18083cae0d5aa5f58d2", size = 161043 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/dc/00/d3976cdcb98027aaf16f1e980e54935eb820872792f0eaedd4fd7abb5964/opentelemetry_sdk-1.32.1-py3-none-any.whl", hash = "sha256:bba37b70a08038613247bc42beee5a81b0ddca422c7d7f1b097b32bf1c7e2f17", size = 118989 },
{ url = "https://files.pythonhosted.org/packages/ee/6a/b8cb562234bd94bcf12ad3058ef7f31319b94a8df65130ce9cc2ff3c8d55/opentelemetry_sdk-1.32.0-py3-none-any.whl", hash = "sha256:ed252d035c22a15536c1f603ca089298daab60850fc2f5ddfa95d95cc1c043ea", size = 118990 },
]
[[package]]
name = "opentelemetry-semantic-conventions"
version = "0.53b1"
version = "0.53b0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "deprecated" },
{ name = "opentelemetry-api" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5e/b6/3c56e22e9b51bcb89edab30d54830958f049760bbd9ab0a759cece7bca88/opentelemetry_semantic_conventions-0.53b1.tar.gz", hash = "sha256:4c5a6fede9de61211b2e9fc1e02e8acacce882204cd770177342b6a3be682992", size = 114350 }
sdist = { url = "https://files.pythonhosted.org/packages/c2/c4/213d23239df175b420b74c6e25899c482701e6614822dc51f8c20dae7e2d/opentelemetry_semantic_conventions-0.53b0.tar.gz", hash = "sha256:05b7908e1da62d72f9bf717ed25c72f566fe005a2dd260c61b11e025f2552cf6", size = 114343 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/27/6b/a8fb94760ef8da5ec283e488eb43235eac3ae7514385a51b6accf881e671/opentelemetry_semantic_conventions-0.53b1-py3-none-any.whl", hash = "sha256:21df3ed13f035f8f3ea42d07cbebae37020367a53b47f1ebee3b10a381a00208", size = 188443 },
{ url = "https://files.pythonhosted.org/packages/7c/23/0bef11f394f828f910f32567d057f097dbaba23edf33114018a380a0d0bf/opentelemetry_semantic_conventions-0.53b0-py3-none-any.whl", hash = "sha256:561da89f766ab51615c0e72b12329e0a1bc16945dbd62c8646ffc74e36a1edff", size = 188441 },
]
[[package]]
@ -2243,14 +2243,14 @@ wheels = [
[[package]]
name = "prompt-toolkit"
version = "3.0.51"
version = "3.0.50"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "wcwidth" },
]
sdist = { url = "https://files.pythonhosted.org/packages/bb/6e/9d084c929dfe9e3bfe0c6a47e31f78a25c54627d64a66e884a8bf5474f1c/prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed", size = 428940 }
sdist = { url = "https://files.pythonhosted.org/packages/a1/e1/bd15cb8ffdcfeeb2bdc215de3c3cffca11408d829e4b8416dcfe71ba8854/prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab", size = 429087 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ce/4f/5249960887b1fbe561d9ff265496d170b55a735b76724f10ef19f9e40716/prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", size = 387810 },
{ url = "https://files.pythonhosted.org/packages/e4/ea/d836f008d33151c7a1f62caf3d8dd782e4d15f6a43897f64480c2b8de2ad/prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198", size = 387816 },
]
[[package]]
@ -2321,9 +2321,6 @@ wheels = [
c = [
{ name = "psycopg-c", marker = "implementation_name != 'pypy'" },
]
pool = [
{ name = "psycopg-pool" },
]
[[package]]
name = "psycopg-c"
@ -2331,18 +2328,6 @@ version = "3.2.6"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/2f/f1/367a2429af2b97f6a46dc116206cd3b1cf668fca7ff3c22b979ea0686427/psycopg_c-3.2.6.tar.gz", hash = "sha256:b5fd4ce70f82766a122ca5076a36c4d5818eaa9df9bf76870bc83a064ffaed3a", size = 609304 }
[[package]]
name = "psycopg-pool"
version = "3.2.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/cf/13/1e7850bb2c69a63267c3dbf37387d3f71a00fd0e2fa55c5db14d64ba1af4/psycopg_pool-3.2.6.tar.gz", hash = "sha256:0f92a7817719517212fbfe2fd58b8c35c1850cdd2a80d36b581ba2085d9148e5", size = 29770 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/47/fd/4feb52a55c1a4bd748f2acaed1903ab54a723c47f6d0242780f4d97104d4/psycopg_pool-3.2.6-py3-none-any.whl", hash = "sha256:5887318a9f6af906d041a0b1dc1c60f8f0dda8340c2572b74e10907b51ed5da7", size = 38252 },
]
[[package]]
name = "publication"
version = "0.0.3"
@ -2759,14 +2744,14 @@ wheels = [
[[package]]
name = "rsa"
version = "4.9.1"
version = "4.9"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pyasn1" },
]
sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034 }
sdist = { url = "https://files.pythonhosted.org/packages/aa/65/7d973b89c4d2351d7fb232c2e452547ddfa243e93131e7cfa766da627b52/rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21", size = 29711 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696 },
{ url = "https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7", size = 34315 },
]
[[package]]
@ -2837,15 +2822,15 @@ wheels = [
[[package]]
name = "sentry-sdk"
version = "2.26.1"
version = "2.25.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/85/26/099631caa51abffb1fd9e08c2138bc6681d3f288a5936c2fc4e054729611/sentry_sdk-2.26.1.tar.gz", hash = "sha256:759e019c41551a21519a95e6cef6d91fb4af1054761923dadaee2e6eca9c02c7", size = 323099 }
sdist = { url = "https://files.pythonhosted.org/packages/85/2f/a0f732270cc7c1834f5ec45539aec87c360d5483a8bd788217a9102ccfbd/sentry_sdk-2.25.1.tar.gz", hash = "sha256:f9041b7054a7cf12d41eadabe6458ce7c6d6eea7a97cfe1b760b6692e9562cf0", size = 322190 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/23/32/0a30b4fafdb3d26d133f99bb566aaa6000004ee7f2c4b72aafea9237ab7e/sentry_sdk-2.26.1-py2.py3-none-any.whl", hash = "sha256:e99390e3f217d13ddcbaeaed08789f1ca614d663b345b9da42e35ad6b60d696a", size = 340558 },
{ url = "https://files.pythonhosted.org/packages/96/b6/84049ab0967affbc7cc7590d86ae0170c1b494edb69df8786707100420e5/sentry_sdk-2.25.1-py2.py3-none-any.whl", hash = "sha256:60b016d0772789454dc55a284a6a44212044d4a16d9f8448725effee97aaf7f6", size = 339851 },
]
[[package]]

View File

@ -16,16 +16,16 @@ three contexts in which to run.
The three contexts corresponds to objects in the API's `model` section, so let's use those names.
- The root `Config`. The root configuration object of the server, containing mostly caching and
error reporting information. This is misleading, however; the `Config` object contains some user
information, specifically a list of permissions the current user (or "no user") has.
- The root `CurrentTenant`. This describes the `Brand` information UIs should use, such as themes,
logos, favicon, and specific default flows for logging in, logging out, and recovering a user
password.
- The current `SessionUser`, the person logged in: username, display name, and various states.
(Note: the authentik server permits administrators to "impersonate" any other user in order to
debug their authentikation experience. If impersonation is active, the `user` field reflects that
user, but it also includes a field, `original`, with the administrator's information.)
- The root `Config`. The root configuration object of the server, containing mostly caching and
error reporting information. This is misleading, however; the `Config` object contains some user
information, specifically a list of permissions the current user (or "no user") has.
- The root `CurrentTenant`. This describes the `Brand` information UIs should use, such as themes,
logos, favicon, and specific default flows for logging in, logging out, and recovering a user
password.
- The current `SessionUser`, the person logged in: username, display name, and various states.
(Note: the authentik server permits administrators to "impersonate" any other user in order to
debug their authentikation experience. If impersonation is active, the `user` field reflects that
user, but it also includes a field, `original`, with the administrator's information.)
(There is a fourth context object, Version, but its use is limited to displaying version information
and checking for upgrades. Just be aware that you will see it, but you will probably never interact
@ -36,55 +36,55 @@ insides are provided by third-party libraries (Patternfly and Rapidoc, respectiv
three are actual applications. The descriptions below are wholly from the view of the user's
experience:
- `Flow`: From a given URL, displays a form that requests information from the user to accomplish a
task. Some tasks require the user to be logged in, but many (such as logging in itself!)
obviously do not.
- `User`: Provides the user with access to the applications they can access, plus a few user
settings.
- `Admin`: Provides someone with super-user permissions access to the administrative functions of
the authentik server.
- `Flow`: From a given URL, displays a form that requests information from the user to accomplish a
task. Some tasks require the user to be logged in, but many (such as logging in itself!)
obviously do not.
- `User`: Provides the user with access to the applications they can access, plus a few user
settings.
- `Admin`: Provides someone with super-user permissions access to the administrative functions of
the authentik server.
**Mental Model**
- Upon initialization, _every_ authentik UI application fetches `Config` and `CurrentTenant`. `User`
and `Admin` will also attempt to load the `SessionUser`; if there is none, the user is kicked out
to the `Flow` for logging into authentik itself.
- `Config`, `CurrentTenant`, and `SessionUser`, are provided by the `@goauthentik/api` application,
not by the codebase under `./web`. (Where you are now).
- `Flow`, `User`, and `Admin` are all called `Interfaces` and are found in
`./web/src/flow/FlowInterface`, `./web/src/user/UserInterface`, `./web/src/admin/AdminInterface`,
respectively.
- Upon initialization, _every_ authentik UI application fetches `Config` and `CurrentTenant`. `User`
and `Admin` will also attempt to load the `SessionUser`; if there is none, the user is kicked out
to the `Flow` for logging into authentik itself.
- `Config`, `CurrentTenant`, and `SessionUser`, are provided by the `@goauthentik/api` application,
not by the codebase under `./web`. (Where you are now).
- `Flow`, `User`, and `Admin` are all called `Interfaces` and are found in
`./web/src/flow/FlowInterface`, `./web/src/user/UserInterface`, `./web/src/admin/AdminInterface`,
respectively.
Inside each of these you will find, in a hierarchal order:
- The context layer described above
- A theme managing layer
- The orchestration layer:
- web socket handler for server-generated events
- The router
- Individual routes for each vertical slice and its relationship to other objects:
- The context layer described above
- A theme managing layer
- The orchestration layer:
- web socket handler for server-generated events
- The router
- Individual routes for each vertical slice and its relationship to other objects:
Each slice corresponds to an object table on the server, and each slice _usually_ consists of the
following:
- A paginated collection display, usually using the `Table` foundation (found in
`./web/src/elements/Table`)
- The ability to view an individual object from the collection, which you may be able to:
- Edit
- Delete
- A form for creating a new object
- Tabs showing that object's relationship to other objects
- Interactive elements for changing or deleting those relationships, or creating new ones.
- The ability to create new objects with which to have that relationship, if they're not part of
the core objects (such as User->MFA authenticator apps, since the latter is not a "core" object
and has no tab of its own).
- A paginated collection display, usually using the `Table` foundation (found in
`./web/src/elements/Table`)
- The ability to view an individual object from the collection, which you may be able to:
- Edit
- Delete
- A form for creating a new object
- Tabs showing that object's relationship to other objects
- Interactive elements for changing or deleting those relationships, or creating new ones.
- The ability to create new objects with which to have that relationship, if they're not part of
the core objects (such as User->MFA authenticator apps, since the latter is not a "core" object
and has no tab of its own).
We are still a bit "all over the place" with respect to sub-units and common units; there are
folders `common`, `elements`, and `components`, and ideally they would be:
- `common`: non-UI related libraries all of our applications need
- `elements`: UI elements shared among multiple applications that do not need context
- `components`: UI elements shared among multiple that use one or more context
- `common`: non-UI related libraries all of our applications need
- `elements`: UI elements shared among multiple applications that do not need context
- `components`: UI elements shared among multiple that use one or more context
... but at the moment there are some context-sensitive elements, and some UI-related stuff in
`common`.
@ -95,18 +95,18 @@ folders `common`, `elements`, and `components`, and ideally they would be:
reliably documented any other way. For the most part, they contain comments related to custom
settings in JSON files, which do not support comments.
- `tsconfig.json`:
- `compilerOptions.useDefineForClassFields: false` is required to make TSC use the "classic" form
of field definition when compiling class definitions. Storybook does not handle the ESNext
proposed definition mechanism (yet).
- `compilerOptions.plugins.ts-lit-plugin.rules.no-unknown-tag-name: "off"`: required to support
rapidoc, which exports its tag late.
- `compilerOptions.plugins.ts-lit-plugin.rules.no-missing-import: "off"`: lit-analyzer currently
does not support path aliases very well, and cannot find the definition files associated with
imports using them.
- `compilerOptions.plugins.ts-lit-plugin.rules.no-incompatible-type-binding: "warn"`: lit-analyzer
does not support generics well when parsing a subtype of `HTMLElement`. As a result, this threw
too many errors to be supportable.
- `tsconfig.json`:
- `compilerOptions.useDefineForClassFields: false` is required to make TSC use the "classic" form
of field definition when compiling class definitions. Storybook does not handle the ESNext
proposed definition mechanism (yet).
- `compilerOptions.plugins.ts-lit-plugin.rules.no-unknown-tag-name: "off"`: required to support
rapidoc, which exports its tag late.
- `compilerOptions.plugins.ts-lit-plugin.rules.no-missing-import: "off"`: lit-analyzer currently
does not support path aliases very well, and cannot find the definition files associated with
imports using them.
- `compilerOptions.plugins.ts-lit-plugin.rules.no-incompatible-type-binding: "warn"`: lit-analyzer
does not support generics well when parsing a subtype of `HTMLElement`. As a result, this threw
too many errors to be supportable.
### License

13262
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
"@floating-ui/dom": "^1.6.11",
"@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.6.0",
"@goauthentik/api": "^2025.2.4-1744640358",
"@goauthentik/api": "^2025.2.4-1744288676",
"@lit-labs/ssr": "^3.2.2",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2",
@ -42,7 +42,7 @@
"lit": "^3.2.0",
"md-front-matter": "^1.0.4",
"mermaid": "^11.4.1",
"rapidoc": "^9.3.8",
"rapidoc": "^9.3.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rehype-highlight": "^7.0.2",
@ -128,14 +128,6 @@
"@rollup/rollup-linux-arm64-gnu": "4.23.0",
"@rollup/rollup-linux-x64-gnu": "4.23.0"
},
"overrides": {
"rapidoc": {
"@apitools/openapi-parser@": "0.0.37"
},
"chromedriver": {
"axios": "^1.8.4"
}
},
"private": true,
"scripts": {
"build": "wireit",

View File

@ -9,11 +9,11 @@ It exists primarily to support late versions of Microsoft Office365 and Microsof
software that still uses the MSEdge-18 and IE-11 _Trident_ web engine for web-based log-ins. It has
limited support for the full language, supporting only the following stages:
- identification
- password
- redirect
- autosubmit
- authenticator validation (both code and WebAuthn)
- identification
- password
- redirect
- autosubmit
- authenticator validation (both code and WebAuthn)
### License

View File

@ -22,7 +22,6 @@ export default [
"coverage/",
"src/locale-codes.ts",
"storybook-static/",
"scripts/esbuild",
"src/locales/",
],
},

View File

@ -131,7 +131,6 @@ export class AkAdminSidebar extends WithCapabilitiesConfig(WithVersion(AKElement
["/identity/users", msg("Users"), [`^/identity/users/(?<id>${ID_REGEX})$`]],
["/identity/groups", msg("Groups"), [`^/identity/groups/(?<id>${UUID_REGEX})$`]],
["/identity/roles", msg("Roles"), [`^/identity/roles/(?<id>${UUID_REGEX})$`]],
["/identity/initial-permissions", msg("Initial Permissions"), [`^/identity/initial-permissions/(?<id>${ID_REGEX})$`]],
["/core/sources", msg("Federation and Social login"), [`^/core/sources/(?<slug>${SLUG_REGEX})$`]],
["/core/tokens", msg("Tokens and App passwords")],
["/flow/stages/invitations", msg("Invitations")]]],

View File

@ -84,10 +84,6 @@ export const ROUTES: Route[] = [
await import("@goauthentik/admin/roles/RoleListPage");
return html`<ak-role-list></ak-role-list>`;
}),
new Route(new RegExp("^/identity/initial-permissions$"), async () => {
await import("@goauthentik/admin/rbac/InitialPermissionsListPage");
return html`<ak-initial-permissions-list></ak-initial-permissions-list>`;
}),
new Route(new RegExp(`^/identity/roles/(?<id>${UUID_REGEX})$`), async (args) => {
await import("@goauthentik/admin/roles/RoleViewPage");
return html`<ak-role-view roleId=${args.id}></ak-role-view>`;

View File

@ -15,7 +15,9 @@ export const bindModeOptions = [
{
label: msg("Direct binding"),
value: LDAPAPIAccessMode.Direct,
description: html`${msg("Always execute the configured bind flow to authenticate the user")}`,
description: html`${msg(
"Always execute the configured bind flow to authenticate the user",
)}`,
},
];
@ -31,7 +33,9 @@ export const searchModeOptions = [
{
label: msg("Direct querying"),
value: LDAPAPIAccessMode.Direct,
description: html`${msg("Always returns the latest data, but slower than cached querying")}`,
description: html`${msg(
"Always returns the latest data, but slower than cached querying",
)}`,
},
];

View File

@ -1,150 +0,0 @@
import { InitialPermissionsModeToLabel } from "@goauthentik/admin/rbac/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider";
import { DataProvision, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
import "@goauthentik/elements/chips/Chip";
import "@goauthentik/elements/chips/ChipGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import {
InitialPermissions,
InitialPermissionsModeEnum,
Permission,
RbacApi,
RbacRolesListRequest,
Role,
} from "@goauthentik/api";
export function rbacPermissionPair(item: Permission): DualSelectPair {
return [item.id.toString(), html`<div class="selection-main">${item.name}</div>`, item.name];
}
@customElement("ak-initial-permissions-form")
export class InitialPermissionsForm extends ModelForm<InitialPermissions, string> {
loadInstance(pk: string): Promise<InitialPermissions> {
return new RbacApi(DEFAULT_CONFIG).rbacInitialPermissionsRetrieve({
id: Number(pk),
});
}
getSuccessMessage(): string {
return this.instance
? msg("Successfully updated initial permissions.")
: msg("Successfully created initial permissions.");
}
async send(data: InitialPermissions): Promise<InitialPermissions> {
if (this.instance?.pk) {
return new RbacApi(DEFAULT_CONFIG).rbacInitialPermissionsPartialUpdate({
id: this.instance.pk,
patchedInitialPermissionsRequest: data,
});
} else {
return new RbacApi(DEFAULT_CONFIG).rbacInitialPermissionsCreate({
initialPermissionsRequest: data,
});
}
}
renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${msg("Name")} required name="name">
<input
type="text"
value="${ifDefined(this.instance?.name)}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Role")} required name="role">
<ak-search-select
.fetchObjects=${async (query?: string): Promise<Role[]> => {
const args: RbacRolesListRequest = {
ordering: "name",
};
if (query !== undefined) {
args.search = query;
}
const users = await new RbacApi(DEFAULT_CONFIG).rbacRolesList(args);
return users.results;
}}
.renderElement=${(role: Role): string => {
return role.name;
}}
.renderDescription=${(role: Role): TemplateResult => {
return html`${role.name}`;
}}
.value=${(role: Role | undefined): string | undefined => {
return role?.pk;
}}
.selected=${(role: Role): boolean => {
return this.instance?.role === role.pk;
}}
>
</ak-search-select>
<p class="pf-c-form__helper-text">
${msg(
"When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Mode")} required name="mode">
<select class="pf-c-form-control">
<option
value=${InitialPermissionsModeEnum.User}
?selected=${this.instance?.mode === InitialPermissionsModeEnum.User}
>
${InitialPermissionsModeToLabel(InitialPermissionsModeEnum.User)}
</option>
<option
value=${InitialPermissionsModeEnum.Role}
?selected=${this.instance?.mode === InitialPermissionsModeEnum.Role}
>
${InitialPermissionsModeToLabel(InitialPermissionsModeEnum.Role)}
</option>
</select>
<p class="pf-c-form__helper-text">
${msg(
"The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Permissions")} name="permissions">
<ak-dual-select-provider
.provider=${(page: number, search?: string): Promise<DataProvision> => {
return new RbacApi(DEFAULT_CONFIG)
.rbacPermissionsList({
page: page,
search: search,
})
.then((results) => {
return {
pagination: results.pagination,
options: results.results.map(rbacPermissionPair),
};
});
}}
.selected=${(this.instance?.permissionsObj ?? []).map(rbacPermissionPair)}
available-label="${msg("Available Permissions")}"
selected-label="${msg("Selected Permissions")}"
></ak-dual-select-provider>
<p class="pf-c-form__helper-text">
${msg("Permissions to grant when a new object is created.")}
</p>
</ak-form-element-horizontal>
</form>`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-initial-permissions-form": InitialPermissionsForm;
}
}

View File

@ -1,115 +0,0 @@
import "@goauthentik/admin/rbac/InitialPermissionsForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/forms/DeleteBulkForm";
import "@goauthentik/elements/forms/ModalForm";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage";
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { InitialPermissions, RbacApi } from "@goauthentik/api";
@customElement("ak-initial-permissions-list")
export class InitialPermissionsListPage extends TablePage<InitialPermissions> {
checkbox = true;
clearOnRefresh = true;
searchEnabled(): boolean {
return true;
}
pageTitle(): string {
return msg("Initial Permissions");
}
pageDescription(): string {
return msg("Set initial permissions for newly created objects.");
}
pageIcon(): string {
return "fa fa-lock";
}
@property()
order = "name";
async apiEndpoint(): Promise<PaginatedResponse<InitialPermissions>> {
return new RbacApi(DEFAULT_CONFIG).rbacInitialPermissionsList(
await this.defaultEndpointConfig(),
);
}
columns(): TableColumn[] {
return [new TableColumn(msg("Name"), "name"), new TableColumn(msg("Actions"))];
}
renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk
objectLabel=${msg("Initial Permissions")}
.objects=${this.selectedElements}
.usedBy=${(item: InitialPermissions) => {
return new RbacApi(DEFAULT_CONFIG).rbacInitialPermissionsUsedByList({
id: item.pk,
});
}}
.delete=${(item: InitialPermissions) => {
return new RbacApi(DEFAULT_CONFIG).rbacInitialPermissionsDestroy({
id: item.pk,
});
}}
>
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
${msg("Delete")}
</button>
</ak-forms-delete-bulk>`;
}
render(): TemplateResult {
return html`<ak-page-header
icon=${this.pageIcon()}
header=${this.pageTitle()}
description=${ifDefined(this.pageDescription())}
>
</ak-page-header>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">${this.renderTable()}</div>
</section>`;
}
row(item: InitialPermissions): TemplateResult[] {
return [
html`${item.name}`,
html`<ak-forms-modal>
<span slot="submit"> ${msg("Update")} </span>
<span slot="header"> ${msg("Update Initial Permissions")} </span>
<ak-initial-permissions-form slot="form" .instancePk=${item.pk}>
</ak-initial-permissions-form>
<button slot="trigger" class="pf-c-button pf-m-plain">
<pf-tooltip position="top" content=${msg("Edit")}>
<i class="fas fa-edit"></i>
</pf-tooltip>
</button>
</ak-forms-modal>`,
];
}
renderObjectCreate(): TemplateResult {
return html`
<ak-forms-modal>
<span slot="submit"> ${msg("Create")} </span>
<span slot="header"> ${msg("Create Initial Permissions")} </span>
<ak-initial-permissions-form slot="form"> </ak-initial-permissions-form>
<button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
</ak-forms-modal>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"initial-permissions-list": InitialPermissionsListPage;
}
}

View File

@ -1,14 +0,0 @@
import { msg } from "@lit/localize";
import { InitialPermissionsModeEnum } from "@goauthentik/api";
export function InitialPermissionsModeToLabel(mode: InitialPermissionsModeEnum): string {
switch (mode) {
case InitialPermissionsModeEnum.User:
return msg("User");
case InitialPermissionsModeEnum.Role:
return msg("Role");
case InitialPermissionsModeEnum.UnknownDefaultOpenApi:
return msg("Unknown Initial Permissions mode");
}
}

View File

@ -7,7 +7,6 @@ import {
} from "@goauthentik/admin/sources/oauth/utils";
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import {
@ -17,7 +16,6 @@ import {
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/Radio";
import "@goauthentik/elements/forms/SearchSelect";
import { msg } from "@lit/localize";
@ -26,7 +24,6 @@ import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import {
AuthorizationCodeAuthMethodEnum,
FlowsInstancesListDesignationEnum,
GroupMatchingModeEnum,
OAuthSource,
@ -39,18 +36,6 @@ import {
import { propertyMappingsProvider, propertyMappingsSelector } from "./OAuthSourceFormHelpers.js";
const authorizationCodeAuthMethodOptions = [
{
label: msg("HTTP Basic Auth"),
value: AuthorizationCodeAuthMethodEnum.BasicAuth,
default: true,
},
{
label: msg("Include the client ID and secret as request parameters"),
value: AuthorizationCodeAuthMethodEnum.PostBody,
},
];
@customElement("ak-source-oauth-form")
export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuthSource>) {
async loadInstance(pk: string): Promise<OAuthSource> {
@ -255,19 +240,6 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
<p class="pf-c-form__helper-text">${msg("Raw JWKS data.")}</p>
</ak-form-element-horizontal>`
: html``}
${this.providerType.name === ProviderTypeEnum.Openidconnect
? html`<ak-radio-input
label=${msg("Authorization code authentication method")}
name="authorizationCodeAuthMethod"
required
.options=${authorizationCodeAuthMethodOptions}
.value=${this.instance?.authorizationCodeAuthMethod}
help=${msg(
"How to perform authentication during an authorization_code token request flow",
)}
>
</ak-radio-input>`
: html``}
</div>
</ak-form-group>`;
}

View File

@ -2,7 +2,6 @@ import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first, groupBy } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-switch-input.js";
import "@goauthentik/elements/ak-checkbox-group/ak-checkbox-group.js";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup";
@ -159,38 +158,68 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="caseInsensitiveMatching"
label=${msg("Case insensitive matching")}
?checked=${first(this.instance?.caseInsensitiveMatching, true)}
help=${msg(
"When enabled, user fields are matched regardless of their casing.",
)}
></ak-switch-input>
<ak-switch-input
name="pretendUserExists"
label=${msg("Pretend user exists")}
?checked=${first(this.instance?.pretendUserExists, true)}
help=${msg(
"When enabled, the stage will always accept the given user identifier and continue.",
)}
></ak-switch-input>
<ak-switch-input
name="showMatchedUser"
label=${msg("Show matched user")}
?checked=${first(this.instance?.showMatchedUser, true)}
help=${msg(
"When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown.",
)}
></ak-switch-input>
<ak-switch-input
name="enableRememberMe"
label=${msg('Enable "Remember me on this device"')}
?checked=${this.instance?.enableRememberMe}
help=${msg(
"When enabled, the user can save their username in a cookie, allowing them to skip directly to entering their password.",
)}
></ak-switch-input>
<ak-form-element-horizontal name="caseInsensitiveMatching">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${first(this.instance?.caseInsensitiveMatching, true)}
/>
<span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon">
<i class="fas fa-check" aria-hidden="true"></i>
</span>
</span>
<span class="pf-c-switch__label"
>${msg("Case insensitive matching")}</span
>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When enabled, user fields are matched regardless of their casing.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="pretendUserExists">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${first(this.instance?.pretendUserExists, true)}
/>
<span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon">
<i class="fas fa-check" aria-hidden="true"></i>
</span>
</span>
<span class="pf-c-switch__label">${msg("Pretend user exists")}</span>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When enabled, the stage will always accept the given user identifier and continue.",
)}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal name="showMatchedUser">
<label class="pf-c-switch">
<input
class="pf-c-switch__input"
type="checkbox"
?checked=${first(this.instance?.showMatchedUser, true)}
/>
<span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon">
<i class="fas fa-check" aria-hidden="true"></i>
</span>
</span>
<span class="pf-c-switch__label">${msg("Show matched user")}</span>
</label>
<p class="pf-c-form__helper-text">
${msg(
"When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown.",
)}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
<ak-form-group>

View File

@ -1,5 +1,4 @@
import {
CSRFHeaderName,
CSRFMiddleware,
EventMiddleware,
LoggingMiddleware,
@ -9,10 +8,6 @@ import { globalAK } from "@goauthentik/common/global";
import { Config, Configuration, CoreApi, CurrentBrand, RootApi } from "@goauthentik/api";
// HACK: Workaround for ESBuild not being able to hoist import statement across entrypoints.
// This can be removed after ESBuild uses a single build context for all entrypoints.
export { CSRFHeaderName };
let globalConfigPromise: Promise<Config> | undefined = Promise.resolve(globalAK().config);
export function config(): Promise<Config> {
if (!globalConfigPromise) {

View File

@ -5,7 +5,6 @@ import "@goauthentik/elements/forms/FormElement";
import "@goauthentik/flow/components/ak-flow-password-input.js";
import { BaseStage } from "@goauthentik/flow/stages/base";
import "@goauthentik/flow/stages/captcha/CaptchaStage";
import { AkRememberMeController } from "@goauthentik/flow/stages/identification/RememberMeController.js";
import { msg, str } from "@lit/localize";
import { CSSResult, PropertyValues, TemplateResult, css, html, nothing } from "lit";
@ -48,8 +47,6 @@ export class IdentificationStage extends BaseStage<
> {
form?: HTMLFormElement;
rememberMe: AkRememberMeController;
@state()
captchaToken = "";
@state()
@ -65,9 +62,8 @@ export class IdentificationStage extends BaseStage<
PFFormControl,
PFTitle,
PFButton,
AkRememberMeController.styles,
/* login page's icons */
css`
/* login page's icons */
.pf-c-login__main-footer-links-item button {
background-color: transparent;
border: 0;
@ -85,11 +81,6 @@ export class IdentificationStage extends BaseStage<
];
}
constructor() {
super();
this.rememberMe = new AkRememberMeController(this);
}
updated(changedProperties: PropertyValues<this>) {
if (changedProperties.has("challenge") && this.challenge !== undefined) {
this.autoRedirect();
@ -277,10 +268,8 @@ export class IdentificationStage extends BaseStage<
autocomplete="username"
spellcheck="false"
class="pf-c-form-control"
value=${this.rememberMe?.username ?? ""}
required
/>
${this.rememberMe.render()}
</ak-form-element>
${this.challenge.passwordFields
? html`

View File

@ -1,156 +0,0 @@
import { getCookie } from "@goauthentik/common/utils.js";
import { msg } from "@lit/localize";
import { css, html, nothing } from "lit";
import { ReactiveController, ReactiveControllerHost } from "lit";
import type { IdentificationStage } from "./IdentificationStage.js";
type RememberMeHost = ReactiveControllerHost & IdentificationStage;
export class AkRememberMeController implements ReactiveController {
static get styles() {
return css`
.remember-me-switch {
display: inline-block;
padding-top: 0.25rem;
}
`;
}
username?: string;
rememberingUsername: boolean = false;
constructor(private host: RememberMeHost) {
this.trackRememberMe = this.trackRememberMe.bind(this);
this.toggleRememberMe = this.toggleRememberMe.bind(this);
this.host.addController(this);
}
// Record a stable token that we can use between requests to track if we've
// been here before. If we can't, clear out the username.
hostConnected() {
try {
const sessionId = localStorage.getItem("authentik-remember-me-session");
if (!!this.localSession && sessionId === this.localSession) {
this.username = undefined;
localStorage?.removeItem("authentik-remember-me-user");
}
localStorage?.setItem("authentik-remember-me-session", this.localSession);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (_e: any) {
this.username = undefined;
}
}
get localSession() {
return (getCookie("authentik_csrf") ?? "").substring(0, 8);
}
get usernameField() {
return this.host.renderRoot.querySelector(
'input[name="uidField"]',
) as HTMLInputElement | null;
}
get rememberMeToggle() {
return this.host.renderRoot.querySelector(
"#authentik-remember-me",
) as HTMLInputElement | null;
}
get isValidChallenge() {
return !(
this.host.challenge.responseErrors &&
this.host.challenge.responseErrors.non_field_errors &&
this.host.challenge.responseErrors.non_field_errors.find(
(cre) => cre.code === "invalid",
)
);
}
get submitButton() {
return this.host.renderRoot.querySelector('button[type="submit"]') as HTMLButtonElement;
}
get isEnabled() {
return (
this.host.challenge !== undefined &&
this.host.challenge.enableRememberMe &&
typeof localStorage !== "undefined"
);
}
get canAutoSubmit() {
return (
!!this.host.challenge &&
!!this.username &&
!!this.usernameField?.value &&
!this.host.challenge.passwordFields &&
!this.host.challenge.passwordlessUrl
);
}
// Before the page is updated, try to extract the username from localstorage.
hostUpdate() {
if (!this.isEnabled) {
return;
}
try {
this.username = localStorage.getItem("authentik-remember-me-user") || undefined;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (_e: any) {
this.username = undefined;
}
}
// After the page is updated, if everything is ready to go, do the autosubmit.
hostUpdated() {
if (this.isEnabled && this.canAutoSubmit) {
this.submitButton?.click();
}
}
trackRememberMe() {
if (!this.usernameField || this.usernameField.value === undefined) {
return;
}
this.username = this.usernameField.value;
localStorage?.setItem("authentik-remember-me-user", this.username);
}
// When active, save current details and record every keystroke to the username.
// When inactive, clear all fields and remove keystroke recorder.
toggleRememberMe() {
if (!this.rememberMeToggle || !this.rememberMeToggle.checked) {
localStorage?.removeItem("authentik-remember-me-user");
localStorage?.removeItem("authentik-remember-me-session");
this.username = undefined;
this.usernameField?.removeEventListener("keyup", this.trackRememberMe);
return;
}
if (!this.usernameField) {
return;
}
localStorage?.setItem("authentik-remember-me-user", this.usernameField.value);
localStorage?.setItem("authentik-remember-me-session", this.localSession);
this.usernameField.addEventListener("keyup", this.trackRememberMe);
}
render() {
return this.isEnabled
? html` <label class="pf-c-switch remember-me-switch">
<input
class="pf-c-switch__input"
id="authentik-remember-me"
@click=${this.toggleRememberMe}
type="checkbox"
?checked=${!!this.username}
/>
<span class="pf-c-form__label">${msg("Remember me on this device")}</span>
</label>`
: nothing;
}
}

View File

@ -1,7 +1,4 @@
// sort-imports-ignore
import "rapidoc";
import { CSRFHeaderName } from "@goauthentik/common/api/config";
import { CSRFHeaderName } from "@goauthentik/common/api/middleware";
import { EVENT_THEME_CHANGE } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global";
import { first, getCookie } from "@goauthentik/common/utils";
@ -9,6 +6,7 @@ import { Interface } from "@goauthentik/elements/Interface";
import "@goauthentik/elements/ak-locale-context";
import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
import { themeImage } from "@goauthentik/elements/utils/images";
import "rapidoc";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, css, html } from "lit";

View File

@ -9086,66 +9086,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -7619,66 +7619,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9178,66 +9178,6 @@ Las vinculaciones a grupos o usuarios se comparan con el usuario del evento.</ta
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9696,91 +9696,12 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="s783964a224796865">
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'. When selecting 'Lookup using a user attribute', this should be a user attribute, otherwise a group attribute.</source>
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ "memberUid", la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'. Lorsque "Recherche avec un attribut utilisateur" est sélectionné, cet attribut doit être un attribut utilisateur, sinon un attribut de groupe.</target>
</trans-unit>
<trans-unit id="s1d47b4f61ca53e8e">
<source>Lookup using user attribute</source>
<target>Recherche avec un attribut utilisateur</target>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
<target>Champ contenant les DN des groupes dont l'utilisateur est membre. Ce champ est utilisé pour rechercher les groupes d'un utilisateur, par exemple 'memberOf'. Pour rechercher les groupes imbriqués dans un environnement Active Directory, utilisez 'memberOf:1.2.840.113556.1.4.1941:'.</target>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
<target>Permissions initiales</target>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
<target>Mode de permissions initiales inconnu</target>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
<target>Permissions initiales mises à jour avec succès.</target>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
<target>Permissions initiales créées avec succès.</target>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
<target>Lorsqu'un utilisateur avec le rôle sélectionné crée un objet, les permissions initiales seront appliquées à cet objet,</target>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
<target>Les permissions initiales peuvent soit être placées sur l'utilisateur créant l'objet, ou sur le rôle sélectionné au champ précédent.</target>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
<target>Permissions disponibles</target>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
<target>Permissions sélectionnées</target>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
<target>Permissions à attribuer lorsqu'un nouvel objet est créé.</target>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
<target>Définir des permissions initiales pour les objets nouvellement créés.</target>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
<target>Mettre à jour les permissions initiales</target>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
<target>Créer des permissions initiales</target>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
<target>Réputation : limite inférieure</target>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
<target>La réputation ne peut pas descendre en dessous de cette valeur. Zéro ou négatif.</target>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
<target>Réputation : limite supérieure</target>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
<target>La réputation ne peut pas monter au dessus de cette valeur. Zéro ou positif.</target>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9703,66 +9703,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9086,66 +9086,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -8988,66 +8988,6 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9413,66 +9413,6 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9421,64 +9421,4 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body></file></xliff>

View File

@ -9506,66 +9506,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9477,66 +9477,6 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -6227,66 +6227,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -9697,91 +9697,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s783964a224796865">
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'. When selecting 'Lookup using a user attribute', this should be a user attribute, otherwise a group attribute.</source>
<target>包含组成员的字段。请注意,如果使用 "memberUid" 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'。当选中“使用用户属性查询”时,此配置应该为用户属性,否则为组属性。</target>
</trans-unit>
<trans-unit id="s1d47b4f61ca53e8e">
<source>Lookup using user attribute</source>
<target>使用用户属性查询</target>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
<target>包含用户所属组 DN 的字段。此字段用于从用户查询组,例如 'memberOf'。要在 Active Directory 环境中查询嵌套组,则使用 'memberOf:1.2.840.113556.1.4.1941:'。</target>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
<target>初始权限</target>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
<target>未知初始权限模式</target>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
<target>已成功更新初始权限。</target>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
<target>已成功创建初始权限。</target>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
<target>当所选角色的用户创建对象时,初始权限会应用于该对象。</target>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
<target>初始权限既可以属于创建对象的用户,又可以属于上一个字段中设置的角色。</target>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
<target>可用权限</target>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
<target>已选权限</target>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
<target>创建新对象时授予的权限。</target>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
<target>为新创建的对象设置初始权限。</target>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
<target>更新初始权限</target>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
<target>创建初始权限</target>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
<target>信誉:下限值</target>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
<target>信誉无法降低到此值以下。可为零或负数。</target>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
<target>信誉:上限值</target>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
<target>信誉无法提高到此值以上。可为零或正数。</target>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -7319,66 +7319,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -9697,79 +9697,12 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s783964a224796865">
<source>Field which contains members of a group. Note that if using the &quot;memberUid&quot; field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'. When selecting 'Lookup using a user attribute', this should be a user attribute, otherwise a group attribute.</source>
<target>包含组成员的字段。请注意,如果使用 &quot;memberUid&quot; 字段,则假定该值包含相对可分辨名称。例如,'memberUid=some-user' 而不是 'memberUid=cn=some-user,ou=groups,...'。当选中“使用用户属性查询”时,此配置应该为用户属性,否则为组属性。</target>
</trans-unit>
<trans-unit id="s1d47b4f61ca53e8e">
<source>Lookup using user attribute</source>
<target>使用用户属性查询</target>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
<target>包含用户所属组 DN 的字段。此字段用于从用户查询组,例如 'memberOf'。要在 Active Directory 环境中查询嵌套组,则使用 'memberOf:1.2.840.113556.1.4.1941:'。</target>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
<target>初始权限</target>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
<target>未知初始权限模式</target>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
<target>已成功更新初始权限。</target>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
<target>已成功创建初始权限。</target>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
<target>当所选角色的用户创建对象时,初始权限会应用于该对象。</target>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
<target>初始权限既可以属于创建对象的用户,又可以属于上一个字段中设置的角色。</target>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
<target>可用权限</target>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
<target>已选权限</target>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
<target>创建新对象时授予的权限。</target>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
<target>为新创建的对象设置初始权限。</target>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
<target>更新初始权限</target>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
<target>创建初始权限</target>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
<target>信誉:下限值</target>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
<target>信誉无法降低到此值以下。可为零或负数。</target>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
<target>信誉:上限值</target>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
<target>信誉无法提高到此值以上。可为零或正数。</target>
</trans-unit>
</body>
</file>

View File

@ -9063,66 +9063,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
</trans-unit>
<trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source>
</trans-unit>
<trans-unit id="sedb57bf4b42a8e40">
<source>Unknown Initial Permissions mode</source>
</trans-unit>
<trans-unit id="s6ea6a64acb45dfdf">
<source>Successfully updated initial permissions.</source>
</trans-unit>
<trans-unit id="sfddf7896ab5938b6">
<source>Successfully created initial permissions.</source>
</trans-unit>
<trans-unit id="s5c5f240cbb6d0bae">
<source>When a user with the selected Role creates an object, the Initial Permissions will be applied to that object.</source>
</trans-unit>
<trans-unit id="sbf27294eef56ac81">
<source>The Initial Permissions can either be placed on the User creating the object, or the Role selected in the previous field.</source>
</trans-unit>
<trans-unit id="s93f04537efda1b24">
<source>Available Permissions</source>
</trans-unit>
<trans-unit id="s297bc57f9e494470">
<source>Selected Permissions</source>
</trans-unit>
<trans-unit id="s0ea71d53764d781c">
<source>Permissions to grant when a new object is created.</source>
</trans-unit>
<trans-unit id="s06fc21a40f5d7de1">
<source>Set initial permissions for newly created objects.</source>
</trans-unit>
<trans-unit id="sc7104a4d0fc35c7c">
<source>Update Initial Permissions</source>
</trans-unit>
<trans-unit id="s83fa005829a65be9">
<source>Create Initial Permissions</source>
</trans-unit>
<trans-unit id="se37ac6cf9c72f21a">
<source>Reputation: lower limit</source>
</trans-unit>
<trans-unit id="sa634ffa797037aac">
<source>Reputation cannot decrease lower than this value. Zero or negative.</source>
</trans-unit>
<trans-unit id="s862986ce8e70edd7">
<source>Reputation: upper limit</source>
</trans-unit>
<trans-unit id="sdd04913b3b46cf30">
<source>Reputation cannot increase higher than this value. Zero or positive.</source>
</trans-unit>
<trans-unit id="s4d5cb134999b50df">
<source>HTTP Basic Auth</source>
</trans-unit>
<trans-unit id="s6927635d1c339cfc">
<source>Include the client ID and secret as request parameters</source>
</trans-unit>
<trans-unit id="s4fca384c634e1a92">
<source>Authorization code authentication method</source>
</trans-unit>
<trans-unit id="sdc02c276ed429008">
<source>How to perform authentication during an authorization_code token request flow</source>
</trans-unit>
</body>
</file>

View File

@ -34,10 +34,6 @@ These fields specify if and which flows are linked on the form. The enrollment f
When enabled, any user identifier will be accepted as valid (as long as they match the correct format, i.e. when [User fields](#user-fields) is set to only allow Emails, then the identifier still needs to be an Email). The stage will succeed and the flow will continue to the next stage. Stages like the [Password stage](../password/index.md) and [Email stage](../email/index.mdx) are aware of this "pretend" user and will behave the same as if the user would exist.
## Enable "Remember me on this device":ak-version[2025.4]
When enabled, users will be given the option at login of having their username stored on the device. If selected, on future logins this stage will automatically fill in the username and fast-forward to the password field. Users will still have the options of clicking "Not you?" and going back to provide a different username or disable this feature.
## Source settings
Some sources (like the [OAuth Source](../../../../users-sources/sources/protocols/oauth/index.mdx) and [SAML Source](../../../../users-sources/sources/protocols/saml/index.md)) require user interaction. To make these sources available to users, they can be selected in the Identification stage settings, which will show them below the selected [user field](#user-fields).

View File

@ -8,7 +8,7 @@ authentik provides several [standard policy types](./index.md#standard-policies)
We also document how to use a policy to [whitelist email domains](./expression/whitelist_email.md) and to [ensure unique email addresses](./expression/unique_email.md).
To learn more see also [bindings](../../add-secure-apps/flows-stages/bindings/index.md) and how to [bind policy bindings to a new application when the application is created](../../add-secure-apps/applications/manage_apps.mdx#instructions) (for example, to configure application-specific access).
To learn more see also [bindings](../../add-secure-apps/flows-stages/bindings/index.md) and how to [bind policy bindings to a new application when yo create the application](../../add-secure-apps/applications/manage_apps.mdx#instructions) (for example, to configure application-specific access).
## Create a policy

View File

@ -19,8 +19,6 @@ Previously, sessions were stored by default in the cache. Now, they are stored i
## New features
### Postgres pool
## Upgrading
This release does not introduce any new requirements. You can follow the upgrade instructions below; for more detailed information about upgrading authentik, refer to our [Upgrade documentation](../../install-config/upgrade.mdx).

View File

@ -4,14 +4,14 @@ sidebar_label: Actual Budget
support_level: community
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
## What is Actual Budget
> Actual Budget is a web-based financial management software. It helps users track and manage their income, expenses, and budgets in real time. The software compares actual spending with planned budgets to improve financial decisions.
> Actual Budget is a web-based financial management software. It helps users track and manage their income, expenses, and budgets in real time.
> The software compares actual spending with planned budgets to improve financial decisions.
>
> -- https://actualbudget.org/
>
> This guide explains how to configure Actual Budget to use authentik as the OAuth provider for logging in to the Web GUI.
## Preparation
@ -37,7 +37,7 @@ To support the integration of Actual Budget with authentik, you need to create a
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
- Note the **Client ID**,**Client Secret**, and **slug** values because they will be required later.
- Set a `Strict` redirect URI to <kbd>https://<em>actual.company</em>/openid/callback</kbd>.
- Set a `Strict` redirect URI to <kbd>https://<em>actual.company</em>/openid/callback/</kbd>.
- Select any available signing key. Actual Budget only supports the RS256 algorithm. Be aware of this when choosing a signing key.
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/flows-stages/bindings/) (policy, group, or user) to manage the listing and access to applications on a user's **My applications** page.
@ -45,67 +45,33 @@ To support the integration of Actual Budget with authentik, you need to create a
## Actual Budget configuration
<Tabs
defaultValue="env"
values={[
{ label: 'With Environment Variables', value: 'env' },
{ label: 'By editing the JSON file', value: 'json' },
{ label: 'Using the UI', value: 'ui' },
]}>
<TabItem value="env">
You can configure OpenID Connect with Actual Budget by adding the following variables to your `.env` file.
1. Sign in to Actual Budget with a browser of your choice and access your budget by clicking on its name.
```yaml showLineNumbers
ACTUAL_OPENID_DISCOVERY_URL=https://authentik.company/application/o/<your-application-slug>/
ACTUAL_OPENID_CLIENT_ID=Your Client ID from authentik
ACTUAL_OPENID_CLIENT_SECRET=Your Client Secret from authentik
ACTUAL_OPENID_SERVER_HOSTNAME=https://actual.company
```
2. Click your budget in the top-left corner to open the dropdown menu and select **Settings**.
</TabItem>
<TabItem value="json">
3. Scroll to the bottom and select **Show advanced settings**. Scroll again and select **I understand the risks, show experimental features**.
You can configure Actual Budget to authenticate users with OpenID Connect by modifying the `/data/config.json` file or it's equivalent specified by the `ACTUAL_DATA_DIR` environment variable.
4. To enable the option **OpenID authentication method** select the checkbox next to it.
```json showLineNumbers title="/data/config.json"
"openId": {
"issuer": "https://authentik.company/application/o/<your-application-slug>/",
"client_id": "<Client ID from authentik>",
"client_secret": "<Client Secret from authentik>",
"server_hostname": "https://actual.company",
"authMethod": "openid"
}
```
5. Scroll up to the new option **Authentication method...** and click **Start using OpenID**.
</TabItem>
<TabItem value="ui">
Alternatively, it is possible to configure OpenID Connect via the UI.
1. Sign in to Actual Budget and select your budget by clicing its name.
2. In the top-left corner, click your budget name to open the dropdown and choose **Settings**.
3. Scroll down and select **Show advanced settings**, then enable **I understand the risks, show experimental features**.
4. Enable **OpenID authentication method**.
5. Scroll up and click **Start using OpenID** under the **Authentication method** section.
6. Fill in the following values:
- **OpenID Provider**: authentik
- **OpenID provider URL**: <kbd>https://<em>authentik.company</em>/application/o/<em>your-application-slug</em>/</kbd>
- **Client ID**: Enter the **Client ID** from authentik
- **Client Secret**: Enter the **Client Secret** from authentik
</TabItem>
</Tabs>
6. Set the following values from the authentik provider:
- Set **OpenID Provider** to **authentik**
- Set **OpenID provider URL** to https://_authentik.company_/application/o/_actual_/
- Set **Client ID** to _client-id_
- Set **Client secret** to _client-secret_
:::warning
The first user to log into Actual Budget via OpenID will become the owner and administrator with the highest privileges for the budget. You should also note that users are not created automatically in Actual Budget. The owner must manually add users.
To do so, navigate to **Server online** > **User Directory**, and create users matching exiting authentik usernames. Then, grant access to the budget via the **User Access** tab.
The first user to log into Actual Budget via OpenID will become the owner and administrator with the highest privileges for the budget. For more information on how to create additional users, see the Note below.
:::
## Resources
## Test the login
- [Official Actual Budget documentation on OpenID Connect integration](https://actualbudget.org/docs/experimental/oauth-auth/)
- Open a browser of your choice and navigate to https://_actual.company_.
- Select the OpenID login method in the dropdown menu and click **Sign in with OpenID**.
- You should be redirected to authentik (with the login flows you created), and then authentik will redirect you back to the https://_actual.company_ URL.
- If you are redirected back to the https://_actual.company_ URL and can see the budget file selection page, the setup was successful.
## Configuration verification
To confirm that authentik is properly configured with Actual Budget, visit your Actual Budget installation, select the OpenID login method from the dropdown menu, and click **Sign in with OpenID**.
:::info
Users are not automatically created when logging in with authentik. The owner must manually create each user in Actual Budget. To do so, click **Server online** at the top next to your name and select **User Directory**. Add a new user. The `Username` must match the one in authentik. You can now grant the new user access to your budget by clicking **Server online** next to your name at the top and selecting **User Access**.
:::

View File

@ -23,7 +23,7 @@ This documentation lists only the settings that you need to change from their de
## authentik configuration
To support the integration of AdventureLog with authentik, you need to create an application/provider pair in authentik.
To support the integration of Adventure Log with authentik, you need to create an application/provider pair in authentik.
### Create an application and provider in authentik
@ -42,22 +42,41 @@ To support the integration of AdventureLog with authentik, you need to create an
## AdventureLog configuration
:::info
`localhost` is unlikely to be a valid `server_url` because it refers to the server hosting AdventureLog, not authentik. Instead, use the IP address of the server running authentik or a domain name if available.
AdventureLog documentation can be found here: https://adventurelog.app/docs/configuration/social_auth/authentik.html
This configuration is done in the Admin Panel. Launch the panel by clicking your user avatar in the navbar, selecting **Settings**, and then clicking **Launch Admin Panel**. Make sure you are logged in as an administrator for this to work.
Alternatively, navigate to `/admin` on your AdventureLog server.
1. In the admin panel, scroll down to the **Social Accounts** section and click **Add** next to **Social applications**. Fill in the following fields:
- Provider: OpenID Connect
- Provider ID: authentik Client ID
- Name: authentik
- Client ID: authentik Client ID
- Secret Key: authentik Client Secret
- Key: _should be left blank_
- Settings: (make sure http/https is set correctly)
```json
{
"server_url": "https://authentik.company/application/o/[YOUR_SLUG]/"
}
```
- Sites: move over the sites you want to enable authentik on, usually `example.com` and `www.example.com` unless you renamed your sites.
:::warning
`localhost` is most likely not a valid `server_url` for authentik in this instance because `localhost` is the server running AdventureLog, not authentik. You should use the IP address of the server running authentik or the domain name if you have one.
:::
1. Log in to your AdventureLog installation as an administrator and launch the Admin Panel. To do so, click your **user avatar** in the navigation bar, select **Settings**, then click **Launch Admin Panel**. Alternatively, visit <kbd>https://<em>adventurelog.company</em>/admin</kbd>.
2. Scroll down to **Social Accounts** and click **Add**. Fill in the following fields:
2. Save the configuration.
- **Provider**: OpenID Connect
- **Provider ID**: Enter the Client ID from authentik
- **Name**: `authentik`
- **Client ID**: Enter the Client ID from authentik
- **Secret Key**: Enter the Client Secret from authentik
- **Key**: Leave this line blank
- Under **Settings**:
- **server_url**: <kbd><em>https://authentik.company</em>/application/o/<em>your-application-slug</em>/</kbd>
- **Sites**: move over the sites you want to enable authentik on, usually `example.com` and `www.example.com` unless you renamed your sites.
Ensure that the authentik server is running and accessible by AdventureLog. Users should now be able to log in to AdventureLog using their authentik account.
## Configuration validation
To validate the configuration, either link to an existing account as described below or naviage to the AdventureLog login page and click the **authentik** button to log in. You should be redirected to the authentik login page. After logging in, you should be redirected back to AdventureLog.
### Linking to Existing Account
@ -72,11 +91,3 @@ Ensure the `https://adventurelog.company/accounts` path is routed to the backend
### authentik - No Permission
Launch your authentik dashboard as an admin and find the AdventureLog app. Click **More details** then **Edit**. In the admin interface, click **Test** under **Check Access**. If you get a 403 error, you need to grant the user the correct permissions. This can be done by going to the user's profile and adding the correct permissions.
## Resources
- [AdventureLog's official documentation](https://adventurelog.app/docs/configuration/social_auth/authentik.html)
## Configuration verification
To confirm authentik is correctly integrated with AdventureLog, log out and attempt to log back in using OpenID Connect by clicking the **authentik** button on the AdventureLog login page.

View File

@ -4,9 +4,6 @@ sidebar_label: Apache Guacamole™
support_level: authentik
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
## What is Apache Guacamole™
> Apache Guacamole is a clientless remote desktop gateway. It supports standard protocols like VNC, RDP, and SSH.
@ -44,13 +41,12 @@ To support the integration of Apache Guacamole with authentik, you need to creat
3. Click **Submit** to save the new application and provider.
## Apache Guacamole Configuration
## Guacamole configuration
It is recommended to create an admin account in Guacamole before configuring Single Sign-On to simplify the process. Create a user in Guacamole using the same username as in authentik and grant them admin permissions. This step is important to avoid losing access to the Guacamole admin settings, as you may need to revert your changes without it.
It is recommended you configure an admin account in Guacamole before setting up SSO to make things easier. Create a user in Guacamole using the username of your user in authentik and give them admin permissions. Without this, you might lose access to the Guacamole admin settings and have to revert the settings below.
:::warning
You can configure Apache Guacamole to use either the `sub` or `preferred_username` as the UID field under `user-name-attribute`. When using `preferred_username` as the user identifier, ensure that the [**Allow users to change username** setting](https://docs.goauthentik.io/docs/sys-mgmt/settings#allow-users-to-change-username) is disabled to prevent authentication issues. The `sub` option uses a unique, stable identifier for the user, while `preferred_username` uses the username configured in authentik.
:::
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
<Tabs
defaultValue="docker"
@ -59,35 +55,29 @@ You can configure Apache Guacamole to use either the `sub` or `preferred_usernam
{ label: 'Standalone', value: 'standalone' },
]}>
<TabItem value="docker">
Docker containers are typically configured using environment variables. To ensure proper integration, add the following variables to your `.env` file:
The Docker containers are configured via environment variables. The following variables are required:
```yaml showLineNumbers
OPENID_AUTHORIZATION_ENDPOINT=https://authentik.company/application/o/authorize/
OPENID_CLIENT_ID=<Client ID from authentik>
OPENID_ISSUER=https://authentik.company/application/o/<your-slug>/
OPENID_JWKS_ENDPOINT=https://authentik.company/application/o/<your-slug>/jwks/
OPENID_REDIRECT_URI=https://guacamole.company/ # Must match Redirect URI in authentik
OPENID_USERNAME_CLAIM_TYPE=preferred_username
```
Additionally, ensure your `guacamole.properties` file (typically located in `/etc/guacamole/`) includes the following line. This setting allows environment variables to be evaluated before static configuration files:
```yaml
enable-environment-properties: true
```
```yaml
OPENID_AUTHORIZATION_ENDPOINT: https://authentik.company/application/o/authorize/
OPENID_CLIENT_ID: # client ID from above
OPENID_ISSUER: https://authentik.company/application/o/*Slug of the application from above*/
OPENID_JWKS_ENDPOINT: https://authentik.company/application/o/*Slug of the application from above*/jwks/
OPENID_REDIRECT_URI: https://guacamole.company/ # This must match the redirect URI above
OPENID_USERNAME_CLAIM_TYPE: preferred_username
```
</TabItem>
<TabItem value="standalone">
To set up Apache Guacamole in a standalone environment, you'll need to adjust the settings in the `guacamole.properties` file, usually found in the `/etc/guacamole/` directory. Add the following settings:
Standalone Guacamole is configured using the `guacamole.properties` file. Add the following settings:
```yaml showLineNumbers title="/etc/guacamole/guacamole.properties"
openid-authorization-endpoint=https://authentik.company/application/o/authorize/
openid-client-id=<Client ID from authentik>
openid-issuer=https://authentik.company/application/o/<your-slug>/
openid-jwks-endpoint=https://authentik.company/application/o/<your-slug>/jwks/
openid-redirect-uri=https://guacamole.company/ # This must match the Redirect URI set in authentik (Including trailing slash).
openid-username-claim-type=preferred_username
```
```
openid-authorization-endpoint=https://authentik.company/application/o/authorize/
openid-client-id=# client ID from above
openid-issuer=https://authentik.company/application/o/*Slug of the application from above*/
openid-jwks-endpoint=https://authentik.company/application/o/*Slug of the application from above*/jwks/
openid-redirect-uri=https://guacamole.company/ # This must match the redirect URI above
openid-username-claim-type=preferred_username
```
</TabItem>
</Tabs>
@ -108,9 +98,9 @@ This section depends on the operating system hosting Apache Guacamole.
2. To add the certificate as trusted in `/etc/ssl/certs/ca-certificates.crt`, use the following command:
```shell
update-ca-certificates
```
```shell
update-ca-certificates
```
##### For _Synology_ systems:
@ -118,80 +108,24 @@ This section depends on the operating system hosting Apache Guacamole.
2. To add the certificate as trusted in `/etc/ssl/certs/ca-certificates.crt`, use the following command:
```shell
update-ca-certificates.sh
```
```shell
update-ca-certificates.sh
```
#### Adding Certificate Authority certificate to `/opt/java/openjkd/jre/lib/security/cacerts`
1. To export the certificate of the Certificate Authority, use the following command on the Certificate Authority host:
```shell
openssl pkcs12 -export -in <CA_certificate>.crt -inkey <CA_certificate>.key -out <CA_certificate>.p12 -passout pass:<password>
```
```shell
openssl pkcs12 -export -in <CA_certificate>.crt -inkey <CA_certificate>.key -out <CA_certificate>.p12 -passout pass:<password>
```
2. To import the certificate to the `/opt/java/openjdk/jre/lib/security/cacerts` keystore on the Apache Guacamole host, use the following command:
```shell
keytool -importkeystore -srckeystore <CA_certificate>.p12 -srcstoretype PKCS12 -keystore /opt/java/openjdk/jre/lib/security/cacerts -deststorepass <destination_store_password> -nopromt -srcstorepass <password>
```
```shell
keytool -importkeystore -srckeystore <CA_certificate>.p12 -srcstoretype PKCS12 -keystore /opt/java/openjdk/jre/lib/security/cacerts -deststorepass <destination_store_password> -nopromt -srcstorepass <password>
```
:::note
More information on the keytool command can be found in the [Oracle documentation.](https://docs.oracle.com/en/java/javase/21/docs/specs/man/keytool.html)
:::
### Self Signed Certificates
When using a self-signed certificate, it is necessary to incorporate the certificate of the corresponding Certificate Authority into both the `/etc/ssl/certs/ca-certificates.crt` file and the `/opt/java/openjkd/jre/lib/security/cacerts` keystore on your Apache Guacamole host. This ensures that the self-signed certificate is trusted by both the system and the Java runtime environment used by Guacamole.
#### Adding Certificate Authority certificate as trusted in `/etc/ssl/certs/ca-certificates.crt`
:::note
This section depends on the operating system hosting Apache Guacamole.
:::
##### For _Debian_ based operating systems:
1. Copy the certificate of the Certificate Authority (e.g. `<CA_certificate>.crt`) to the `/usr/local/share/ca-certificates/` directory on the Apache Guacamole host. Ensure that the file extension is `.crt`.
2. To add the certificate as trusted in `/etc/ssl/certs/ca-certificates.crt`, use the following command:
```shell
update-ca-certificates
```
##### For _Synology_ systems:
1. Copy the certificate of the Certificate Authority (e.g. `<CA_certificate>.crt`) to the `/usr/syno/etc/security-profile/ca-bundle-profile/ca-certificates/` directory on the Synology host. Ensure that the filetype is `.crt`.
2. To add the certificate as trusted in `/etc/ssl/certs/ca-certificates.crt`, use the following command:
```shell
update-ca-certificates.sh
```
#### Adding Certificate Authority certificate to `/opt/java/openjkd/jre/lib/security/cacerts`
1. To export the certificate of the Certificate Authority, use the following command on the Certificate Authority host:
```shell
openssl pkcs12 -export -in <CA_certificate>.crt -inkey <CA_certificate>.key -out <CA_certificate>.p12 -passout pass:<password>
```
2. To import the certificate to the `/opt/java/openjdk/jre/lib/security/cacerts` keystore on the Apache Guacamole host, use the following command:
```shell
keytool -importkeystore -srckeystore <CA_certificate>.p12 -srcstoretype PKCS12 -keystore /opt/java/openjdk/jre/lib/security/cacerts -deststorepass <destination_store_password> -nopromt -srcstorepass <password>
```
:::note
More information on the keytool command can be found in the [Oracle documentation.](https://docs.oracle.com/en/java/javase/21/docs/specs/man/keytool.html)
:::
## Resources
- [Apache Guacamole official documentation on OpenID Connect integrations](https://guacamole.apache.org/doc/gug/openid-auth.html#configuring-guacamole-for-single-sign-on-with-openid-connect)
## Configuration verification
To verify that authentik is correctly configured with Apache Guacamole, log out and log back in through authentik. You should notice a new button appearing at the bottom left of the login page.

View File

@ -46,6 +46,80 @@ Using the authentik Admin interface, navigate to **Directory** -> **Groups** and
After creating the groups, select a group, navigate to the **Users** tab, and manage its members by using the **Add existing user** and **Create user** buttons as needed.
## Terraform provider
```hcl
data "authentik_flow" "default-provider-authorization-implicit-consent" {
slug = "default-provider-authorization-implicit-consent"
}
data "authentik_flow" "default-provider-invalidation" {
slug = "default-invalidation-flow"
}
data "authentik_property_mapping_provider_scope" "scope-email" {
name = "authentik default OAuth Mapping: OpenID 'email'"
}
data "authentik_property_mapping_provider_scope" "scope-profile" {
name = "authentik default OAuth Mapping: OpenID 'profile'"
}
data "authentik_property_mapping_provider_scope" "scope-openid" {
name = "authentik default OAuth Mapping: OpenID 'openid'"
}
data "authentik_certificate_key_pair" "generated" {
name = "authentik Self-signed Certificate"
}
resource "authentik_provider_oauth2" "argocd" {
name = "ArgoCD"
# Required. You can use the output of:
# $ openssl rand -hex 16
client_id = "my_client_id"
# Optional: will be generated if not provided
# client_secret = "my_client_secret"
authorization_flow = data.authentik_flow.default-provider-authorization-implicit_consent.id
invalidation_flow = data.authentik_flow.default-provider-invalidation.id
signing_key = data.authentik_certificate_key_pair.generated.id
allowed_redirect_uris = [
{
matching_mode = "strict",
url = "https://argocd.company/api/dex/callback",
},
{
matching_mode = "strict",
url = "http://localhost:8085/auth/callback",
}
]
property_mappings = [
data.authentik_property_mapping_provider_scope.scope-email.id,
data.authentik_property_mapping_provider_scope.scope-profile.id,
data.authentik_property_mapping_provider_scope.scope-openid.id,
]
}
resource "authentik_application" "argocd" {
name = "ArgoCD"
slug = "argocd"
protocol_provider = authentik_provider_oauth2.argocd.id
}
resource "authentik_group" "argocd_admins" {
name = "ArgoCD Admins"
}
resource "authentik_group" "argocd_viewers" {
name = "ArgoCD Viewers"
}
```
## ArgoCD Configuration
:::note

View File

@ -16,6 +16,7 @@ The following placeholders are used in this guide:
- `arubaorchestrator.company` is the FQDN of the Aruba Orchestrator installation.
- `authentik.company` is the FQDN of the authentik installation.
- `SSL Certificate` is the name of the SSL certificate used to sign outgoing responses.
:::note
This documentation lists only the settings that you need to change from their default values. Be aware that any changes other than those explicitly mentioned in this guide could cause issues accessing your application.

Some files were not shown because too many files have changed in this diff Show More