Compare commits
54 Commits
dependabot
...
revert-rev
Author | SHA1 | Date | |
---|---|---|---|
de1ec20d7a | |||
430678326d | |||
8fb7b5160d | |||
14a6430e21 | |||
7c32fc8c17 | |||
ed0a9d6a0a | |||
53143e0c40 | |||
178e010ed4 | |||
49b666fbde | |||
c343e3a7f4 | |||
5febf3ce5b | |||
b8c5bd678b | |||
4dd5eccbaa | |||
2410884006 | |||
3cb921b0f9 | |||
535f92981f | |||
955d69d5b7 | |||
fb01d8e96a | |||
6d39efd3e3 | |||
3020c31bcd | |||
22412729e2 | |||
a02868a27d | |||
bfbb4a8ebc | |||
6c0e827677 | |||
29884cbf81 | |||
0f02985b0c | |||
2244e026c2 | |||
429c03021c | |||
f47e8d9d72 | |||
3e7d2587c4 | |||
55a38d4a36 | |||
6021bb932d | |||
54a5d95717 | |||
a0a1275452 | |||
919aa5df59 | |||
cedf7cf683 | |||
cbc5a1c39d | |||
5f6b69c998 | |||
cf065db3d5 | |||
86c65325ce | |||
2b8e10e979 | |||
9298807275 | |||
ed56d6ac50 | |||
8c07b385ad | |||
880db7a86c | |||
99c1250ba5 | |||
5ce126ac83 | |||
dfa21d0725 | |||
e7e4af3894 | |||
931d6ec579 | |||
ff45acb25c | |||
c96557ff2d | |||
734feac4ae | |||
b17a9ed145 |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2025.2.4
|
||||
current_version = 2025.4.0
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
||||
|
13
.github/workflows/ci-main.yml
vendored
13
.github/workflows/ci-main.yml
vendored
@ -70,22 +70,18 @@ jobs:
|
||||
- name: checkout stable
|
||||
run: |
|
||||
# Copy current, latest config to local
|
||||
# Temporarly comment the .github backup while migrating to uv
|
||||
cp authentik/lib/default.yml local.env.yml
|
||||
# cp -R .github ..
|
||||
cp -R .github ..
|
||||
cp -R scripts ..
|
||||
git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1)
|
||||
# rm -rf .github/ scripts/
|
||||
# mv ../.github ../scripts .
|
||||
rm -rf scripts/
|
||||
mv ../scripts .
|
||||
rm -rf .github/ scripts/
|
||||
mv ../.github ../scripts .
|
||||
- name: Setup authentik env (stable)
|
||||
uses: ./.github/actions/setup
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
continue-on-error: true
|
||||
- name: run migrations to stable
|
||||
run: poetry run python -m lifecycle.migrate
|
||||
run: uv run python -m lifecycle.migrate
|
||||
- name: checkout current code
|
||||
run: |
|
||||
set -x
|
||||
@ -232,7 +228,6 @@ jobs:
|
||||
needs:
|
||||
- lint
|
||||
- test-migrations
|
||||
- test-migrations-from-stable
|
||||
- test-unittest
|
||||
- test-integration
|
||||
- test-e2e
|
||||
|
@ -40,7 +40,8 @@ COPY ./web /work/web/
|
||||
COPY ./website /work/website/
|
||||
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
||||
|
||||
RUN npm run build
|
||||
RUN npm run build && \
|
||||
npm run build:sfe
|
||||
|
||||
# Stage 3: Build go proxy
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
|
||||
|
@ -20,8 +20,8 @@ Even if the issue is not a CVE, we still greatly appreciate your help in hardeni
|
||||
|
||||
| Version | Supported |
|
||||
| --------- | --------- |
|
||||
| 2024.12.x | ✅ |
|
||||
| 2025.2.x | ✅ |
|
||||
| 2025.4.x | ✅ |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from os import environ
|
||||
|
||||
__version__ = "2025.2.4"
|
||||
__version__ = "2025.4.0"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ def migrate_custom_css(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
if not path.exists():
|
||||
return
|
||||
css = path.read_text()
|
||||
Brand.objects.using(db_alias).update(branding_custom_css=css)
|
||||
Brand.objects.using(db_alias).all().update(branding_custom_css=css)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -99,18 +99,17 @@ class GroupSerializer(ModelSerializer):
|
||||
if superuser
|
||||
else "authentik_core.disable_group_superuser"
|
||||
)
|
||||
has_perm = user.has_perm(perm)
|
||||
if self.instance and not has_perm:
|
||||
has_perm = user.has_perm(perm, self.instance)
|
||||
if not has_perm:
|
||||
raise ValidationError(
|
||||
_(
|
||||
(
|
||||
"User does not have permission to set "
|
||||
"superuser status to {superuser_status}."
|
||||
).format_map({"superuser_status": superuser})
|
||||
if self.instance or superuser:
|
||||
has_perm = user.has_perm(perm) or user.has_perm(perm, self.instance)
|
||||
if not has_perm:
|
||||
raise ValidationError(
|
||||
_(
|
||||
(
|
||||
"User does not have permission to set "
|
||||
"superuser status to {superuser_status}."
|
||||
).format_map({"superuser_status": superuser})
|
||||
)
|
||||
)
|
||||
)
|
||||
return superuser
|
||||
|
||||
class Meta:
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
from django.apps import apps
|
||||
from django.contrib.auth.management import create_permissions
|
||||
from django.core.management import call_command
|
||||
from django.core.management.base import BaseCommand, no_translations
|
||||
from guardian.management import create_anonymous_user
|
||||
|
||||
@ -16,6 +17,10 @@ class Command(BaseCommand):
|
||||
"""Check permissions for all apps"""
|
||||
for tenant in Tenant.objects.filter(ready=True):
|
||||
with tenant:
|
||||
# See https://code.djangoproject.com/ticket/28417
|
||||
# Remove potential lingering old permissions
|
||||
call_command("remove_stale_contenttypes", "--no-input")
|
||||
|
||||
for app in apps.get_app_configs():
|
||||
self.stdout.write(f"Checking app {app.name} ({app.label})\n")
|
||||
create_permissions(app, verbosity=0)
|
||||
|
@ -31,7 +31,10 @@ class PickleSerializer:
|
||||
|
||||
def loads(self, data):
|
||||
"""Unpickle data to be loaded from redis"""
|
||||
return pickle.loads(data) # nosec
|
||||
try:
|
||||
return pickle.loads(data) # nosec
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
|
||||
def _migrate_session(
|
||||
|
@ -0,0 +1,27 @@
|
||||
# Generated by Django 5.1.9 on 2025-05-14 11:15
|
||||
|
||||
from django.apps.registry import Apps
|
||||
from django.db import migrations
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
|
||||
|
||||
def remove_old_authenticated_session_content_type(
|
||||
apps: Apps, schema_editor: BaseDatabaseSchemaEditor
|
||||
):
|
||||
db_alias = schema_editor.connection.alias
|
||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||
|
||||
ContentType.objects.using(db_alias).filter(model="oldauthenticatedsession").delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_core", "0047_delete_oldauthenticatedsession"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
code=remove_old_authenticated_session_content_type,
|
||||
),
|
||||
]
|
@ -124,6 +124,16 @@ class TestGroupsAPI(APITestCase):
|
||||
{"is_superuser": ["User does not have permission to set superuser status to True."]},
|
||||
)
|
||||
|
||||
def test_superuser_no_perm_no_superuser(self):
|
||||
"""Test creating a group without permission and without superuser flag"""
|
||||
assign_perm("authentik_core.add_group", self.login_user)
|
||||
self.client.force_login(self.login_user)
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:group-list"),
|
||||
data={"name": generate_id(), "is_superuser": False},
|
||||
)
|
||||
self.assertEqual(res.status_code, 201)
|
||||
|
||||
def test_superuser_update_no_perm(self):
|
||||
"""Test updating a superuser group without permission"""
|
||||
group = Group.objects.create(name=generate_id(), is_superuser=True)
|
||||
|
@ -132,13 +132,14 @@ class LicenseKey:
|
||||
"""Get a summarized version of all (not expired) licenses"""
|
||||
total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0)
|
||||
for lic in License.objects.all():
|
||||
total.internal_users += lic.internal_users
|
||||
total.external_users += lic.external_users
|
||||
if lic.is_valid:
|
||||
total.internal_users += lic.internal_users
|
||||
total.external_users += lic.external_users
|
||||
total.license_flags.extend(lic.status.license_flags)
|
||||
exp_ts = int(mktime(lic.expiry.timetuple()))
|
||||
if total.exp == 0:
|
||||
total.exp = exp_ts
|
||||
total.exp = max(total.exp, exp_ts)
|
||||
total.license_flags.extend(lic.status.license_flags)
|
||||
return total
|
||||
|
||||
@staticmethod
|
||||
|
@ -39,6 +39,10 @@ class License(SerializerModel):
|
||||
internal_users = models.BigIntegerField()
|
||||
external_users = models.BigIntegerField()
|
||||
|
||||
@property
|
||||
def is_valid(self) -> bool:
|
||||
return self.expiry >= now()
|
||||
|
||||
@property
|
||||
def serializer(self) -> type[BaseSerializer]:
|
||||
from authentik.enterprise.api import LicenseSerializer
|
||||
|
@ -8,6 +8,7 @@ from django.test import TestCase
|
||||
from django.utils.timezone import now
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
from authentik.enterprise.models import (
|
||||
THRESHOLD_READ_ONLY_WEEKS,
|
||||
@ -71,9 +72,9 @@ class TestEnterpriseLicense(TestCase):
|
||||
)
|
||||
def test_valid_multiple(self):
|
||||
"""Check license verification"""
|
||||
lic = License.objects.create(key=generate_id())
|
||||
lic = License.objects.create(key=generate_id(), expiry=expiry_valid)
|
||||
self.assertTrue(lic.status.status().is_valid)
|
||||
lic2 = License.objects.create(key=generate_id())
|
||||
lic2 = License.objects.create(key=generate_id(), expiry=expiry_valid)
|
||||
self.assertTrue(lic2.status.status().is_valid)
|
||||
total = LicenseKey.get_total()
|
||||
self.assertEqual(total.internal_users, 200)
|
||||
@ -232,7 +233,9 @@ class TestEnterpriseLicense(TestCase):
|
||||
)
|
||||
def test_expiry_expired(self):
|
||||
"""Check license verification"""
|
||||
License.objects.create(key=generate_id())
|
||||
User.objects.all().delete()
|
||||
License.objects.all().delete()
|
||||
License.objects.create(key=generate_id(), expiry=expiry_expired)
|
||||
self.assertEqual(LicenseKey.get_total().summary().status, LicenseUsageStatus.EXPIRED)
|
||||
|
||||
@patch(
|
||||
|
@ -15,6 +15,7 @@
|
||||
{% endblock %}
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}">
|
||||
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
||||
<link rel="prefetch" href="{{ flow_background_url }}" />
|
||||
{% include "base/header_js.html" %}
|
||||
<style>
|
||||
html,
|
||||
@ -22,7 +23,7 @@
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
background-image: url("{{ flow.background_url }}");
|
||||
background-image: url("{{ flow_background_url }}");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
{% block head_before %}
|
||||
{{ block.super }}
|
||||
<link rel="prefetch" href="{{ flow.background_url }}" />
|
||||
<link rel="prefetch" href="{{ flow_background_url }}" />
|
||||
{% if flow.compatibility_mode and not inspector %}
|
||||
<script>ShadyDOM = { force: !navigator.webdriver };</script>
|
||||
{% endif %}
|
||||
@ -21,7 +21,7 @@ window.authentik.flow = {
|
||||
<script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script>
|
||||
<style>
|
||||
:root {
|
||||
--ak-flow-background: url("{{ flow.background_url }}");
|
||||
--ak-flow-background: url("{{ flow_background_url }}");
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
@ -69,6 +69,7 @@ SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre"
|
||||
SESSION_KEY_GET = "authentik/flows/get"
|
||||
SESSION_KEY_POST = "authentik/flows/post"
|
||||
SESSION_KEY_HISTORY = "authentik/flows/history"
|
||||
SESSION_KEY_AUTH_STARTED = "authentik/flows/auth_started"
|
||||
QS_KEY_TOKEN = "flow_token" # nosec
|
||||
QS_QUERY = "query"
|
||||
|
||||
@ -453,6 +454,7 @@ class FlowExecutorView(APIView):
|
||||
SESSION_KEY_APPLICATION_PRE,
|
||||
SESSION_KEY_PLAN,
|
||||
SESSION_KEY_GET,
|
||||
SESSION_KEY_AUTH_STARTED,
|
||||
# We might need the initial POST payloads for later requests
|
||||
# SESSION_KEY_POST,
|
||||
# We don't delete the history on purpose, as a user might
|
||||
|
@ -6,14 +6,23 @@ from django.shortcuts import get_object_or_404
|
||||
from ua_parser.user_agent_parser import Parse
|
||||
|
||||
from authentik.core.views.interface import InterfaceView
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.flows.models import Flow, FlowDesignation
|
||||
from authentik.flows.views.executor import SESSION_KEY_AUTH_STARTED
|
||||
|
||||
|
||||
class FlowInterfaceView(InterfaceView):
|
||||
"""Flow interface"""
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
kwargs["flow"] = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
|
||||
flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
|
||||
if (
|
||||
not self.request.user.is_authenticated
|
||||
and flow.designation == FlowDesignation.AUTHENTICATION
|
||||
):
|
||||
self.request.session[SESSION_KEY_AUTH_STARTED] = True
|
||||
self.request.session.save()
|
||||
kwargs["flow"] = flow
|
||||
kwargs["flow_background_url"] = flow.background_url(self.request)
|
||||
kwargs["inspector"] = "inspector" in self.request.GET
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
@ -363,6 +363,9 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
|
||||
pool_options = config.get_dict_from_b64_json("postgresql.pool_options", True)
|
||||
if not pool_options:
|
||||
pool_options = True
|
||||
# FIXME: Temporarily force pool to be deactivated.
|
||||
# See https://github.com/goauthentik/authentik/issues/14320
|
||||
pool_options = False
|
||||
|
||||
db = {
|
||||
"default": {
|
||||
|
@ -494,86 +494,88 @@ 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,
|
||||
}
|
||||
},
|
||||
)
|
||||
# FIXME: Temporarily force pool to be deactivated.
|
||||
# See https://github.com/goauthentik/authentik/issues/14320
|
||||
# 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,
|
||||
}
|
||||
},
|
||||
)
|
||||
# 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,
|
||||
# }
|
||||
# },
|
||||
# )
|
||||
|
@ -39,3 +39,4 @@ class AuthentikPoliciesConfig(ManagedAppConfig):
|
||||
label = "authentik_policies"
|
||||
verbose_name = "authentik Policies"
|
||||
default = True
|
||||
mountpoint = "policy/"
|
||||
|
89
authentik/policies/templates/policies/buffer.html
Normal file
89
authentik/policies/templates/policies/buffer.html
Normal file
@ -0,0 +1,89 @@
|
||||
{% extends 'login/base_full.html' %}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block head %}
|
||||
{{ block.super }}
|
||||
<script>
|
||||
let redirecting = false;
|
||||
const checkAuth = async () => {
|
||||
if (redirecting) return true;
|
||||
const url = "{{ check_auth_url }}";
|
||||
console.debug("authentik/policies/buffer: Checking authentication...");
|
||||
try {
|
||||
const result = await fetch(url, {
|
||||
method: "HEAD",
|
||||
});
|
||||
if (result.status >= 400) {
|
||||
return false
|
||||
}
|
||||
console.debug("authentik/policies/buffer: Continuing");
|
||||
redirecting = true;
|
||||
if ("{{ auth_req_method }}" === "post") {
|
||||
document.querySelector("form").submit();
|
||||
} else {
|
||||
window.location.assign("{{ continue_url|escapejs }}");
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let timeout = 100;
|
||||
let offset = 20;
|
||||
let attempt = 0;
|
||||
const main = async () => {
|
||||
attempt += 1;
|
||||
await checkAuth();
|
||||
console.debug(`authentik/policies/buffer: Waiting ${timeout}ms...`);
|
||||
setTimeout(main, timeout);
|
||||
timeout += (offset * attempt);
|
||||
if (timeout >= 2000) {
|
||||
timeout = 2000;
|
||||
}
|
||||
}
|
||||
document.addEventListener("visibilitychange", async () => {
|
||||
if (document.hidden) return;
|
||||
console.debug("authentik/policies/buffer: Checking authentication on tab activate...");
|
||||
await checkAuth();
|
||||
});
|
||||
main();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
{% trans 'Waiting for authentication...' %} - {{ brand.branding_title }}
|
||||
{% endblock %}
|
||||
|
||||
{% block card_title %}
|
||||
{% trans 'Waiting for authentication...' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block card %}
|
||||
<form class="pf-c-form" method="{{ auth_req_method }}" action="{{ continue_url }}">
|
||||
{% if auth_req_method == "post" %}
|
||||
{% for key, value in auth_req_body.items %}
|
||||
<input type="hidden" name="{{ key }}" value="{{ value }}" />
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<div class="pf-c-empty-state">
|
||||
<div class="pf-c-empty-state__content">
|
||||
<div class="pf-c-empty-state__icon">
|
||||
<span class="pf-c-spinner pf-m-xl" role="progressbar">
|
||||
<span class="pf-c-spinner__clipper"></span>
|
||||
<span class="pf-c-spinner__lead-ball"></span>
|
||||
<span class="pf-c-spinner__tail-ball"></span>
|
||||
</span>
|
||||
</div>
|
||||
<h1 class="pf-c-title pf-m-lg">
|
||||
{% trans "You're already authenticating in another tab. This page will refresh once authentication is completed." %}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pf-c-form__group pf-m-action">
|
||||
<a href="{{ auth_req_url }}" class="pf-c-button pf-m-primary pf-m-block">
|
||||
{% trans "Authenticate in this tab" %}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
121
authentik/policies/tests/test_views.py
Normal file
121
authentik/policies/tests/test_views.py
Normal file
@ -0,0 +1,121 @@
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.http import HttpResponse
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik.core.models import Application, Provider
|
||||
from authentik.core.tests.utils import create_test_flow, create_test_user
|
||||
from authentik.flows.models import FlowDesignation
|
||||
from authentik.flows.planner import FlowPlan
|
||||
from authentik.flows.views.executor import SESSION_KEY_PLAN
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.lib.tests.utils import dummy_get_response
|
||||
from authentik.policies.views import (
|
||||
QS_BUFFER_ID,
|
||||
SESSION_KEY_BUFFER,
|
||||
BufferedPolicyAccessView,
|
||||
BufferView,
|
||||
PolicyAccessView,
|
||||
)
|
||||
|
||||
|
||||
class TestPolicyViews(TestCase):
|
||||
"""Test PolicyAccessView"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.factory = RequestFactory()
|
||||
self.user = create_test_user()
|
||||
|
||||
def test_pav(self):
|
||||
"""Test simple policy access view"""
|
||||
provider = Provider.objects.create(
|
||||
name=generate_id(),
|
||||
)
|
||||
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
|
||||
|
||||
class TestView(PolicyAccessView):
|
||||
def resolve_provider_application(self):
|
||||
self.provider = provider
|
||||
self.application = app
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
return HttpResponse("foo")
|
||||
|
||||
req = self.factory.get("/")
|
||||
req.user = self.user
|
||||
res = TestView.as_view()(req)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertEqual(res.content, b"foo")
|
||||
|
||||
def test_pav_buffer(self):
|
||||
"""Test simple policy access view"""
|
||||
provider = Provider.objects.create(
|
||||
name=generate_id(),
|
||||
)
|
||||
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
|
||||
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
|
||||
|
||||
class TestView(BufferedPolicyAccessView):
|
||||
def resolve_provider_application(self):
|
||||
self.provider = provider
|
||||
self.application = app
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
return HttpResponse("foo")
|
||||
|
||||
req = self.factory.get("/")
|
||||
req.user = AnonymousUser()
|
||||
middleware = SessionMiddleware(dummy_get_response)
|
||||
middleware.process_request(req)
|
||||
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
|
||||
req.session.save()
|
||||
res = TestView.as_view()(req)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertTrue(res.url.startswith(reverse("authentik_policies:buffer")))
|
||||
|
||||
def test_pav_buffer_skip(self):
|
||||
"""Test simple policy access view (skip buffer)"""
|
||||
provider = Provider.objects.create(
|
||||
name=generate_id(),
|
||||
)
|
||||
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
|
||||
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
|
||||
|
||||
class TestView(BufferedPolicyAccessView):
|
||||
def resolve_provider_application(self):
|
||||
self.provider = provider
|
||||
self.application = app
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
return HttpResponse("foo")
|
||||
|
||||
req = self.factory.get("/?skip_buffer=true")
|
||||
req.user = AnonymousUser()
|
||||
middleware = SessionMiddleware(dummy_get_response)
|
||||
middleware.process_request(req)
|
||||
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
|
||||
req.session.save()
|
||||
res = TestView.as_view()(req)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertTrue(res.url.startswith(reverse("authentik_flows:default-authentication")))
|
||||
|
||||
def test_buffer(self):
|
||||
"""Test buffer view"""
|
||||
uid = generate_id()
|
||||
req = self.factory.get(f"/?{QS_BUFFER_ID}={uid}")
|
||||
req.user = AnonymousUser()
|
||||
middleware = SessionMiddleware(dummy_get_response)
|
||||
middleware.process_request(req)
|
||||
ts = generate_id()
|
||||
req.session[SESSION_KEY_BUFFER % uid] = {
|
||||
"method": "get",
|
||||
"body": {},
|
||||
"url": f"/{ts}",
|
||||
}
|
||||
req.session.save()
|
||||
|
||||
res = BufferView.as_view()(req)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertIn(ts, res.render().content.decode())
|
@ -1,7 +1,14 @@
|
||||
"""API URLs"""
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from authentik.policies.api.bindings import PolicyBindingViewSet
|
||||
from authentik.policies.api.policies import PolicyViewSet
|
||||
from authentik.policies.views import BufferView
|
||||
|
||||
urlpatterns = [
|
||||
path("buffer", BufferView.as_view(), name="buffer"),
|
||||
]
|
||||
|
||||
api_urlpatterns = [
|
||||
("policies/all", PolicyViewSet),
|
||||
|
@ -1,23 +1,37 @@
|
||||
"""authentik access helper classes"""
|
||||
|
||||
from typing import Any
|
||||
from uuid import uuid4
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import AccessMixin
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.http import HttpRequest, HttpResponse, QueryDict
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic.base import View
|
||||
from django.views.generic.base import TemplateView, View
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.models import Application, Provider, User
|
||||
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_POST
|
||||
from authentik.flows.models import Flow, FlowDesignation
|
||||
from authentik.flows.planner import FlowPlan
|
||||
from authentik.flows.views.executor import (
|
||||
SESSION_KEY_APPLICATION_PRE,
|
||||
SESSION_KEY_AUTH_STARTED,
|
||||
SESSION_KEY_PLAN,
|
||||
SESSION_KEY_POST,
|
||||
)
|
||||
from authentik.lib.sentry import SentryIgnoredException
|
||||
from authentik.policies.denied import AccessDeniedResponse
|
||||
from authentik.policies.engine import PolicyEngine
|
||||
from authentik.policies.types import PolicyRequest, PolicyResult
|
||||
|
||||
LOGGER = get_logger()
|
||||
QS_BUFFER_ID = "af_bf_id"
|
||||
QS_SKIP_BUFFER = "skip_buffer"
|
||||
SESSION_KEY_BUFFER = "authentik/policies/pav_buffer/%s"
|
||||
|
||||
|
||||
class RequestValidationError(SentryIgnoredException):
|
||||
@ -125,3 +139,65 @@ class PolicyAccessView(AccessMixin, View):
|
||||
for message in result.messages:
|
||||
messages.error(self.request, _(message))
|
||||
return result
|
||||
|
||||
|
||||
def url_with_qs(url: str, **kwargs):
|
||||
"""Update/set querystring of `url` with the parameters in `kwargs`. Original query string
|
||||
parameters are retained"""
|
||||
if "?" not in url:
|
||||
return url + f"?{urlencode(kwargs)}"
|
||||
url, _, qs = url.partition("?")
|
||||
qs = QueryDict(qs, mutable=True)
|
||||
qs.update(kwargs)
|
||||
return url + f"?{urlencode(qs.items())}"
|
||||
|
||||
|
||||
class BufferView(TemplateView):
|
||||
"""Buffer view"""
|
||||
|
||||
template_name = "policies/buffer.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
buf_id = self.request.GET.get(QS_BUFFER_ID)
|
||||
buffer: dict = self.request.session.get(SESSION_KEY_BUFFER % buf_id)
|
||||
kwargs["auth_req_method"] = buffer["method"]
|
||||
kwargs["auth_req_body"] = buffer["body"]
|
||||
kwargs["auth_req_url"] = url_with_qs(buffer["url"], **{QS_SKIP_BUFFER: True})
|
||||
kwargs["check_auth_url"] = reverse("authentik_api:user-me")
|
||||
kwargs["continue_url"] = url_with_qs(buffer["url"], **{QS_BUFFER_ID: buf_id})
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
class BufferedPolicyAccessView(PolicyAccessView):
|
||||
"""PolicyAccessView which buffers access requests in case the user is not logged in"""
|
||||
|
||||
def handle_no_permission(self):
|
||||
plan: FlowPlan | None = self.request.session.get(SESSION_KEY_PLAN)
|
||||
authenticating = self.request.session.get(SESSION_KEY_AUTH_STARTED)
|
||||
if plan:
|
||||
flow = Flow.objects.filter(pk=plan.flow_pk).first()
|
||||
if not flow or flow.designation != FlowDesignation.AUTHENTICATION:
|
||||
LOGGER.debug("Not buffering request, no flow or flow not for authentication")
|
||||
return super().handle_no_permission()
|
||||
if not plan and authenticating is None:
|
||||
LOGGER.debug("Not buffering request, no flow plan active")
|
||||
return super().handle_no_permission()
|
||||
if self.request.GET.get(QS_SKIP_BUFFER):
|
||||
LOGGER.debug("Not buffering request, explicit skip")
|
||||
return super().handle_no_permission()
|
||||
buffer_id = str(uuid4())
|
||||
LOGGER.debug("Buffering access request", bf_id=buffer_id)
|
||||
self.request.session[SESSION_KEY_BUFFER % buffer_id] = {
|
||||
"body": self.request.POST,
|
||||
"url": self.request.build_absolute_uri(self.request.get_full_path()),
|
||||
"method": self.request.method.lower(),
|
||||
}
|
||||
return redirect(
|
||||
url_with_qs(reverse("authentik_policies:buffer"), **{QS_BUFFER_ID: buffer_id})
|
||||
)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
response = super().dispatch(request, *args, **kwargs)
|
||||
if QS_BUFFER_ID in self.request.GET:
|
||||
self.request.session.pop(SESSION_KEY_BUFFER % self.request.GET[QS_BUFFER_ID], None)
|
||||
return response
|
||||
|
@ -30,7 +30,7 @@ from authentik.flows.stage import StageView
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.lib.views import bad_request_message
|
||||
from authentik.policies.types import PolicyRequest
|
||||
from authentik.policies.views import PolicyAccessView, RequestValidationError
|
||||
from authentik.policies.views import BufferedPolicyAccessView, RequestValidationError
|
||||
from authentik.providers.oauth2.constants import (
|
||||
PKCE_METHOD_PLAIN,
|
||||
PKCE_METHOD_S256,
|
||||
@ -326,7 +326,7 @@ class OAuthAuthorizationParams:
|
||||
return code
|
||||
|
||||
|
||||
class AuthorizationFlowInitView(PolicyAccessView):
|
||||
class AuthorizationFlowInitView(BufferedPolicyAccessView):
|
||||
"""OAuth2 Flow initializer, checks access to application and starts flow"""
|
||||
|
||||
params: OAuthAuthorizationParams
|
||||
|
@ -18,11 +18,11 @@ from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner
|
||||
from authentik.flows.stage import RedirectStage
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.policies.engine import PolicyEngine
|
||||
from authentik.policies.views import PolicyAccessView
|
||||
from authentik.policies.views import BufferedPolicyAccessView
|
||||
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
|
||||
|
||||
|
||||
class RACStartView(PolicyAccessView):
|
||||
class RACStartView(BufferedPolicyAccessView):
|
||||
"""Start a RAC connection by checking access and creating a connection token"""
|
||||
|
||||
endpoint: Endpoint
|
||||
|
@ -35,8 +35,8 @@ REQUEST_KEY_SAML_SIG_ALG = "SigAlg"
|
||||
REQUEST_KEY_SAML_RESPONSE = "SAMLResponse"
|
||||
REQUEST_KEY_RELAY_STATE = "RelayState"
|
||||
|
||||
SESSION_KEY_AUTH_N_REQUEST = "authentik/providers/saml/authn_request"
|
||||
SESSION_KEY_LOGOUT_REQUEST = "authentik/providers/saml/logout_request"
|
||||
PLAN_CONTEXT_SAML_AUTH_N_REQUEST = "authentik/providers/saml/authn_request"
|
||||
PLAN_CONTEXT_SAML_LOGOUT_REQUEST = "authentik/providers/saml/logout_request"
|
||||
|
||||
|
||||
# This View doesn't have a URL on purpose, as its called by the FlowExecutor
|
||||
@ -50,10 +50,11 @@ class SAMLFlowFinalView(ChallengeStageView):
|
||||
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
application: Application = self.executor.plan.context[PLAN_CONTEXT_APPLICATION]
|
||||
provider: SAMLProvider = get_object_or_404(SAMLProvider, pk=application.provider_id)
|
||||
if SESSION_KEY_AUTH_N_REQUEST not in self.request.session:
|
||||
if PLAN_CONTEXT_SAML_AUTH_N_REQUEST not in self.executor.plan.context:
|
||||
self.logger.warning("No AuthNRequest in context")
|
||||
return self.executor.stage_invalid()
|
||||
|
||||
auth_n_request: AuthNRequest = self.request.session.pop(SESSION_KEY_AUTH_N_REQUEST)
|
||||
auth_n_request: AuthNRequest = self.executor.plan.context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST]
|
||||
try:
|
||||
response = AssertionProcessor(provider, request, auth_n_request).build_response()
|
||||
except SAMLException as exc:
|
||||
@ -106,6 +107,3 @@ class SAMLFlowFinalView(ChallengeStageView):
|
||||
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
|
||||
# We'll never get here since the challenge redirects to the SP
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
def cleanup(self):
|
||||
self.request.session.pop(SESSION_KEY_AUTH_N_REQUEST, None)
|
||||
|
@ -19,9 +19,9 @@ from authentik.providers.saml.exceptions import CannotHandleAssertion
|
||||
from authentik.providers.saml.models import SAMLProvider
|
||||
from authentik.providers.saml.processors.logout_request_parser import LogoutRequestParser
|
||||
from authentik.providers.saml.views.flows import (
|
||||
PLAN_CONTEXT_SAML_LOGOUT_REQUEST,
|
||||
REQUEST_KEY_RELAY_STATE,
|
||||
REQUEST_KEY_SAML_REQUEST,
|
||||
SESSION_KEY_LOGOUT_REQUEST,
|
||||
)
|
||||
|
||||
LOGGER = get_logger()
|
||||
@ -33,6 +33,10 @@ class SAMLSLOView(PolicyAccessView):
|
||||
|
||||
flow: Flow
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.plan_context = {}
|
||||
|
||||
def resolve_provider_application(self):
|
||||
self.application = get_object_or_404(Application, slug=self.kwargs["application_slug"])
|
||||
self.provider: SAMLProvider = get_object_or_404(
|
||||
@ -59,6 +63,7 @@ class SAMLSLOView(PolicyAccessView):
|
||||
request,
|
||||
{
|
||||
PLAN_CONTEXT_APPLICATION: self.application,
|
||||
**self.plan_context,
|
||||
},
|
||||
)
|
||||
plan.append_stage(in_memory_stage(SessionEndStage))
|
||||
@ -83,7 +88,7 @@ class SAMLSLOBindingRedirectView(SAMLSLOView):
|
||||
self.request.GET[REQUEST_KEY_SAML_REQUEST],
|
||||
relay_state=self.request.GET.get(REQUEST_KEY_RELAY_STATE, None),
|
||||
)
|
||||
self.request.session[SESSION_KEY_LOGOUT_REQUEST] = logout_request
|
||||
self.plan_context[PLAN_CONTEXT_SAML_LOGOUT_REQUEST] = logout_request
|
||||
except CannotHandleAssertion as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
@ -111,7 +116,7 @@ class SAMLSLOBindingPOSTView(SAMLSLOView):
|
||||
payload[REQUEST_KEY_SAML_REQUEST],
|
||||
relay_state=payload.get(REQUEST_KEY_RELAY_STATE, None),
|
||||
)
|
||||
self.request.session[SESSION_KEY_LOGOUT_REQUEST] = logout_request
|
||||
self.plan_context[PLAN_CONTEXT_SAML_LOGOUT_REQUEST] = logout_request
|
||||
except CannotHandleAssertion as exc:
|
||||
LOGGER.info(str(exc))
|
||||
return bad_request_message(self.request, str(exc))
|
||||
|
@ -15,16 +15,16 @@ from authentik.flows.models import in_memory_stage
|
||||
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner
|
||||
from authentik.flows.views.executor import SESSION_KEY_POST
|
||||
from authentik.lib.views import bad_request_message
|
||||
from authentik.policies.views import PolicyAccessView
|
||||
from authentik.policies.views import BufferedPolicyAccessView
|
||||
from authentik.providers.saml.exceptions import CannotHandleAssertion
|
||||
from authentik.providers.saml.models import SAMLBindings, SAMLProvider
|
||||
from authentik.providers.saml.processors.authn_request_parser import AuthNRequestParser
|
||||
from authentik.providers.saml.views.flows import (
|
||||
PLAN_CONTEXT_SAML_AUTH_N_REQUEST,
|
||||
REQUEST_KEY_RELAY_STATE,
|
||||
REQUEST_KEY_SAML_REQUEST,
|
||||
REQUEST_KEY_SAML_SIG_ALG,
|
||||
REQUEST_KEY_SAML_SIGNATURE,
|
||||
SESSION_KEY_AUTH_N_REQUEST,
|
||||
SAMLFlowFinalView,
|
||||
)
|
||||
from authentik.stages.consent.stage import (
|
||||
@ -35,10 +35,14 @@ from authentik.stages.consent.stage import (
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
class SAMLSSOView(PolicyAccessView):
|
||||
class SAMLSSOView(BufferedPolicyAccessView):
|
||||
"""SAML SSO Base View, which plans a flow and injects our final stage.
|
||||
Calls get/post handler."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.plan_context = {}
|
||||
|
||||
def resolve_provider_application(self):
|
||||
self.application = get_object_or_404(Application, slug=self.kwargs["application_slug"])
|
||||
self.provider: SAMLProvider = get_object_or_404(
|
||||
@ -68,6 +72,7 @@ class SAMLSSOView(PolicyAccessView):
|
||||
PLAN_CONTEXT_CONSENT_HEADER: _("You're about to sign into %(application)s.")
|
||||
% {"application": self.application.name},
|
||||
PLAN_CONTEXT_CONSENT_PERMISSIONS: [],
|
||||
**self.plan_context,
|
||||
},
|
||||
)
|
||||
except FlowNonApplicableException:
|
||||
@ -83,7 +88,7 @@ class SAMLSSOView(PolicyAccessView):
|
||||
|
||||
def post(self, request: HttpRequest, application_slug: str) -> HttpResponse:
|
||||
"""GET and POST use the same handler, but we can't
|
||||
override .dispatch easily because PolicyAccessView's dispatch"""
|
||||
override .dispatch easily because BufferedPolicyAccessView's dispatch"""
|
||||
return self.get(request, application_slug)
|
||||
|
||||
|
||||
@ -103,7 +108,7 @@ class SAMLSSOBindingRedirectView(SAMLSSOView):
|
||||
self.request.GET.get(REQUEST_KEY_SAML_SIGNATURE),
|
||||
self.request.GET.get(REQUEST_KEY_SAML_SIG_ALG),
|
||||
)
|
||||
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request
|
||||
self.plan_context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST] = auth_n_request
|
||||
except CannotHandleAssertion as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
@ -137,7 +142,7 @@ class SAMLSSOBindingPOSTView(SAMLSSOView):
|
||||
payload[REQUEST_KEY_SAML_REQUEST],
|
||||
payload.get(REQUEST_KEY_RELAY_STATE),
|
||||
)
|
||||
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request
|
||||
self.plan_context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST] = auth_n_request
|
||||
except CannotHandleAssertion as exc:
|
||||
LOGGER.info(str(exc))
|
||||
return bad_request_message(self.request, str(exc))
|
||||
@ -151,4 +156,4 @@ class SAMLSSOBindingInitView(SAMLSSOView):
|
||||
"""Create SAML Response from scratch"""
|
||||
LOGGER.debug("No SAML Request, using IdP-initiated flow.")
|
||||
auth_n_request = AuthNRequestParser(self.provider).idp_initiated()
|
||||
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request
|
||||
self.plan_context[PLAN_CONTEXT_SAML_AUTH_N_REQUEST] = auth_n_request
|
||||
|
@ -99,6 +99,7 @@ class RBACPermissionViewSet(ReadOnlyModelViewSet):
|
||||
filterset_class = PermissionFilter
|
||||
permission_classes = [IsAuthenticated]
|
||||
search_fields = [
|
||||
"name",
|
||||
"codename",
|
||||
"content_type__model",
|
||||
"content_type__app_label",
|
||||
|
@ -2,7 +2,7 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"$id": "https://goauthentik.io/blueprints/schema.json",
|
||||
"type": "object",
|
||||
"title": "authentik 2025.2.4 Blueprint schema",
|
||||
"title": "authentik 2025.4.0 Blueprint schema",
|
||||
"required": [
|
||||
"version",
|
||||
"entries"
|
||||
|
@ -31,7 +31,7 @@ services:
|
||||
volumes:
|
||||
- redis:/data
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.0}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@ -55,7 +55,7 @@ services:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.0}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
|
@ -29,4 +29,4 @@ func UserAgent() string {
|
||||
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||
}
|
||||
|
||||
const VERSION = "2025.2.4"
|
||||
const VERSION = "2025.4.0"
|
||||
|
@ -56,6 +56,7 @@ EXPOSE 3389 6636 9300
|
||||
|
||||
USER 1000
|
||||
|
||||
ENV GOFIPS=1
|
||||
ENV TMPDIR=/dev/shm/ \
|
||||
GOFIPS=1
|
||||
|
||||
ENTRYPOINT ["/ldap"]
|
||||
|
@ -62,7 +62,8 @@ function prepare_debug {
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends krb5-kdc krb5-user krb5-admin-server libkrb5-dev gcc
|
||||
VIRTUAL_ENV=/ak-root/.venv uv sync --frozen
|
||||
source "${VENV_PATH}/bin/activate"
|
||||
uv sync --active --frozen
|
||||
touch /unittest.xml
|
||||
chown authentik:authentik /unittest.xml
|
||||
}
|
||||
@ -96,6 +97,7 @@ elif [[ "$1" == "test-all" ]]; then
|
||||
elif [[ "$1" == "healthcheck" ]]; then
|
||||
run_authentik healthcheck $(cat $MODE_FILE)
|
||||
elif [[ "$1" == "dump_config" ]]; then
|
||||
shift
|
||||
exec python -m authentik.lib.config $@
|
||||
elif [[ "$1" == "debug" ]]; then
|
||||
exec sleep infinity
|
||||
|
@ -26,7 +26,7 @@ Parameters:
|
||||
Description: authentik Docker image
|
||||
AuthentikVersion:
|
||||
Type: String
|
||||
Default: 2025.2.4
|
||||
Default: 2025.4.0
|
||||
Description: authentik Docker image tag
|
||||
AuthentikServerCPU:
|
||||
Type: Number
|
||||
|
Binary file not shown.
@ -8,7 +8,6 @@
|
||||
# Jens L. <jens@goauthentik.io>, 2022
|
||||
# Lars Lehmann <lars@lars-lehmann.net>, 2023
|
||||
# Johannes —/—, 2023
|
||||
# Dominic Wagner <mail@dominic-wagner.de>, 2023
|
||||
# fde4f289d99ed356ff5cfdb762dc44aa_a8a971d, 2023
|
||||
# Christian Foellmann <foellmann@foe-services.de>, 2023
|
||||
# kidhab, 2023
|
||||
@ -30,17 +29,18 @@
|
||||
# Alexander Möbius, 2025
|
||||
# Jonas, 2025
|
||||
# Niklas Kroese, 2025
|
||||
# 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025
|
||||
# datenschmutz, 2025
|
||||
# 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025
|
||||
# Dominic Wagner <mail@dominic-wagner.de>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: datenschmutz, 2025\n"
|
||||
"Last-Translator: Dominic Wagner <mail@dominic-wagner.de>, 2025\n"
|
||||
"Language-Team: German (https://app.transifex.com/authentik/teams/119923/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -214,6 +214,7 @@ msgid "User's display name."
|
||||
msgstr "Anzeigename"
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "Benutzer"
|
||||
|
||||
@ -402,6 +403,18 @@ msgstr "Eigenschaft"
|
||||
msgid "Property Mappings"
|
||||
msgstr "Eigenschaften"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
msgstr "Sitzung"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Sessions"
|
||||
msgstr "Sitzungen"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Authenticated Session"
|
||||
msgstr "Authentifizierte Sitzung"
|
||||
@ -511,6 +524,38 @@ msgstr "Lizenzverwendung"
|
||||
msgid "License Usage Records"
|
||||
msgstr "Lizenzverwendung Aufzeichnungen"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Zu prüfender Feldschlüssel, die in den Aufforderungsstufen definierten "
|
||||
"Feldschlüssel sind verfügbar."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Passwort nicht im Kontext festgelegt"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "This password has been used previously. Please choose a different one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr "Enterprise ist erforderlich, um auf diese Funktion zuzugreifen."
|
||||
@ -1303,12 +1348,6 @@ msgstr "Richtlinien Cache Metriken anzeigen"
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr "Richtlinien Cache Metriken löschen"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Zu prüfender Feldschlüssel, die in den Aufforderungsstufen definierten "
|
||||
"Feldschlüssel sind verfügbar."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr "Wie häufig der Passwort-Hash auf haveibeenpwned vertreten sein darf"
|
||||
@ -1320,10 +1359,6 @@ msgstr ""
|
||||
"Die Richtlinie wird verweigert, wenn die zxcvbn-Bewertung gleich oder "
|
||||
"kleiner diesem Wert ist."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Passwort nicht im Kontext festgelegt"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr "Ungültiges Passwort."
|
||||
@ -1365,20 +1400,6 @@ msgstr "Reputationswert"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "Reputationswert"
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Waiting for authentication..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid ""
|
||||
"You're already authenticating in another tab. This page will refresh once "
|
||||
"authentication is completed."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Authenticate in this tab"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/denied.html
|
||||
msgid "Permission denied"
|
||||
msgstr "Erlaubnis verweigert"
|
||||
@ -2208,6 +2229,10 @@ msgstr "Rolle"
|
||||
msgid "Roles"
|
||||
msgstr "Rollen"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr "Systemberechtigung"
|
||||
@ -2478,6 +2503,22 @@ msgstr "LDAP Quelle Eigenschafts-Zuordnung"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "LDAP Quelle Eigenschafts-Zuordnungen"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr ""
|
||||
@ -2487,6 +2528,14 @@ msgstr ""
|
||||
msgid "No token received."
|
||||
msgstr "Kein Token empfangen."
|
||||
|
||||
#: 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 "Token-URL anfordern"
|
||||
@ -2528,6 +2577,12 @@ msgstr ""
|
||||
msgid "Additional Scopes"
|
||||
msgstr "zusätzliche Scopes"
|
||||
|
||||
#: 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 "Outh Quelle"
|
||||
@ -3434,6 +3489,12 @@ msgstr ""
|
||||
"Wenn aktiviert, wird die Phase auch dann erfolgreich abgeschlossen und "
|
||||
"fortgesetzt, wenn falsche Benutzerdaten eingegeben wurden."
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid ""
|
||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||
" to skip straight to entering their password."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr "Optionaler Registrierungs-Flow, der unten auf der Seite verlinkt ist."
|
||||
@ -3826,6 +3887,14 @@ msgstr ""
|
||||
"Die Ereignisse werden nach dieser Dauer gelöscht (Format: "
|
||||
"Wochen=3;Tage=2;Stunden=3,Sekunden=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 ""
|
||||
|
Binary file not shown.
@ -15,7 +15,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
||||
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
|
||||
@ -190,6 +190,7 @@ msgid "User's display name."
|
||||
msgstr "Nombre para mostrar del usuario."
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "Usuario"
|
||||
|
||||
@ -378,6 +379,18 @@ msgstr "Asignación de Propiedades"
|
||||
msgid "Property Mappings"
|
||||
msgstr "Asignaciones de Propiedades"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
msgstr "Sesión"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Sessions"
|
||||
msgstr "Sesiones"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Authenticated Session"
|
||||
msgstr "Sesión autenticada"
|
||||
@ -485,6 +498,38 @@ msgstr "Uso de Licencias"
|
||||
msgid "License Usage Records"
|
||||
msgstr "Registro de Uso de Licencias"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Clave de campo a verificar, las claves de campo definidas en las etapas de "
|
||||
"Solicitud están disponibles."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "La contraseña no se ha establecido en contexto"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "This password has been used previously. Please choose a different one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr "Se requiere de Enterprise para acceder esta característica."
|
||||
@ -1268,12 +1313,6 @@ msgstr "Ver las métricas de caché de la Política"
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr "Borrar las métricas de caché de la Política"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Clave de campo a verificar, las claves de campo definidas en las etapas de "
|
||||
"Solicitud están disponibles."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr ""
|
||||
@ -1287,10 +1326,6 @@ msgstr ""
|
||||
"Si la puntuación zxcvbn es igual o menor que este valor, la política "
|
||||
"fallará."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "La contraseña no se ha establecido en contexto"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr "Contraseña inválida."
|
||||
@ -1332,20 +1367,6 @@ msgstr "Puntuación de Reputacion"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "Puntuaciones de Reputacion"
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Waiting for authentication..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid ""
|
||||
"You're already authenticating in another tab. This page will refresh once "
|
||||
"authentication is completed."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Authenticate in this tab"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/denied.html
|
||||
msgid "Permission denied"
|
||||
msgstr "Permiso denegado"
|
||||
@ -2175,6 +2196,10 @@ msgstr "Rol"
|
||||
msgid "Roles"
|
||||
msgstr "Roles"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr "Permiso de sistema"
|
||||
@ -2443,6 +2468,22 @@ msgstr "Asignación de Propiedades de Fuente de LDAP"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Asignaciones de Propiedades de Fuente de LDAP"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "La contraseña no coincide con la complejidad de Active Directory."
|
||||
@ -2451,6 +2492,14 @@ msgstr "La contraseña no coincide con la complejidad de Active Directory."
|
||||
msgid "No token received."
|
||||
msgstr "No se recibió ningún token."
|
||||
|
||||
#: 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 "Solicitar URL de token"
|
||||
@ -2491,6 +2540,12 @@ msgstr "URL utilizada por authentik para obtener información del usuario."
|
||||
msgid "Additional Scopes"
|
||||
msgstr "Alcances Adicionales"
|
||||
|
||||
#: 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 "Fuente de OAuth"
|
||||
@ -3407,6 +3462,12 @@ msgstr ""
|
||||
"Cuando está habilitado, la etapa tendrá éxito y continuará incluso cuando se"
|
||||
" ingrese información de usuario incorrecta."
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid ""
|
||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||
" to skip straight to entering their password."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr ""
|
||||
@ -3794,6 +3855,14 @@ msgstr ""
|
||||
"Los Eventos serán eliminados después de este periodo. (Formato: "
|
||||
"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 ""
|
||||
|
Binary file not shown.
@ -15,7 +15,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Ville Ranki, 2025\n"
|
||||
"Language-Team: Finnish (https://app.transifex.com/authentik/teams/119923/fi/)\n"
|
||||
@ -186,6 +186,7 @@ msgid "User's display name."
|
||||
msgstr "Käyttäjän näytettävä nimi"
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "Käyttäjä"
|
||||
|
||||
@ -371,6 +372,18 @@ msgstr "Ominaisuuskytkentä"
|
||||
msgid "Property Mappings"
|
||||
msgstr "Ominaisuuskytkennät"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
msgstr "Istunto"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Sessions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Authenticated Session"
|
||||
msgstr "Autentikoitu istunto"
|
||||
@ -478,6 +491,38 @@ msgstr "Lisenssin käyttö"
|
||||
msgid "License Usage Records"
|
||||
msgstr "Lisenssin käyttötiedot"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Kentän avain, joka tarkistetaan. Kysymysvaiheissa määritellyt kenttien "
|
||||
"avaimet ovat käytettävissä."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Salasanaa ei ole asetettu kontekstissa"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "This password has been used previously. Please choose a different one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr "Tämän ominaisuuden käyttöön tarvitaan Enterprise-versiota."
|
||||
@ -1251,12 +1296,6 @@ msgstr "Näytä käytäntövälimuistitilastot"
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr "Tyhjennä käytäntövälimuistitilastot"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Kentän avain, joka tarkistetaan. Kysymysvaiheissa määritellyt kenttien "
|
||||
"avaimet ovat käytettävissä."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr ""
|
||||
@ -1269,10 +1308,6 @@ msgstr ""
|
||||
"Jos zxcvbn-pistemäärä on tämä arvo tai pienempi, käytännön suorittaminen "
|
||||
"epäonnistuu."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Salasanaa ei ole asetettu kontekstissa"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr "Virheellinen salasana."
|
||||
@ -1314,20 +1349,6 @@ msgstr "Mainepistemäärä"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "Mainepistemäärät"
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Waiting for authentication..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid ""
|
||||
"You're already authenticating in another tab. This page will refresh once "
|
||||
"authentication is completed."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Authenticate in this tab"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/denied.html
|
||||
msgid "Permission denied"
|
||||
msgstr "Käyttö evätty"
|
||||
@ -2155,6 +2176,10 @@ msgstr "Rooli"
|
||||
msgid "Roles"
|
||||
msgstr "Roolit"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr "Järjestelmän käyttöoikeus"
|
||||
@ -2420,6 +2445,22 @@ msgstr "LDAP-lähteen ominaisuuskytkentä"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "LDAP-lähteen ominaisuuskytkennät"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä."
|
||||
@ -2428,6 +2469,14 @@ msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä."
|
||||
msgid "No token received."
|
||||
msgstr "Tunnistetta ei saatu."
|
||||
|
||||
#: 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 "Pyyntötunnisteen URL"
|
||||
@ -2468,6 +2517,12 @@ msgstr "URL, jota authentik käyttää käyttäjätiedon hakemiseksi."
|
||||
msgid "Additional Scopes"
|
||||
msgstr "Lisäkäyttöalueet"
|
||||
|
||||
#: 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 "OAuth-lähde"
|
||||
@ -3377,6 +3432,12 @@ msgstr ""
|
||||
"Kun tämä on käytössä, vaihe onnistuu ja suoritus jatkuu, vaikka olisi "
|
||||
"syötetty virheelliset käyttäjätiedot."
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid ""
|
||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||
" to skip straight to entering their password."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr ""
|
||||
@ -3754,6 +3815,14 @@ msgstr ""
|
||||
"Tapahtumat poistetaan tämän ajan jälkeen. (Muoto: "
|
||||
"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 ""
|
||||
|
Binary file not shown.
@ -12,17 +12,17 @@
|
||||
# tmassimi, 2024
|
||||
# Marc Schmitt, 2024
|
||||
# albanobattistella <albanobattistella@gmail.com>, 2024
|
||||
# Matteo Piccina <altermatte@gmail.com>, 2025
|
||||
# Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025
|
||||
# Matteo Piccina <altermatte@gmail.com>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n"
|
||||
"Last-Translator: Matteo Piccina <altermatte@gmail.com>, 2025\n"
|
||||
"Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -194,6 +194,7 @@ msgid "User's display name."
|
||||
msgstr "Nome visualizzato dell'utente."
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "Utente"
|
||||
|
||||
@ -380,6 +381,18 @@ msgstr "Mappatura della proprietà"
|
||||
msgid "Property Mappings"
|
||||
msgstr "Mappatura delle proprietà"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
msgstr "Sessione"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Sessions"
|
||||
msgstr "Sessioni"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Authenticated Session"
|
||||
msgstr "Sessione Autenticata"
|
||||
@ -487,6 +500,38 @@ msgstr "Utilizzo della licenza"
|
||||
msgid "License Usage Records"
|
||||
msgstr "Registri sull'utilizzo della licenza"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Chiave di campo da verificare, sono disponibili le chiavi di campo definite "
|
||||
"nelle fasi Richiesta."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Password non impostata nel contesto"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "This password has been used previously. Please choose a different one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr "Versione Enterprise richiesta per accedere a questa funzione"
|
||||
@ -1274,12 +1319,6 @@ msgstr "Visualizza le metriche della cache della Policy"
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr "Cancellare le metriche della cache della Policy"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Chiave di campo da verificare, sono disponibili le chiavi di campo definite "
|
||||
"nelle fasi Richiesta."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr ""
|
||||
@ -1292,10 +1331,6 @@ msgstr ""
|
||||
"Se il punteggio zxcvbn è inferiore o uguale a questo valore, il criterio non"
|
||||
" verrà soddisfatto."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Password non impostata nel contesto"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr "Password invalida."
|
||||
@ -1337,22 +1372,6 @@ msgstr "Punteggio di reputazione"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "Punteggi di reputazione"
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Waiting for authentication..."
|
||||
msgstr "In attesa di autenticazione..."
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid ""
|
||||
"You're already authenticating in another tab. This page will refresh once "
|
||||
"authentication is completed."
|
||||
msgstr ""
|
||||
"Ti stai già autenticando in un'altra scheda. Questa pagina si aggiornerà una"
|
||||
" volta completata l'autenticazione."
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Authenticate in this tab"
|
||||
msgstr "Autenticati in questa scheda"
|
||||
|
||||
#: authentik/policies/templates/policies/denied.html
|
||||
msgid "Permission denied"
|
||||
msgstr "Permesso negato"
|
||||
@ -2182,6 +2201,10 @@ msgstr "Ruolo"
|
||||
msgid "Roles"
|
||||
msgstr "Ruoli"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr "Autorizzazione di sistema"
|
||||
@ -2452,6 +2475,22 @@ msgstr "Mappatura delle proprietà sorgente LDAP"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Mappature delle proprietà della sorgente LDAP"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "La password non soddisfa la complessità Active Directory."
|
||||
@ -2460,6 +2499,14 @@ msgstr "La password non soddisfa la complessità Active Directory."
|
||||
msgid "No token received."
|
||||
msgstr "Nessun token ricevuto."
|
||||
|
||||
#: 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 "URL di Richiesta Token"
|
||||
@ -2500,6 +2547,12 @@ msgstr "URL utilizzato da authentik per ottenere le informazioni dell'utente."
|
||||
msgid "Additional Scopes"
|
||||
msgstr "Ambiti aggiuntivi"
|
||||
|
||||
#: 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 "Sorgente OAuth"
|
||||
@ -3426,6 +3479,12 @@ msgstr ""
|
||||
"Quando abilitato, la fase avrà successo e continuerà anche quando vengono "
|
||||
"inserite informazioni utente errate."
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid ""
|
||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||
" to skip straight to entering their password."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr "Flusso di iscrizione opzionale, che è collegato in fondo alla pagina."
|
||||
@ -3812,6 +3871,14 @@ msgstr ""
|
||||
"Gli eventi saranno cancellati dopo questa durata. (Formato: "
|
||||
"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 ""
|
||||
|
@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-03-31 00:10+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: NavyStack, 2023\n"
|
||||
"Language-Team: Korean (https://app.transifex.com/authentik/teams/119923/ko/)\n"
|
||||
@ -176,6 +176,7 @@ msgid "User's display name."
|
||||
msgstr "사용자의 표시 이름"
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "사용자"
|
||||
|
||||
@ -344,6 +345,18 @@ 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 "인증된 세션"
|
||||
@ -447,6 +460,36 @@ msgstr "라이선스 사용"
|
||||
msgid "License Usage Records"
|
||||
msgstr "라이선스 사용 기록"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr "확인하려는 필드 키, 프롬프트 스테이지에서 정의된 필드 키를 사용할 수 있습니다."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "비밀번호가 컨텍스트에 설정되지 않음"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "This password has been used previously. Please choose a different one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr ""
|
||||
@ -1182,10 +1225,6 @@ msgstr "정책의 캐시 메트릭 보기"
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr "정책의 캐시 메트릭 삭제"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr "확인하려는 필드 키, 프롬프트 스테이지에서 정의된 필드 키를 사용할 수 있습니다."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr "비밀번호 해시가 허용되는 해시 횟수"
|
||||
@ -1195,10 +1234,6 @@ msgid ""
|
||||
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
||||
msgstr "만약 zxcvbn 점수가 이 값과 같거나 이 값보다 작다면, 정책이 실패합니다."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "비밀번호가 컨텍스트에 설정되지 않음"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr ""
|
||||
@ -1240,20 +1275,6 @@ msgstr "평판 점수"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "평판 점수"
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Waiting for authentication..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid ""
|
||||
"You're already authenticating in another tab. This page will refresh once "
|
||||
"authentication is completed."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Authenticate in this tab"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/denied.html
|
||||
msgid "Permission denied"
|
||||
msgstr "권한 거부됨"
|
||||
@ -2013,6 +2034,10 @@ msgstr "역할"
|
||||
msgid "Roles"
|
||||
msgstr "역할"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr "시스템 권한"
|
||||
@ -2231,6 +2256,13 @@ msgid ""
|
||||
"enabled on a single LDAP source."
|
||||
msgstr "사용자가 비밀번호를 변경하면 LDAP로 다시 동기화합니다. 이 기능은 단일의 LDAP 소스에서만 활성화할 수 있습니다."
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
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 ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP 소스"
|
||||
@ -2247,6 +2279,22 @@ msgstr ""
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다."
|
||||
@ -2255,6 +2303,14 @@ msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다.
|
||||
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 "토큰 요청 URL"
|
||||
@ -2293,6 +2349,12 @@ msgstr "사용자 정보를 가져오기 위해 authentik에서 사용하는 URL
|
||||
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 "OAuth 소스"
|
||||
@ -3149,6 +3211,12 @@ msgid ""
|
||||
"info is entered."
|
||||
msgstr "활성화되면 잘못된 사용자 정보가 입력되더라도 단계가 성공하고 계속됩니다."
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid ""
|
||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||
" to skip straight to entering their password."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr "페이지 하단에 링크된, 선택적 등록 플로우를 참조하세요."
|
||||
@ -3500,6 +3568,14 @@ msgid ""
|
||||
"weeks=3;days=2;hours=3,seconds=2)."
|
||||
msgstr "이 기간이 지나면 이벤트가 삭제됩니다. (서식: hours=-1;minutes=-2;seconds=-3)"
|
||||
|
||||
#: 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 ""
|
||||
|
@ -7,18 +7,18 @@
|
||||
# Bartosz Karpiński, 2023
|
||||
# Michał Jastrzębski, 2024
|
||||
# Tomci 12 <drizztes@gmail.com>, 2024
|
||||
# Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2024
|
||||
# Marc Schmitt, 2025
|
||||
# Jens L. <jens@goauthentik.io>, 2025
|
||||
# Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2025\n"
|
||||
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
||||
"Language-Team: Polish (https://app.transifex.com/authentik/teams/119923/pl/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -189,6 +189,7 @@ msgid "User's display name."
|
||||
msgstr "Wyświetlana nazwa użytkownika."
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "Użytkownik"
|
||||
|
||||
@ -371,6 +372,18 @@ msgstr "Mapowanie właściwości"
|
||||
msgid "Property Mappings"
|
||||
msgstr "Mapowanie właściwości"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
msgstr "Sesja"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Sessions"
|
||||
msgstr "Sesje"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Authenticated Session"
|
||||
msgstr "Sesja uwierzytelniona"
|
||||
@ -479,6 +492,38 @@ msgstr "Wykorzystanie licencji"
|
||||
msgid "License Usage Records"
|
||||
msgstr "Rejestr wykorzystania licencji"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Klucz pola do sprawdzenia, dostępne są klucze pola zdefiniowane w etapach "
|
||||
"monitu."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Hasło nie jest ustawione w kontekście"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "This password has been used previously. Please choose a different one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr "Wymagane jest konto Enterprise, aby uzyskać dostęp do tej funkcji."
|
||||
@ -1257,12 +1302,6 @@ msgstr "Wyświetl metryki pamięci podręcznej Zasady"
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr "Wyczyść metryki pamięci podręcznej Zasady"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Klucz pola do sprawdzenia, dostępne są klucze pola zdefiniowane w etapach "
|
||||
"monitu."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr "Ile razy skrót hasła może być na haveibeenpwned"
|
||||
@ -1274,10 +1313,6 @@ msgstr ""
|
||||
"Jeśli wynik zxcvbn jest równy lub mniejszy od tej wartości, zasada zakończy "
|
||||
"się niepowodzeniem."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Hasło nie jest ustawione w kontekście"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr ""
|
||||
@ -1319,20 +1354,6 @@ msgstr "Punkty reputacji"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "Punkty reputacji"
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Waiting for authentication..."
|
||||
msgstr "Oczekiwanie na uwierzytelnienie..."
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid ""
|
||||
"You're already authenticating in another tab. This page will refresh once "
|
||||
"authentication is completed."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Authenticate in this tab"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/denied.html
|
||||
msgid "Permission denied"
|
||||
msgstr "Odmowa uprawnień"
|
||||
@ -2141,6 +2162,10 @@ msgstr "Rola"
|
||||
msgid "Roles"
|
||||
msgstr "Role"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr "Uprawnienie systemowe"
|
||||
@ -2390,6 +2415,22 @@ msgstr ""
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "Hasło nie pasuje do złożoności usługi Active Directory."
|
||||
@ -2398,6 +2439,14 @@ msgstr "Hasło nie pasuje do złożoności usługi Active Directory."
|
||||
msgid "No token received."
|
||||
msgstr "Nie otrzymano tokena."
|
||||
|
||||
#: 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 "URL żądania tokena"
|
||||
@ -2440,6 +2489,12 @@ msgstr "URL używany przez authentik do uzyskania informacji o użytkowniku."
|
||||
msgid "Additional Scopes"
|
||||
msgstr "Dodatkowe zakresy"
|
||||
|
||||
#: 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 "Źródło OAuth"
|
||||
@ -3344,6 +3399,12 @@ msgstr ""
|
||||
"Po włączeniu tej opcji etap zakończy się powodzeniem i będzie kontynuowany "
|
||||
"nawet po wprowadzeniu nieprawidłowych danych użytkownika."
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid ""
|
||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||
" to skip straight to entering their password."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr ""
|
||||
@ -3727,6 +3788,14 @@ msgstr ""
|
||||
"Zdarzenia zostaną usunięte po upływie tego czasu. (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 ""
|
||||
|
||||
#: 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 "Opcja ta konfiguruje łącza stopki na stronach wykonawców przepływu."
|
||||
|
@ -18,7 +18,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Marc Schmitt, 2025\n"
|
||||
"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n"
|
||||
@ -191,6 +191,7 @@ msgid "User's display name."
|
||||
msgstr "Отображаемое имя пользователя."
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "Пользователь"
|
||||
|
||||
@ -379,6 +380,18 @@ 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 "Аутентифицированная Сессия"
|
||||
@ -487,6 +500,37 @@ msgstr "Использование лицензии"
|
||||
msgid "License Usage Records"
|
||||
msgstr "Записи использования лицензии"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Ключ поля для проверки, доступны ключи поля, определенные в этапах запроса."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Пароль не задан в контексте"
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "This password has been used previously. Please choose a different one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr "Для доступа к этой функции требуется Enterprise."
|
||||
@ -1267,11 +1311,6 @@ msgstr "Просмотр показателей кэша политики"
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr "Очистка показателей кэша политики"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Ключ поля для проверки, доступны ключи поля, определенные в этапах запроса."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr "Как часто хэш пароля может быть представлен на haveibeenpwned"
|
||||
@ -1283,10 +1322,6 @@ msgstr ""
|
||||
"Если показатель zxcvbn равен или меньше этого значения, политика будет "
|
||||
"провалена."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Пароль не задан в контексте"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr "Неправильный пароль"
|
||||
@ -1328,20 +1363,6 @@ msgstr "Оценка репутации"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "Оценка репутации"
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Waiting for authentication..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid ""
|
||||
"You're already authenticating in another tab. This page will refresh once "
|
||||
"authentication is completed."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/buffer.html
|
||||
msgid "Authenticate in this tab"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/templates/policies/denied.html
|
||||
msgid "Permission denied"
|
||||
msgstr "Доступ запрещен"
|
||||
@ -2164,6 +2185,10 @@ msgstr "Роль"
|
||||
msgid "Roles"
|
||||
msgstr "Роли"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr "Системное разрешение"
|
||||
@ -2421,6 +2446,22 @@ msgstr "Сопоставление свойства LDAP источника"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Сопоставление свойств LDAP источника"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr "Пароль не соответствует сложности Active Directory."
|
||||
@ -2429,6 +2470,14 @@ msgstr "Пароль не соответствует сложности Active D
|
||||
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 "URL-адрес запроса токена"
|
||||
@ -2471,6 +2520,12 @@ 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 "Источник OAuth"
|
||||
@ -3376,6 +3431,12 @@ msgstr ""
|
||||
"При включении этап будет завершаться успешно и продолжаться даже в случае "
|
||||
"ввода неправильной информации о пользователе."
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid ""
|
||||
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||
" to skip straight to entering their password."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/identification/models.py
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr ""
|
||||
@ -3767,6 +3828,14 @@ msgstr ""
|
||||
"По истечении этого времени события будут удалены. (Формат: недели=3; дни=2; "
|
||||
"часы=3, секунды=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 ""
|
||||
|
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2025.2.4",
|
||||
"version": "2025.4.0",
|
||||
"private": true
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ EXPOSE 9000 9300 9443
|
||||
|
||||
USER 1000
|
||||
|
||||
ENV GOFIPS=1
|
||||
ENV TMPDIR=/dev/shm/ \
|
||||
GOFIPS=1
|
||||
|
||||
ENTRYPOINT ["/proxy"]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "authentik"
|
||||
version = "2025.2.4"
|
||||
version = "2025.4.0"
|
||||
description = ""
|
||||
authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }]
|
||||
requires-python = "==3.12.*"
|
||||
|
@ -56,6 +56,7 @@ HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/rac", "healthch
|
||||
|
||||
USER 1000
|
||||
|
||||
ENV GOFIPS=1
|
||||
ENV TMPDIR=/dev/shm/ \
|
||||
GOFIPS=1
|
||||
|
||||
ENTRYPOINT ["/rac"]
|
||||
|
@ -56,6 +56,7 @@ EXPOSE 1812/udp 9300
|
||||
|
||||
USER 1000
|
||||
|
||||
ENV GOFIPS=1
|
||||
ENV TMPDIR=/dev/shm/ \
|
||||
GOFIPS=1
|
||||
|
||||
ENTRYPOINT ["/radius"]
|
||||
|
@ -1,7 +1,7 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: authentik
|
||||
version: 2025.2.4
|
||||
version: 2025.4.0
|
||||
description: Making authentication simple.
|
||||
contact:
|
||||
email: hello@goauthentik.io
|
||||
|
@ -410,3 +410,77 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
|
||||
self.driver.find_element(By.CSS_SELECTOR, "header > h1").text,
|
||||
"Permission denied",
|
||||
)
|
||||
|
||||
@retry()
|
||||
@apply_blueprint(
|
||||
"default/flow-default-authentication-flow.yaml",
|
||||
"default/flow-default-invalidation-flow.yaml",
|
||||
)
|
||||
@apply_blueprint("default/flow-default-provider-authorization-implicit-consent.yaml")
|
||||
@apply_blueprint("system/providers-oauth2.yaml")
|
||||
@reconcile_app("authentik_crypto")
|
||||
def test_authorization_consent_implied_parallel(self):
|
||||
"""test OpenID Provider flow (default authorization flow with implied consent)"""
|
||||
# Bootstrap all needed objects
|
||||
authorization_flow = Flow.objects.get(
|
||||
slug="default-provider-authorization-implicit-consent"
|
||||
)
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name=generate_id(),
|
||||
client_type=ClientTypes.CONFIDENTIAL,
|
||||
client_id=self.client_id,
|
||||
client_secret=self.client_secret,
|
||||
signing_key=create_test_cert(),
|
||||
redirect_uris=[
|
||||
RedirectURI(
|
||||
RedirectURIMatchingMode.STRICT, "http://localhost:3000/login/generic_oauth"
|
||||
)
|
||||
],
|
||||
authorization_flow=authorization_flow,
|
||||
)
|
||||
provider.property_mappings.set(
|
||||
ScopeMapping.objects.filter(
|
||||
scope_name__in=[
|
||||
SCOPE_OPENID,
|
||||
SCOPE_OPENID_EMAIL,
|
||||
SCOPE_OPENID_PROFILE,
|
||||
SCOPE_OFFLINE_ACCESS,
|
||||
]
|
||||
)
|
||||
)
|
||||
Application.objects.create(
|
||||
name=generate_id(),
|
||||
slug=self.app_slug,
|
||||
provider=provider,
|
||||
)
|
||||
|
||||
self.driver.get(self.live_server_url)
|
||||
login_window = self.driver.current_window_handle
|
||||
|
||||
self.driver.switch_to.new_window("tab")
|
||||
grafana_window = self.driver.current_window_handle
|
||||
self.driver.get("http://localhost:3000")
|
||||
self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click()
|
||||
|
||||
self.driver.switch_to.window(login_window)
|
||||
self.login()
|
||||
|
||||
self.driver.switch_to.window(grafana_window)
|
||||
self.wait_for_url("http://localhost:3000/?orgId=1")
|
||||
self.driver.get("http://localhost:3000/profile")
|
||||
self.assertEqual(
|
||||
self.driver.find_element(By.CLASS_NAME, "page-header__title").text,
|
||||
self.user.name,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.driver.find_element(By.CSS_SELECTOR, "input[name=name]").get_attribute("value"),
|
||||
self.user.name,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.driver.find_element(By.CSS_SELECTOR, "input[name=email]").get_attribute("value"),
|
||||
self.user.email,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.driver.find_element(By.CSS_SELECTOR, "input[name=login]").get_attribute("value"),
|
||||
self.user.email,
|
||||
)
|
||||
|
@ -20,7 +20,7 @@ from tests.e2e.utils import SeleniumTestCase, retry
|
||||
class TestProviderSAML(SeleniumTestCase):
|
||||
"""test SAML Provider flow"""
|
||||
|
||||
def setup_client(self, provider: SAMLProvider, force_post: bool = False):
|
||||
def setup_client(self, provider: SAMLProvider, force_post: bool = False, **kwargs):
|
||||
"""Setup client saml-sp container which we test SAML against"""
|
||||
metadata_url = (
|
||||
self.url(
|
||||
@ -40,6 +40,7 @@ class TestProviderSAML(SeleniumTestCase):
|
||||
"SP_ENTITY_ID": provider.issuer,
|
||||
"SP_SSO_BINDING": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
||||
"SP_METADATA_URL": metadata_url,
|
||||
**kwargs,
|
||||
},
|
||||
)
|
||||
|
||||
@ -111,6 +112,74 @@ class TestProviderSAML(SeleniumTestCase):
|
||||
[self.user.email],
|
||||
)
|
||||
|
||||
@retry()
|
||||
@apply_blueprint(
|
||||
"default/flow-default-authentication-flow.yaml",
|
||||
"default/flow-default-invalidation-flow.yaml",
|
||||
)
|
||||
@apply_blueprint(
|
||||
"default/flow-default-provider-authorization-implicit-consent.yaml",
|
||||
)
|
||||
@apply_blueprint(
|
||||
"system/providers-saml.yaml",
|
||||
)
|
||||
@reconcile_app("authentik_crypto")
|
||||
def test_sp_initiated_implicit_post(self):
|
||||
"""test SAML Provider flow SP-initiated flow (implicit consent)"""
|
||||
# Bootstrap all needed objects
|
||||
authorization_flow = Flow.objects.get(
|
||||
slug="default-provider-authorization-implicit-consent"
|
||||
)
|
||||
provider: SAMLProvider = SAMLProvider.objects.create(
|
||||
name="saml-test",
|
||||
acs_url="http://localhost:9009/saml/acs",
|
||||
audience="authentik-e2e",
|
||||
issuer="authentik-e2e",
|
||||
sp_binding=SAMLBindings.POST,
|
||||
authorization_flow=authorization_flow,
|
||||
signing_kp=create_test_cert(),
|
||||
)
|
||||
provider.property_mappings.set(SAMLPropertyMapping.objects.all())
|
||||
provider.save()
|
||||
Application.objects.create(
|
||||
name="SAML",
|
||||
slug="authentik-saml",
|
||||
provider=provider,
|
||||
)
|
||||
self.setup_client(provider, True)
|
||||
self.driver.get("http://localhost:9009")
|
||||
self.login()
|
||||
self.wait_for_url("http://localhost:9009/")
|
||||
|
||||
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
|
||||
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],
|
||||
[self.user.name],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"][
|
||||
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
|
||||
],
|
||||
[self.user.username],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/username"],
|
||||
[self.user.username],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/uid"],
|
||||
[str(self.user.pk)],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
|
||||
[self.user.email],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"],
|
||||
[self.user.email],
|
||||
)
|
||||
|
||||
@retry()
|
||||
@apply_blueprint(
|
||||
"default/flow-default-authentication-flow.yaml",
|
||||
@ -450,3 +519,81 @@ class TestProviderSAML(SeleniumTestCase):
|
||||
lambda driver: driver.current_url.startswith(should_url),
|
||||
f"URL {self.driver.current_url} doesn't match expected URL {should_url}",
|
||||
)
|
||||
|
||||
@retry()
|
||||
@apply_blueprint(
|
||||
"default/flow-default-authentication-flow.yaml",
|
||||
"default/flow-default-invalidation-flow.yaml",
|
||||
)
|
||||
@apply_blueprint(
|
||||
"default/flow-default-provider-authorization-implicit-consent.yaml",
|
||||
)
|
||||
@apply_blueprint(
|
||||
"system/providers-saml.yaml",
|
||||
)
|
||||
@reconcile_app("authentik_crypto")
|
||||
def test_sp_initiated_implicit_post_buffer(self):
|
||||
"""test SAML Provider flow SP-initiated flow (implicit consent)"""
|
||||
# Bootstrap all needed objects
|
||||
authorization_flow = Flow.objects.get(
|
||||
slug="default-provider-authorization-implicit-consent"
|
||||
)
|
||||
provider: SAMLProvider = SAMLProvider.objects.create(
|
||||
name="saml-test",
|
||||
acs_url=f"http://{self.host}:9009/saml/acs",
|
||||
audience="authentik-e2e",
|
||||
issuer="authentik-e2e",
|
||||
sp_binding=SAMLBindings.POST,
|
||||
authorization_flow=authorization_flow,
|
||||
signing_kp=create_test_cert(),
|
||||
)
|
||||
provider.property_mappings.set(SAMLPropertyMapping.objects.all())
|
||||
provider.save()
|
||||
Application.objects.create(
|
||||
name="SAML",
|
||||
slug="authentik-saml",
|
||||
provider=provider,
|
||||
)
|
||||
self.setup_client(provider, True, SP_ROOT_URL=f"http://{self.host}:9009")
|
||||
|
||||
self.driver.get(self.live_server_url)
|
||||
login_window = self.driver.current_window_handle
|
||||
self.driver.switch_to.new_window("tab")
|
||||
client_window = self.driver.current_window_handle
|
||||
# We need to access the SP on the same host as the IdP for SameSite cookies
|
||||
self.driver.get(f"http://{self.host}:9009")
|
||||
|
||||
self.driver.switch_to.window(login_window)
|
||||
self.login()
|
||||
self.driver.switch_to.window(client_window)
|
||||
|
||||
self.wait_for_url(f"http://{self.host}:9009/")
|
||||
|
||||
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
|
||||
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],
|
||||
[self.user.name],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"][
|
||||
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
|
||||
],
|
||||
[self.user.username],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/username"],
|
||||
[self.user.username],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/uid"],
|
||||
[str(self.user.pk)],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
|
||||
[self.user.email],
|
||||
)
|
||||
self.assertEqual(
|
||||
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"],
|
||||
[self.user.email],
|
||||
)
|
||||
|
14
uv.lock
generated
14
uv.lock
generated
@ -165,7 +165,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "authentik"
|
||||
version = "2025.2.4"
|
||||
version = "2025.4.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "argon2-cffi" },
|
||||
@ -1436,11 +1436,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
version = "0.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1467,15 +1467,15 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/45/ad3e1b4d448f22c0cff4f5692f5ed0666658578e358b8d58a19846048059/httpcore-1.0.8.tar.gz", hash = "sha256:86e94505ed24ea06514883fd44d2bc02d90e77e7979c8eb71b90f41d364a1bad", size = 85385 }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/8d/f052b1e336bb2c1fc7ed1aaed898aa570c0b61a09707b108979d9fc6e308/httpcore-1.0.8-py3-none-any.whl", hash = "sha256:5254cf149bcb5f75e9d1b2b9f729ea4a4b883d1ad7379fc632b727cec23674be", size = 78732 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -47,7 +47,16 @@ class SimpleFlowExecutor {
|
||||
return `${ak().api.base}api/v3/flows/executor/${this.flowSlug}/?query=${encodeURIComponent(window.location.search.substring(1))}`;
|
||||
}
|
||||
|
||||
loading() {
|
||||
this.container.innerHTML = `<div class="d-flex justify-content-center">
|
||||
<div class="spinner-border spinner-border-md" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
start() {
|
||||
this.loading();
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: this.apiURL,
|
||||
|
@ -89,19 +89,24 @@ export class RoleObjectPermissionForm extends ModelForm<RoleAssignData, number>
|
||||
>
|
||||
</ak-search-select>
|
||||
</ak-form-element-horizontal>
|
||||
${this.modelPermissions?.results.map((perm) => {
|
||||
return html` <ak-form-element-horizontal name="permissions.${perm.codename}">
|
||||
<label class="pf-c-switch">
|
||||
<input class="pf-c-switch__input" type="checkbox" />
|
||||
<span class="pf-c-switch__toggle">
|
||||
<span class="pf-c-switch__toggle-icon">
|
||||
<i class="fas fa-check" aria-hidden="true"></i>
|
||||
${this.modelPermissions?.results
|
||||
.filter((perm) => {
|
||||
const [_app, model] = this.model?.split(".") || "";
|
||||
return perm.codename !== `add_${model}`;
|
||||
})
|
||||
.map((perm) => {
|
||||
return html` <ak-form-element-horizontal name="permissions.${perm.codename}">
|
||||
<label class="pf-c-switch">
|
||||
<input class="pf-c-switch__input" type="checkbox" />
|
||||
<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>
|
||||
<span class="pf-c-switch__label">${perm.name}</span>
|
||||
</label>
|
||||
</ak-form-element-horizontal>`;
|
||||
})}
|
||||
<span class="pf-c-switch__label">${perm.name}</span>
|
||||
</label>
|
||||
</ak-form-element-horizontal>`;
|
||||
})}
|
||||
</form>`;
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ export class RoleAssignedObjectPermissionTable extends Table<RoleAssignedObjectP
|
||||
ordering: "codename",
|
||||
});
|
||||
modelPermissions.results = modelPermissions.results.filter((value) => {
|
||||
return !value.codename.startsWith("add_");
|
||||
return value.codename !== `add_${this.model?.split(".")[1]}`;
|
||||
});
|
||||
this.modelPermissions = modelPermissions;
|
||||
return perms;
|
||||
|
@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
|
||||
export const ERROR_CLASS = "pf-m-danger";
|
||||
export const PROGRESS_CLASS = "pf-m-in-progress";
|
||||
export const CURRENT_CLASS = "pf-m-current";
|
||||
export const VERSION = "2025.2.4";
|
||||
export const VERSION = "2025.4.0";
|
||||
export const TITLE_DEFAULT = "authentik";
|
||||
export const ROUTE_SEPARATOR = ";";
|
||||
|
||||
|
@ -85,7 +85,6 @@ export abstract class AKChart<T> extends AKElement {
|
||||
.container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -1091,7 +1091,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="sd62cfc27ad4aa33b">
|
||||
<source>Based on the User's Email</source>
|
||||
<target>Basierend auf der E-Mail Adresse des Benutzers</target>
|
||||
<target>Basierend auf der E-Mail-Adresse des Benutzers</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s55eb75bedf96be0f">
|
||||
@ -2361,6 +2361,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="s9307f3dbb07a73b5">
|
||||
<source>Only fail the policy, don't invalidate user's password</source>
|
||||
<target>Nur die Richtlinie fehlschlagen lassen, das Passwort des Benutzers nicht ungültig machen.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="scea1f16238093e35">
|
||||
@ -2809,6 +2810,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
</trans-unit>
|
||||
<trans-unit id="sfbc59ff17a73503d">
|
||||
<source>User path</source>
|
||||
<target>Nutzerpfad</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sd18170637295bace">
|
||||
@ -2878,6 +2880,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
</trans-unit>
|
||||
<trans-unit id="s995535e7af30d754">
|
||||
<source>Use the user's email address, but deny enrollment when the email address already exists</source>
|
||||
<target>Verwende die E-Mail-Adresse des Benutzers, aber verweigere die Registrierung, wenn die E-Mail-Adresse bereits existiert.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s542ecb4130f6cea5">
|
||||
@ -2886,6 +2889,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
</trans-unit>
|
||||
<trans-unit id="s2a1debf34e5aeba4">
|
||||
<source>Use the user's username, but deny enrollment when the username already exists</source>
|
||||
<target>Verwende den Anmeldenamen des Benutzers, aber verweigere die Registrierung von der Anmeldename bereits existiert.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s81ce0d54727f42d2">
|
||||
@ -3740,6 +3744,9 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
</trans-unit>
|
||||
<trans-unit id="s14401ff4a0cba208">
|
||||
<source>Failed to update <x id="0" equiv-text="${this.objectLabel}"/>: <x id="1" equiv-text="${pluckErrorDetail(parsedError)}"/></source>
|
||||
<target>Aktualisieren von
|
||||
<x id="0" equiv-text="${this.objectLabel}"/>fehlgeschlagen:
|
||||
<x id="1" equiv-text="${e.toString()}"/></target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="sa95a538bfbb86111">
|
||||
@ -4951,7 +4958,7 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
</trans-unit>
|
||||
<trans-unit id="se50a08ab71bb96ed">
|
||||
<source>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.</source>
|
||||
<target>Sofern eine gültige E-Mailadresse oder Benutzername angegeben wurde und diese Option aktiviert ist, wird das Profilbild und der Benutzername des Benutzers angezeigt. Ansonsten wird der vom Benutzer eingegebene Text angezeigt.</target>
|
||||
<target>Sofern eine gültige E-Mail-Adresse oder Benutzername angegeben wurde und diese Option aktiviert ist, wird das Profilbild und der Benutzername des Benutzers angezeigt. Ansonsten wird der vom Benutzer eingegebene Text angezeigt.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="s0295ce5d6f635d75">
|
||||
@ -6245,7 +6252,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s670ad066cc0e50a3">
|
||||
<source>Login to continue to <x id="0" equiv-text="${this.challenge.applicationPre}"/>.</source>
|
||||
<target>Anmelden um mit <x id="0" equiv-text="${this.challenge.applicationPre}"/> fortzufahren.</target>
|
||||
<target>Anmelden, um mit <x id="0" equiv-text="${this.challenge.applicationPre}"/> fortzufahren.</target>
|
||||
|
||||
</trans-unit>
|
||||
<trans-unit id="scf5ce91bfba10a61">
|
||||
@ -7451,6 +7458,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s28b99b59541f54ca">
|
||||
<source>Connection failed after <x id="0" equiv-text="${this.connectionAttempt}"/> attempts.</source>
|
||||
<target>Verbindung nach <x id="0" equiv-text="${this.connectionAttempt}"/> Versuch(en) fehlgeschlagen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7c7d956418e1c8c8">
|
||||
<source>Re-connecting in <x id="0" equiv-text="${Math.max(1, delay / 1000)}"/> second(s).</source>
|
||||
@ -7572,11 +7580,11 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s456d88f3679190fd">
|
||||
<source>Allow users to change email</source>
|
||||
<target>Benutzer können E-Mail ändern</target>
|
||||
<target>Benutzer können E-Mail-Adresse ändern</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5fc6c14d106f40d3">
|
||||
<source>Enable the ability for users to change their email.</source>
|
||||
<target>Benutzer haben die Möglichkeit, ihre E-Mail zu ändern.</target>
|
||||
<target>Benutzer haben die Möglichkeit, ihre E-Mail-Adresse zu ändern.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s628e414bb2367057">
|
||||
<source>Allow users to change username</source>
|
||||
@ -7801,7 +7809,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8cc0075913c67566">
|
||||
<source>Enter the email associated with your account, and we'll send you a link to reset your password.</source>
|
||||
<target>Gib die Email deines Accounts ein und du erhältst einen Link zum zurücksetzen des Passworts.</target>
|
||||
<target>Gib die E-Mail-Adresse deines Accounts ein und du erhältst einen Link zum zurücksetzen des Passworts.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s06bfe45ffef2cf60">
|
||||
<source>Stage name: <x id="0" equiv-text="${this.challenge.name}"/></source>
|
||||
@ -7885,6 +7893,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc1673c93148583ba">
|
||||
<source>Request failed. Please try again later.</source>
|
||||
<target>Anfrage fehlgeschlagen. Bitte versuchen Sie es später erneut.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s85be1f5e7a0fa3b1">
|
||||
<source>Available Roles</source>
|
||||
@ -8277,7 +8286,6 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s354405ae02cb262d">
|
||||
<source>Last seen: <x id="0" equiv-text="${formatElapsedTime(lastSeen)}"/> (<x id="1" equiv-text="${lastSeen.toLocaleTimeString()}"/>)</source>
|
||||
<target>Zuletzt gesehen: <x id="0" equiv-text="${getRelativeTime(lastSeen)}"/> (<x id="1" equiv-text="${lastSeen.toLocaleTimeString()}"/>)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5aebe06e3ddf6ca9">
|
||||
<source>Sign assertions</source>
|
||||
@ -8849,9 +8857,11 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s61ffea061fae0af4">
|
||||
<source>No notifications found.</source>
|
||||
<target>Keine Benachrichtigungen gefunden.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="scf8d5cdc8b434982">
|
||||
<source>You don't have any notifications currently.</source>
|
||||
<target>Sie haben zur Zeit keine Benachrichtigungen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s358e08de4fbebf51">
|
||||
<source>Version <x id="0" equiv-text="${this.version?.versionCurrent || ""}"/></source>
|
||||
|
@ -9602,6 +9602,81 @@ Liitokset käyttäjiin/ryhmiin tarkistetaan tapahtuman käyttäjästä.</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>
|
||||
</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>
|
||||
<trans-unit id="s844baf19a6c4a9b4">
|
||||
<source>Enable "Remember me on this device"</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfa72bca733f40692">
|
||||
<source>When enabled, the user can save their username in a cookie, allowing them to skip directly to entering their password.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s1c336c2d6cef77b3">
|
||||
<source>Remember me on this device</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s86cf007b861152ca">
|
||||
<source>Ensure that the user's new password is different from their previous passwords. The number of past passwords to check is configurable.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s79b3fcd40dd63921">
|
||||
<source>Number of previous passwords to check</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -9700,6 +9700,7 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s1d47b4f61ca53e8e">
|
||||
<source>Lookup using user attribute</source>
|
||||
<target>Ricerca tramite attributo utente</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>
|
||||
|
@ -8620,7 +8620,6 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
|
||||
</trans-unit>
|
||||
<trans-unit id="s354405ae02cb262d">
|
||||
<source>Last seen: <x id="0" equiv-text="${formatElapsedTime(lastSeen)}"/> (<x id="1" equiv-text="${lastSeen.toLocaleTimeString()}"/>)</source>
|
||||
<target>Son görülme: <x id="0" equiv-text="${getRelativeTime(lastSeen)}"/> (<x id="1" equiv-text="${lastSeen.toLocaleTimeString()}"/>)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5aebe06e3ddf6ca9">
|
||||
<source>Sign assertions</source>
|
||||
|
@ -42,7 +42,7 @@ By default, the captcha test keys are used. You can get a proper key [here](http
|
||||
|
||||
## Recovery with email verification
|
||||
|
||||
Flow: right-click [here](https://version-2024-12.goauthentik.io/assets/files/flows-recovery-email-verification-408d6afeff2fbf276bf43a949e332ef6.yaml) and save the file.
|
||||
Flow: right-click [here](/blueprints/example/flows-recovery-email-verification.yaml) and save the file.
|
||||
|
||||
Recovery flow, the user is sent an email after they've identified themselves. After they click on the link in the email, they are prompted for a new password and immediately logged on.
|
||||
|
||||
|
@ -13,6 +13,7 @@ This integration creates the following objects:
|
||||
- Secret to store the token
|
||||
- Prometheus ServiceMonitor (if the Prometheus Operator is installed in the target cluster)
|
||||
- Ingress (only Proxy outposts)
|
||||
- HTTPRoute (only Proxy outposts, when the Gateway API resources are installed in the target cluster, and the `kubernetes_httproute_parent_refs` setting is set, see below)
|
||||
- Traefik Middleware (only Proxy outposts with forward auth enabled)
|
||||
|
||||
The following outpost settings are used:
|
||||
@ -24,6 +25,8 @@ The following outpost settings are used:
|
||||
- `kubernetes_ingress_annotations`: Any additional annotations to add to the ingress object, for example cert-manager
|
||||
- `kubernetes_ingress_secret_name`: Name of the secret that is used for TLS connections, can be empty to disable TLS config
|
||||
- `kubernetes_ingress_class_name`: Optionally set the ingress class used for the generated ingress, requires authentik 2022.11.0
|
||||
- `kubernetes_httproute_parent_refs`: Define which Gateways the HTTPRoute wants to be attached to.
|
||||
- `kubernetes_httproute_annotations`: Any additional annotations to add to the HTTPRoute object
|
||||
- `kubernetes_service_type`: Service kind created, can be set to LoadBalancer for LDAP outposts for example
|
||||
- `kubernetes_disabled_components`: Disable any components of the kubernetes integration, can be any of
|
||||
- 'secret'
|
||||
@ -32,6 +35,7 @@ The following outpost settings are used:
|
||||
- 'prometheus servicemonitor'
|
||||
- 'ingress'
|
||||
- 'traefik middleware'
|
||||
- 'httproute'
|
||||
- `kubernetes_image_pull_secrets`: If the above docker image is in a private repository, use these secrets to pull. (NOTE: The secret must be created manually in the namespace first.)
|
||||
- `kubernetes_json_patches`: Applies an RFC 6902 compliant JSON patch to the Kubernetes objects.
|
||||
|
||||
|
@ -66,6 +66,10 @@ Starting with authentik 2022.11.0, the following checks can also be done with th
|
||||
- Check the password hash against the database of [Have I Been Pwned](https://haveibeenpwned.com/). Only the first 5 characters of the hashed password are transmitted, the rest is compared in authentik
|
||||
- Check the password against the password complexity checker [zxcvbn](https://github.com/dropbox/zxcvbn), which detects weak password on various metrics.
|
||||
|
||||
### Password Uniqueness Policy
|
||||
|
||||
This policy prevents users from reusing their previous passwords when setting a new password. For detailed information, see [Password Uniqueness Policy](./unique_password.md).
|
||||
|
||||
### Reputation Policy
|
||||
|
||||
authentik keeps track of failed login attempts by source IP and attempted username. These values are saved as scores. Each failed login decreases the score for the client IP as well as the targeted username by 1 (one).
|
||||
|
46
website/docs/customize/policies/unique_password.md
Normal file
46
website/docs/customize/policies/unique_password.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
title: Password Uniqueness Policy
|
||||
sidebar_label: Password Uniqueness Policy
|
||||
support_level: authentik
|
||||
tags:
|
||||
- policy
|
||||
- password
|
||||
- security
|
||||
- enterprise
|
||||
authentik_version: "2025.4.0"
|
||||
authentik_enterprise: true
|
||||
---
|
||||
|
||||
The Password Uniqueness policy prevents users from reusing their previous passwords when setting a new password. To use this feature, you will need to create a Password Uniqueness policy, using the instructions below.
|
||||
|
||||
## How it works
|
||||
|
||||
This policy maintains a record of previously used passwords for each user. When a new password is created, it is compared against this historical log. If a match is found with any previous password, the policy is not met, and the user is required to choose a different password.
|
||||
|
||||
The password history is maintained automatically when this policy is in use. Old password hashes are stored securely in authentik's database.
|
||||
|
||||
:::info
|
||||
This policy takes effect after the first password change following policy activation. Before that first change, there's no password history data to compare against.
|
||||
:::
|
||||
|
||||
## Integration with other policies
|
||||
|
||||
For comprehensive password security, consider using this policy alongside:
|
||||
|
||||
- [Password Policy](./index.md#password-policy) - To enforce password complexity rules
|
||||
- [Password-Expiry Policy](./index.md#password-expiry-policy) - To enforce regular password rotation
|
||||
|
||||
## Implement a Password Uniqueness policy
|
||||
|
||||
To implement a policy that prevents users from reusing their previous passwords, follow these steps:
|
||||
|
||||
1. In the Admin interface, navigate to **Customization** > **Policies**.
|
||||
2. Click **Create** to define a new Password Uniqueness Policy.
|
||||
- **Name**: provide a descriptive name for the policy.
|
||||
- **Password field**: enter the name of the input field to check for the new password. By default, if no custom flows are used, the field name is `password`. This field name must match the field name used in your Prompt stage.
|
||||
- **Number of previous passwords to check**: enter the number of past passwords that you want to set as the number of previous passwords that are checked and stored for each user, with a default of 1. For instance, if set to 3, users will not be able to reuse any of their last 3 passwords.
|
||||
3. Bind the policy to your **password prompt stage**: For example, if you're using the `default-password-change` flow, edit the `default-password-change-prompt` stage and add the policy in the **Validation Policies** section.
|
||||
|
||||
:::info
|
||||
Password history records are stored securely and cannot be used to reconstruct original passwords.
|
||||
:::
|
@ -70,6 +70,9 @@ To check if your config has been applied correctly, you can run the following co
|
||||
- `AUTHENTIK_POSTGRESQL__USER`: Database user
|
||||
- `AUTHENTIK_POSTGRESQL__PORT`: Database port, defaults to 5432
|
||||
- `AUTHENTIK_POSTGRESQL__PASSWORD`: Database password, defaults to the environment variable `POSTGRES_PASSWORD`
|
||||
{/* TODO: Temporarily deactivated feature, see https://github.com/goauthentik/authentik/issues/14320 */}
|
||||
{/* - `AUTHENTIK_POSTGRESQL__USE_POOL`: Use a [connection pool](https://docs.djangoproject.com/en/stable/ref/databases/#connection-pool) for PostgreSQL connections. Defaults to `false`. :ak-version[2025.4] */}
|
||||
- `AUTHENTIK_POSTGRESQL__POOL_OPTIONS`: Extra configuration to pass to the [ConnectionPool object](https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool) when it is created. Must be a base64-encoded JSON dictionary. Ignored when `USE_POOL` is set to `false`. :ak-version[2025.4]
|
||||
- `AUTHENTIK_POSTGRESQL__USE_PGBOUNCER`: Adjust configuration to support connection to PgBouncer. Deprecated, see below
|
||||
- `AUTHENTIK_POSTGRESQL__USE_PGPOOL`: Adjust configuration to support connection to Pgpool. Deprecated, see below
|
||||
- `AUTHENTIK_POSTGRESQL__SSLMODE`: Strictness of ssl verification. Defaults to `"verify-ca"`
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,9 +27,9 @@ This guide outlines the critical components to back up and restore in authentik.
|
||||
### Backup
|
||||
|
||||
- **Role:** Manages temporary data:
|
||||
- User sessions (lost data = users must reauthenticate).
|
||||
- Pending tasks (e.g., queued emails, outpost syncs).
|
||||
- **Impact of Loss:** Service interruptions (e.g., users logged out), and potential permanent data loss (e.g., queued emails).
|
||||
- Cache
|
||||
- **Impact of Loss:** Temporary performance loss (while cache gets rebuilt), and potential permanent data loss (e.g., queued emails).
|
||||
- **Backup Guidance:**
|
||||
- Use Redis' [`SAVE`](https://redis.io/commands/save) or [`BGSAVE`](https://redis.io/commands/bgsave).
|
||||
- **Official Documentation:** [Redis Persistence](https://redis.io/docs/management/persistence/)
|
||||
|
@ -0,0 +1,66 @@
|
||||
---
|
||||
title: "Initial permissions"
|
||||
description: "Set permissions for object creation."
|
||||
authentik_version: "2025.4.0"
|
||||
authentik_preview: true
|
||||
---
|
||||
|
||||
Initial permissions automatically assigns [object-level permissions](./permissions.md#object-permissions) between a newly created object and its creator.
|
||||
|
||||
The purpose of initial permissions is to assign a specific user (or role) a set of pre-selected permissions that are required for them to accomplish their tasks.
|
||||
|
||||
An authentik administrator creates an initial permissions object (a set of selected permissions) and then associates it with either: 1) an individual user 2) a role - in which case everyone in a group with that role will have the same initial permissions.
|
||||
|
||||
## Common use cases
|
||||
|
||||
Imagine you have a new team tasked with creating [flows](../../add-secure-apps/flows-stages/flow/index.md) and [stages](../../add-secure-apps/flows-stages/stages/index.md). These team members need the ability to view and manage all the flow and stage objects created by other team members. However, they should not have permissions to perform any other actions within the Admin interface.
|
||||
|
||||
In the example use case above, the specific objects that the users or role create and manage could be any object. For example, you might have a team responsible for creating new users and managing those user objects, but they should not be able to create flows, blueprints, or brands.
|
||||
|
||||
## High-level workflow
|
||||
|
||||
The fundamental steps to implement initial permissions are as follows:
|
||||
|
||||
1. Create a role. Initial permissions will be assigned whenever a user with this role creates a new object.
|
||||
2. Create a group, and assign the new role to it, and add any members that you want to use the initial permissions set. You can also create new users later, and add them to the group.
|
||||
3. Create an initial permissions object, and add all needed permissions to it.
|
||||
4. Optionally, create additional users and add them to the group to which the role is assigned.
|
||||
|
||||
Because the new initial permissions object is coupled with the role (and that role is assigned to a group), the initial permissions object is applied automatically to any new objects (users or flows or any object) that the member user creates.
|
||||
|
||||
:::info
|
||||
Typically, initial permissions are assigned to a user or role that is not a super-user nor administrator. In this scenario, the administrator needs to verify that the user has the `Can view Admin interface` permission (which allows the user to access the Admin interface). For details, see Step 5 below.
|
||||
|
||||
Be aware that any rights beyond viewing the Admin interface will need to be assigned as well; for example, if you want a non-administrator user to be able to create flows in the Admin interface, you need to grant those global permissions to add flows.
|
||||
:::
|
||||
|
||||
## Create and implement initial permissions
|
||||
|
||||
To create a new set of initial permissions and apply them to either a single user or a role (and every user with that role), follow these steps:
|
||||
|
||||
1. Log in to authentik as an administrator, and open the authentik Admin interface.
|
||||
|
||||
2. [Create a new role](../roles/manage_roles.md): navigate to **Directory** > **Roles** and click **Create**.
|
||||
|
||||
3. [Create a new group](../groups/manage_groups.mdx): navigate to **Directory** > **Groups** and click **Create**. After creating the group:
|
||||
|
||||
- [assign the new role to the group](../groups/manage_groups.mdx#assign-a-role-to-a-group)
|
||||
- [add any members](../user/user_basic_operations.md#add-a-user-to-a-group) that require the initial permissions. You can add already existing users, or [create new users](../user/user_basic_operations.md#create-a-user).
|
||||
|
||||
4. Create an initial permissions object: navigate to **Directory** > **Initial Permissions** and click **Create**. Configure the following settings:
|
||||
|
||||
- **Name**: Provide a descriptive name for the new initial permissions object.
|
||||
|
||||
- **Role**: Select the role to which you want to apply initial permissions. When a member of a group with this assigned role creates an object, initial permissions will be applied to that object.
|
||||
|
||||
- **Mode**: select whether you want to attach the initial permission to a _role_ or to a _single user_.
|
||||
|
||||
- **Role**: select this to allow everyone with that role (i.e. everyone in a group to which this role is assigned) to be able to see each others' objects.
|
||||
|
||||
- **User**: select this to apply the initial permissions _only_ to a user
|
||||
|
||||
- **Permissions**: select all permissions to add to the initial permissions object.
|
||||
|
||||
5. To ensure that the user or role (whichever you selected in the **Mode** configuration step above) to whom you assign the initial permissions _also_ has access to the Admin interface, check to see if the users also need [the global permission `Can view admin interface`](./manage_permissions#assign-can-view-admin-interface-permissions). Furthermore, verify that the user(s) has the global permissions to add specific objects.
|
||||
|
||||
6. Optionally, create new users and add them to the group. Each new user added to the group will automatically have the set of permissions included within the initial permissions object.
|
@ -3,7 +3,9 @@ title: "Manage permissions"
|
||||
description: "Learn how to use global and object permissions in authentik."
|
||||
---
|
||||
|
||||
Refer to the following topics for instructions to view and manage permissions. To learn more about the concepts and fundamanetals of authentik permissions, refer to [About Permissions](./permissions.md).
|
||||
For instructions on viewing and managing permissions, see the following topics.To learn more about the concepts and fundamentals of authentik permissions, refer to [About Permissions](./permissions.md).
|
||||
|
||||
To learn about using Initial Permissions, a pre-defined set of permissions, refer to our [documentation](./initial_permissions.mdx).
|
||||
|
||||
## View permissions
|
||||
|
||||
@ -30,7 +32,7 @@ To view _object_ permissions for a specific user or role:
|
||||
|
||||
### View stage permissions
|
||||
|
||||
\_These instructions apply to all objects that **do not** have a detail page.\_\_
|
||||
_These instructions apply to all objects that **do not** have a detail page._
|
||||
|
||||
1. Go to the Admin interface and navigate to **Flows and Stages -> Stages**.
|
||||
2. On the row for the specific stage whose permissions you want to view, click the **lock icon**.
|
||||
@ -68,14 +70,30 @@ To assign or remove _global_ permissions for a user:
|
||||
6. In the **Assign permission to user** box, click the plus sign (**+**) and then click the checkbox beside each permission that you want to assign to the user. To remove permissions, deselect the checkbox.
|
||||
7. Click **Add**, and then click **Assign** to save your changes and close the box.
|
||||
|
||||
### Assign or remove permissions on a specific group
|
||||
### Assign `Can view Admin interface` permissions
|
||||
|
||||
You can grant regular users, who are not superusers nor Admins, the right to view the Admin interface. This can be useful in scenarios where you have a team who needs to be able to create certain objects (flows, other users, etc) but who should not have full access to the Admin interface.
|
||||
|
||||
To assign the `Can view Admin interface` permission to a user (follow the same steps for a role):
|
||||
|
||||
1. Go to the Admin interface and navigate to **Directory -> User**.
|
||||
2. Select a specific user the clicking on the user's name.
|
||||
3. Click the **Permissions** tab at the top of the page.
|
||||
4. Click **Assigned Global Permissions** to the left.
|
||||
5. In the **Assign permissions** area, click **Assign Permission**.
|
||||
6. In the **Assign permission to user** box, click the plus sign (**+**), enter `admin` in the Search field and click the search icon.
|
||||
7. Select the returned permission, click **Add**, and then click **Assign** to save your changes and close the box.
|
||||
|
||||
Be aware that any rights beyond viewing the Admin interface will need to be assigned as well; for example, if you want a non-administrator user to be able to create flows in the Admin interface, you need to grant those global permissions to add flows.
|
||||
|
||||
### Assign or remove object permissions on a group
|
||||
|
||||
:::info
|
||||
Note that groups themselves do not have permissions. Rather, users and roles have permissions assigned that allow them to create, modify, delete, etc., a group.
|
||||
Also there are no global permissions for groups.
|
||||
:::
|
||||
|
||||
To assign or remove _object_ permissions on a specific group by users and roles:
|
||||
To assign or remove _object_ permissions on a specific group for users and roles:
|
||||
|
||||
1. Go to the Admin interface and navigate to **Directory -> Groups**.
|
||||
2. Select a specific group by clicking the group's name.
|
||||
|
@ -18,6 +18,8 @@ There are two main types of permissions in authentik:
|
||||
- [**Global permissions**](#global-permissions)
|
||||
- [**Object permissions**](#object-permissions)
|
||||
|
||||
Additionally, authentik employs _initial permissions_ to streamline the process of granting object-level permissions when an object (user or role) is created. This feature enables an Admin to proactively assign specific rights to a user for object creation, as well as for viewing and managing those objects and other objects created by individuals in the same role. For more details, refer to [Initial permissions](./initial_permissions.mdx).
|
||||
|
||||
### Global permissions
|
||||
|
||||
Global permissions define who can do what on a global level across the entire system. Some examples in authentik are the ability to add new [flows](../../add-secure-apps/flows-stages/flow/index.md) or to create a URL for users to recover their login credentials.
|
||||
|
@ -31,7 +31,7 @@ Starting with authentik version 2025.2, the permission to change super-user stat
|
||||
|
||||
To [add or remove users](../user/user_basic_operations.md#add-a-user-to-a-group) from the group, or to manage permissions assigned to the group, click on the name of the group to go to the group's detail page and then click on the **Permissions** tab.
|
||||
|
||||
For more information about permissions, refer to [Assign or remove permissions for a specific group](../access-control/manage_permissions.md#assign-or-remove-permissions-on-a-specific-group).
|
||||
For more information about permissions, refer to [Assign or remove permissions for a specific group](../access-control/manage_permissions.md#assign-or-remove-object-permissions-on-a-group).
|
||||
|
||||
## Delete a group
|
||||
|
||||
@ -47,7 +47,7 @@ You can assign a role to a group, and then all users in the group inherit the pe
|
||||
|
||||
## Delegating group member management:ak-version[2024.4]
|
||||
|
||||
To give a specific Role or User the ability to manage group members, the following permissions need to be granted on the matching Group object:
|
||||
To give a specific role or user the ability to manage group members, the following permissions need to be granted on the matching group object:
|
||||
|
||||
- Can view group
|
||||
- Can add user to group
|
||||
|
@ -7,66 +7,79 @@ support_level: community
|
||||
|
||||
The following placeholders are used in this guide:
|
||||
|
||||
- `ad.company` is the Name of the Active Directory domain.
|
||||
- `ad.company` is the name of the Active Directory domain.
|
||||
- `authentik.company` is the FQDN of the authentik install.
|
||||
|
||||
## Active Directory setup
|
||||
## Active Directory configuration
|
||||
|
||||
1. Open Active Directory Users and Computers
|
||||
To support the integration of Active Directory with authentik, you need to create a service account in Active Directory.
|
||||
|
||||
2. Create a user in Active Directory, matching your naming scheme
|
||||
1. Open **Active Directory Users and Computers** on a domain controller or computer with **Active Directory Remote Server Administration Tools** installed.
|
||||
2. Navigate to an Organizational Unit, right click on it, and select **New** > **User**.
|
||||
3. Create a service account, matching your naming scheme, for example:
|
||||
|
||||

|
||||
|
||||
3. Give the User a password, generated using for example `pwgen 64 1` or `openssl rand 36 | base64 -w 0`.
|
||||
4. Set the password for the service account. Ensure that the **Reset user password and force password change at next logon** option is not checked.
|
||||
|
||||
4. Open the Delegation of Control Wizard by right-clicking the domain and selecting "All Tasks".
|
||||
Either one of the following commands can be used to generate the password:
|
||||
|
||||
5. Select the authentik service user you've just created.
|
||||
```sh
|
||||
pwgen 64 1
|
||||
```
|
||||
|
||||
6. Ensure the "Reset user password and force password change at next logon" Option is checked.
|
||||
```sh
|
||||
openssl rand 36 | base64 -w 0
|
||||
```
|
||||
|
||||
5. Open the **Delegation of Control Wizard** by right-clicking the domain Active Directory Users and Computers, and selecting **All Tasks**.
|
||||
6. Select the authentik service account that you've just created.
|
||||
7. Grant these additional permissions (only required when _User password writeback_ is enabled on the LDAP source in authentik, and dependent on your AD Domain)
|
||||
|
||||

|
||||
|
||||
7. Grant these additional permissions (only required when _Sync users' password_ is enabled, and dependent on your AD Domain)
|
||||
## authentik Setup
|
||||
|
||||
To support the integration of authentik with Active Directory, you will need to create a new LDAP Source in authentik.
|
||||
|
||||
1. Log in to authentik as an admin, and open the authentik Admin interface.
|
||||
2. Navigate to **Directory** > **Federation & Social login**.
|
||||
3. Click **Create** and select **LDAP Source** as the type.
|
||||
4. Provide a name, slug, and the following required configurations:
|
||||
|
||||
Under **Connection Settings**:
|
||||
|
||||
- **Server URI**: `ldap://ad.company`
|
||||
|
||||
:::note
|
||||
For authentik to be able to write passwords back to Active Directory, make sure to use `ldaps://` as a prefix. You can verify that LDAPS is working by opening the `ldp.exe` tool on a domain controller and attempting a connection to the server via port 636. If a connection can be established, LDAPS is functioning as expected. More information can be found in the [Microsoft LDAPS documentation](https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/ldap-over-ssl-connection-issues).
|
||||
|
||||
Multiple servers can be specified by separating URIs with a comma (e.g. `ldap://dc1.ad.company,ldap://dc2.ad.company`). If a DNS entry with multiple records is used, authentik will select a random entry when first connecting.
|
||||
:::
|
||||
|
||||
- **Bind CN**: `<service account>@ad.company`
|
||||
- **Bind Password**: the password of the service account created in the previous section.
|
||||
- **Base DN**: the base DN which you want authentik to sync.
|
||||
|
||||
Under **LDAP Attribute Mapping**:
|
||||
|
||||
- **User Property Mappings**: select all Mappings which start with "authentik default LDAP" and "authentik default Active Directory"
|
||||
- **Group Property Mappings**: select "authentik default LDAP Mapping: Name"
|
||||
|
||||
Under **Additional Settings** _(optional)_ configurations that may need to be adjusted based on the setup of your domain:
|
||||
|
||||
- **Group**: if enabled, all synchronized groups will be given this group as a parent.
|
||||
- **Addition User/Group DN**: additional DN which is _prepended_ to your Base DN configured above, to limit the scope of synchronization for Users and Groups.
|
||||
- **User object filter**: which objects should be considered users (e.g. `(objectClass=user)`). For Active Directory set it to `(&(objectClass=user)(!(objectClass=computer)))` to exclude Computer accounts.
|
||||
- **Group object filter**: which objects should be considered groups (e.g `(objectClass=group)`).
|
||||
- **Lookup using a user attribute**: acquire group membership from a User object attribute (`memberOf`) instead of a Group attribute (`member`). This works with directories and nested groups memberships (Active Directory, RedHat IDM/FreeIPA), using `memberOf:1.2.840.113556.1.4.1941:` as the group membership field.
|
||||
- **Group membership field**: the user object attribute or the group object attribute that determines the group membership of a user (e.g. `member`). If **Lookup using a user attribute** is set, this should be a user object attribute, otherwise a group object attribute.
|
||||
- **Object uniqueness field**: a user attribute that contains a unique identifier (e.g. `objectSid`).
|
||||
|
||||
5. Click **Finish** to save the LDAP Source. An LDAP synchronization will begin in the background. Once completed, you can view the summary by navigating to **Dashboards** > **System Tasks**:
|
||||
|
||||

|
||||
|
||||
Additional info: https://support.microfocus.com/kb/doc.php?id=7023371
|
||||
6. To finalise the Active Directory setup, you need to enable the backend "authentik LDAP" in the Password Stage.
|
||||
|
||||
## authentik Setup
|
||||
|
||||
In authentik, create a new LDAP Source in Directory -> Federation & Social login.
|
||||
|
||||
Use these settings:
|
||||
|
||||
- Server URI: `ldap://ad.company`
|
||||
|
||||
For authentik to be able to write passwords back to Active Directory, make sure to use `ldaps://`. You can test to verify LDAPS is working using `ldp.exe`.
|
||||
|
||||
You can specify multiple servers by separating URIs with a comma, like `ldap://dc1.ad.company,ldap://dc2.ad.company`.
|
||||
|
||||
When using a DNS entry with multiple Records, authentik will select a random entry when first connecting.
|
||||
|
||||
- Bind CN: `<name of your service user>@ad.company`
|
||||
- Bind Password: The password you've given the user above
|
||||
- Base DN: The base DN which you want authentik to sync
|
||||
- Property mappings: Control/Command-select all Mappings which start with "authentik default LDAP" and "authentik default Active Directory"
|
||||
- Group property mappings: Select "authentik default LDAP Mapping: Name"
|
||||
|
||||
Additional settings that might need to be adjusted based on the setup of your domain:
|
||||
|
||||
- Group: If enabled, all synchronized groups will be given this group as a parent.
|
||||
- Addition User/Group DN: Additional DN which is _prepended_ to your Base DN configured above to limit the scope of synchronization for Users and Groups
|
||||
- User object filter: Which objects should be considered users. For Active Directory set it to `(&(objectClass=user)(!(objectClass=computer)))` to exclude Computer accounts.
|
||||
- Group object filter: Which objects should be considered groups.
|
||||
- Group membership field: Which user field saves the group membership
|
||||
- Object uniqueness field: A user field which contains a unique Identifier
|
||||
|
||||
After you save the source, a synchronization will start in the background. When its done, you can see the summary under Dashboards -> System Tasks.
|
||||
|
||||

|
||||
|
||||
To finalise the Active Directory setup, you need to enable the backend "authentik LDAP" in the Password Stage.
|
||||
|
||||

|
||||

|
||||
|
@ -12,18 +12,13 @@ For FreeIPA, follow the [FreeIPA Integration](../../directory-sync/freeipa/index
|
||||
|
||||
## Configuration options for LDAP sources
|
||||
|
||||
To create or edit a source in authentik, open the Admin interface and navigate to **Directory -> Ferderation and Social login**. There you can create a new LDAP source, or edit an existing one, using the following settings.
|
||||
To create or edit a source in authentik, open the Admin interface and navigate to **Directory > Ferderation and Social login**. There you can create a new LDAP source, or edit an existing one, using the following settings.
|
||||
|
||||
- **Enabled**: Toggle this option on to allow authentik to use the defined LDAP source.
|
||||
|
||||
- **Update internal password on login**: When the user logs in to authentik using the LDAP password backend, the password is stored as a hashed value in authentik. Toggle off (default setting) if you do not want to store the hashed passwords in authentik.
|
||||
|
||||
- **Sync users**: Enable or disable user synchronization between authentik and the LDAP source.
|
||||
|
||||
- **User password writeback**: Enable this option if you want to write password changes that are made in authentik back to LDAP.
|
||||
|
||||
- **Sync groups**: Enable/disable group synchronization. Groups are synced in the background every 5 minutes.
|
||||
|
||||
- **Parent group**: Optionally set this group as the parent group for all synced groups. An example use case of this would be to import Active Directory groups under a root `imported-from-ad` group.
|
||||
|
||||
#### Connection settings
|
||||
@ -34,13 +29,9 @@ To create or edit a source in authentik, open the Admin interface and navigate t
|
||||
- **Use Server URI for SNI verification**: this setting is required for servers using TLS 1.3+
|
||||
|
||||
- **TLS Verification Certificate**: Specify a keypair to validate the remote certificate.
|
||||
|
||||
- **TLS Client authentication**: Client certificate keypair to authenticate against the LDAP Server's Certificate.
|
||||
|
||||
- **Bind CN**: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`.
|
||||
|
||||
- **Bind password**: Password used during the bind process.
|
||||
|
||||
- **Base DN**: Base DN (distinguished name) used for all LDAP queries.
|
||||
|
||||
#### LDAP Attribute mapping
|
||||
@ -54,19 +45,13 @@ To create or edit a source in authentik, open the Admin interface and navigate t
|
||||
#### Additional Settings
|
||||
|
||||
- **Group**: Parent group for all the groups imported from LDAP.
|
||||
|
||||
- **User path**: Path template for all new users created.
|
||||
|
||||
- **Addition User DN**: Prepended to the base DN for user queries.
|
||||
|
||||
- **Addition Group DN**: Prepended to the base DN for group queries.
|
||||
|
||||
- **User object filter**: Consider objects matching this filter to be users.
|
||||
|
||||
- **Group object filter**: Consider objects matching this filter to be groups.
|
||||
|
||||
- **Group membership field**: This field contains the user's group memberships.
|
||||
|
||||
- **Lookup using a user attribute**: Acquire group membership from a User object attribute (`memberOf`) instead of a Group attribute (`member`). This works with directories with nested groups memberships (Active Directory, RedHat IDM/FreeIPA), using `memberOf:1.2.840.113556.1.4.1941:` as the group membership field.
|
||||
- **Group membership field**: The user object attribute or the group object attribute that determines the group membership for a user. If **Lookup using a user attribute** is set, this should be a user object attribute, otherwise a group object attribute.
|
||||
- **Object uniqueness field**: This field contains a unique identifier.
|
||||
|
||||
## LDAP source property mappings
|
||||
@ -90,14 +75,14 @@ return {
|
||||
|
||||
LDAP property mappings are used when you define a LDAP source. These mappings define which LDAP property maps to which authentik property. By default, the following mappings are created:
|
||||
|
||||
- authentik default Active Directory Mapping: givenName
|
||||
- authentik default Active Directory Mapping: sAMAccountName
|
||||
- authentik default Active Directory Mapping: sn
|
||||
- authentik default Active Directory Mapping: userPrincipalName
|
||||
- authentik default LDAP Mapping: mail
|
||||
- authentik default LDAP Mapping: Name
|
||||
- authentik default OpenLDAP Mapping: cn
|
||||
- authentik default OpenLDAP Mapping: uid
|
||||
- `authentik default Active Directory Mapping: givenName`
|
||||
- `authentik default Active Directory Mapping: sAMAccountName`
|
||||
- `authentik default Active Directory Mapping: sn`
|
||||
- `authentik default Active Directory Mapping: userPrincipalName`
|
||||
- `authentik default LDAP Mapping: mail`
|
||||
- `authentik default LDAP Mapping: Name`
|
||||
- `authentik default OpenLDAP Mapping: cn`
|
||||
- `authentik default OpenLDAP Mapping: uid`
|
||||
|
||||
These are configured with most common LDAP setups.
|
||||
|
||||
|
@ -2,13 +2,14 @@ import { generateVersionDropdown } from "./src/utils.js";
|
||||
import apiReference from "./docs/developer-docs/api/reference/sidebar";
|
||||
|
||||
const releases = [
|
||||
"releases/2025/v2025.4",
|
||||
"releases/2025/v2025.2",
|
||||
"releases/2024/v2024.12",
|
||||
"releases/2024/v2024.10",
|
||||
{
|
||||
type: "category",
|
||||
label: "Previous versions",
|
||||
items: [
|
||||
"releases/2024/v2024.10",
|
||||
"releases/2024/v2024.8",
|
||||
"releases/2024/v2024.6",
|
||||
"releases/2024/v2024.4",
|
||||
@ -396,6 +397,7 @@ export default {
|
||||
"customize/policies/expression/managing_flow_context_keys",
|
||||
],
|
||||
},
|
||||
"customize/policies/unique_password",
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -494,6 +496,7 @@ export default {
|
||||
items: [
|
||||
"users-sources/access-control/permissions",
|
||||
"users-sources/access-control/manage_permissions",
|
||||
"users-sources/access-control/initial_permissions",
|
||||
],
|
||||
},
|
||||
{
|
||||
|
Reference in New Issue
Block a user