Compare commits

..

32 Commits

Author SHA1 Message Date
66a4970014 release: 2024.10.2 2024-11-14 17:05:40 +01:00
7ab9300761 website/docs: 2024.10.2 release notes (cherry-pick #12025) (#12026)
website/docs: 2024.10.2 release notes (#12025)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-14 17:00:32 +01:00
a2eccd5022 core: use versioned_script for path only (cherry-pick #12003) (#12023)
core: use versioned_script for path only (#12003)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-14 14:03:03 +01:00
31aeaa247f providers/oauth2: fix manual device code entry (cherry-pick #12017) (#12019)
providers/oauth2: fix manual device code entry (#12017)

* providers/oauth2: fix manual device code entry



* make code input a char field to prevent leading 0s from being cut off



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-13 21:59:10 +01:00
f49008bbb6 crypto: validate that generated certificate's name is unique (cherry-pick #12015) (#12016)
crypto: validate that generated certificate's name is unique (#12015)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-13 17:05:59 +01:00
feb13c8ee5 providers/proxy: fix Issuer when AUTHENTIK_HOST_BROWSER is set (cherry-pick #11968) (#12005)
providers/proxy: fix Issuer when AUTHENTIK_HOST_BROWSER is set (#11968)

correctly use host_browser's hostname as host header for token requests to ensure Issuer is identical

Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-13 00:59:10 +01:00
d5ef831718 web: bump API Client version (#11992)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	web/package-lock.json
#	web/package.json
2024-11-11 14:30:24 +01:00
64676819ec blueprints: add default Password policy (cherry-pick #11793) (#11993)
blueprints: add default Password policy (#11793)

* add password policy to default password change flow

This change complies with the minimal compositional requirements by
NIST SP 800-63 Digital Identity Guidelines. See
https://pages.nist.gov/800-63-4/sp800-63b.html#password

More work is needed to comply with other parts of the Guidelines,
specifically

> If the chosen password is found on the blocklist, the CSP or verifier
> [...] SHALL provide the reason for rejection.

and

> Verifiers SHALL offer guidance to the subscriber to assist the user in
> choosing a strong password. This is particularly important following
> the rejection of a password on the blocklist as it discourages trivial
> modification of listed weak passwords.

* add docs for default Password policy

* remove HIBP from default Password policy

* add zxcvbn to default Password policy

* add fallback password error message to password policy, fix validation policy



* reword docs




* add HIBP caveat




* separate policy into separate blueprint



* use password policy for oobe flow



* kiss



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2024-11-11 13:54:44 +01:00
7ed268fef4 stages/captcha: Run interactive captcha in Frame (cherry-pick #11857) (#11991)
stages/captcha: Run interactive captcha in Frame (#11857)

* initial turnstile frame



* add interactive flag



* add interactive support for all



* fix missing migration



* don't hide in identification stage if interactive



* fixup



* require less hacky css



* update docs



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-11 13:31:01 +01:00
f6526d1be9 stages/password: use recovery flow from brand (cherry-pick #11953) (#11969)
stages/password: use recovery flow from brand (#11953)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-08 16:56:16 +01:00
12f8b4566b website/docs: fix slug matching redirect URI causing broken refresh (cherry-pick #11950) (#11954)
website/docs: fix slug matching redirect URI causing broken refresh (#11950)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-07 19:26:49 +01:00
665de8ef22 release: 2024.10.1 2024-11-05 18:06:32 +01:00
9eaa723bf8 website/docs: 2024.10.1 Release Notes (cherry-pick #11926) (#11928)
website/docs: `2024.10.1` Release Notes (#11926)

* fix API Changes in `2024.10` changelog

* add `2024.10.1` API Changes to changelog

* add changes in `2024.10.1` to changelog

* change `details` to `h3` in changelog

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2024-11-05 18:05:00 +01:00
b2ca9c8cbc website: remove RC disclaimer for version 2024.10 (cherry-pick #11871) (#11920)
website: remove RC disclaimer for version 2024.10 (#11871)

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2024-11-05 12:13:11 +01:00
7927392100 website/docs: add info about invalidation flow, default flows in general (cherry-pick #11800) (#11921)
website/docs: add info about invalidation flow, default flows in general (#11800)

* restructure

* tweak

* fix header

* added more definitions

* jens excellent idea

* restructure the Layouts content

* tweaks

* links fix

* links still

* fighting links and cache

* argh links

* ditto

* remove link

* anothe link

* Jens' edit

* listed default flows set by brand

* add links back

* tweaks

* used import for list

* tweak

* rewrite some stuff



* format



* mangled rebase, fixed

* bump

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2024-11-05 12:12:59 +01:00
d8d07e32cb website: fix docs redirect (cherry-pick #11873) (#11922)
website: fix docs redirect (#11873)

fix docs redirect

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2024-11-05 12:12:46 +01:00
f7c5d329eb website/docs: fix release notes to say Federation (cherry-pick #11889) (#11923)
website/docs: fix release notes to say Federation (#11889)

* fix Federation

* typo

* added back should

* slooooow down

---------

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
2024-11-05 12:12:27 +01:00
92dec32547 enterprise/rac: fix API Schema for invalidation_flow (cherry-pick #11907) (#11908)
enterprise/rac: fix API Schema for invalidation_flow (#11907)

* enterprise/rac: fix API Schema for invalidation_flow



* fix tests



* add tests



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-04 20:42:41 +01:00
510feccd31 core: add None check to a device's extra_description (cherry-pick #11904) (#11906)
core: add `None` check to a device's `extra_description` (#11904)

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2024-11-04 18:12:34 +01:00
364a9a1f02 web: fix missing status code on failed build (#11903)
* fix missing status code on failed build

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

* fix locale

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

* fix format

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	web/xliff/tr.xlf
2024-11-04 18:06:22 +01:00
40cbb7567b providers/oauth2: fix size limited index for tokens (cherry-pick #11879) (#11905)
providers/oauth2: fix size limited index for tokens (#11879)

* providers/oauth2: fix size limited index for tokens

I preserved the migrations as comments so the index IDs and migration
IDs remain searchable without accessing git history.

* rename migration file to more descriptive

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2024-11-04 18:05:55 +01:00
8ad0f63994 website: update supported versions (cherry-pick #11841) (#11872)
website: update supported versions (#11841)

update supported versions

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2024-10-31 12:59:54 +01:00
6ce33ab912 root: bumpversion 2024.10 (#11865)
release: 2024.10.0
2024-10-30 22:45:48 +01:00
d96b577abd web/admin: fix code-based MFA toggle not working in wizard (cherry-pick #11854) (#11855)
web/admin: fix code-based MFA toggle not working in wizard (#11854)

closes #11834

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-10-29 20:19:54 +01:00
8c547589f6 sources/kerberos: add kiprop to ignored system principals (cherry-pick #11852) (#11853)
sources/kerberos: add kiprop to ignored system principals (#11852)

Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2024-10-29 17:31:32 +01:00
3775e5b84f website: 2024.10 Release Notes (cherry-pick #11839) (#11840)
website: 2024.10 Release Notes (#11839)

* generate diffs and changelog

* add 2024.10 release notes

* reorder release note highlights

* lint website

* reorder release note new features

* reword Kerberos




* extend JWE description




---------

Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-10-28 17:27:59 +01:00
fa30339f65 website/docs: remove � (cherry-pick #11823) (#11835)
website/docs: remove � (#11823)

remove 

Signed-off-by: Tobias <5702338+T0biii@users.noreply.github.com>
Co-authored-by: Tobias <5702338+T0biii@users.noreply.github.com>
2024-10-28 13:21:02 +01:00
e825eda106 website/docs: Update social-logins github (cherry-pick #11822) (#11836)
website/docs: Update social-logins github (#11822)

Update index.md

Signed-off-by: Tobias <5702338+T0biii@users.noreply.github.com>
Co-authored-by: Tobias <5702338+T0biii@users.noreply.github.com>
2024-10-28 13:20:38 +01:00
246cae3dfa lifecycle: fix kdc5-config missing (cherry-pick #11826) (#11829)
lifecycle: fix kdc5-config missing (#11826)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-10-28 01:15:50 +01:00
6cfd2bd1af website/docs: update preview status of different features (cherry-pick #11817) (#11818)
website/docs: update preview status of different features (#11817)

* remove preview from RAC



* add preview page instead of info box



* remove preview from rbac



* add preview to gdtc



* add preview to kerberos source



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-10-25 21:42:45 +02:00
f0e4f93fe6 lifecycle: fix missing krb5 deps for full testing in image (cherry-pick #11815) (#11816)
lifecycle: fix missing krb5 deps for full testing in image (#11815)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-10-25 18:46:55 +02:00
434aa57ba7 release: 2024.10.0-rc1 2024-10-25 17:26:39 +02:00
95 changed files with 2383 additions and 10375 deletions

View File

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

View File

@ -2,7 +2,7 @@
from os import environ
__version__ = "2024.10.0"
__version__ = "2024.10.2"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -7,7 +7,7 @@ API Browser - {{ brand.branding_title }}
{% endblock %}
{% block head %}
{% versioned_script "dist/standalone/api-browser/index-%v.js" %}
<script src="{% versioned_script 'dist/standalone/api-browser/index-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
{% endblock %}

View File

@ -27,7 +27,8 @@ def blueprint_tester(file_name: Path) -> Callable:
base = Path("blueprints/")
rel_path = Path(file_name).relative_to(base)
importer = Importer.from_string(BlueprintInstance(path=str(rel_path)).retrieve())
self.assertTrue(importer.validate()[0])
validation, logs = importer.validate()
self.assertTrue(validation, logs)
self.assertTrue(importer.apply())
return tester

View File

@ -1,5 +1,6 @@
"""Authenticator Devices API Views"""
from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework.fields import (
@ -40,7 +41,11 @@ class DeviceSerializer(MetaNameSerializer):
def get_extra_description(self, instance: Device) -> str:
"""Get extra description"""
if isinstance(instance, WebAuthnDevice):
return instance.device_type.description
return (
instance.device_type.description
if instance.device_type
else _("Extra description not available")
)
if isinstance(instance, EndpointDevice):
return instance.data.get("deviceSignals", {}).get("deviceModel")
return ""

View File

@ -15,8 +15,8 @@
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
{% versioned_script "dist/poly-%v.js" %}
{% versioned_script "dist/standalone/loading/index-%v.js" %}
<script src="{% versioned_script 'dist/poly-%v.js' %}" type="module"></script>
<script src="{% versioned_script 'dist/standalone/loading/index-%v.js' %}" type="module"></script>
{% block head %}
{% endblock %}
<meta name="sentry-trace" content="{{ sentry_trace }}" />

View File

@ -3,7 +3,7 @@
{% load authentik_core %}
{% block head %}
{% versioned_script "dist/admin/AdminInterface-%v.js" %}
<script src="{% versioned_script 'dist/admin/AdminInterface-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
{% include "base/header_js.html" %}

View File

@ -3,7 +3,7 @@
{% load authentik_core %}
{% block head %}
{% versioned_script "dist/user/UserInterface-%v.js" %}
<script src="{% versioned_script 'dist/user/UserInterface-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
{% include "base/header_js.html" %}

View File

@ -2,7 +2,6 @@
from django import template
from django.templatetags.static import static as static_loader
from django.utils.safestring import mark_safe
from authentik import get_full_version
@ -12,10 +11,4 @@ register = template.Library()
@register.simple_tag()
def versioned_script(path: str) -> str:
"""Wrapper around {% static %} tag that supports setting the version"""
returned_lines = [
(
f'<script src="{static_loader(path.replace("%v", get_full_version()))}'
'" type="module"></script>'
),
]
return mark_safe("".join(returned_lines)) # nosec
return static_loader(path.replace("%v", get_full_version()))

View File

@ -24,6 +24,7 @@ from rest_framework.fields import (
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
@ -181,7 +182,10 @@ class CertificateDataSerializer(PassiveSerializer):
class CertificateGenerationSerializer(PassiveSerializer):
"""Certificate generation parameters"""
common_name = CharField()
common_name = CharField(
validators=[UniqueValidator(queryset=CertificateKeyPair.objects.all())],
source="name",
)
subject_alt_name = CharField(required=False, allow_blank=True, label=_("Subject-alt name"))
validity_days = IntegerField(initial=365)
alg = ChoiceField(default=PrivateKeyAlg.RSA, choices=PrivateKeyAlg.choices)
@ -242,11 +246,10 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet):
def generate(self, request: Request) -> Response:
"""Generate a new, self-signed certificate-key pair"""
data = CertificateGenerationSerializer(data=request.data)
if not data.is_valid():
return Response(data.errors, status=400)
data.is_valid(raise_exception=True)
raw_san = data.validated_data.get("subject_alt_name", "")
sans = raw_san.split(",") if raw_san != "" else []
builder = CertificateBuilder(data.validated_data["common_name"])
builder = CertificateBuilder(data.validated_data["name"])
builder.alg = data.validated_data["alg"]
builder.build(
subject_alt_names=sans,

View File

@ -89,6 +89,17 @@ class TestCrypto(APITestCase):
self.assertIsInstance(ext[1], DNSName)
self.assertEqual(ext[1].value, "baz")
def test_builder_api_duplicate(self):
"""Test Builder (via API)"""
cert = create_test_cert()
self.client.force_login(create_test_admin_user())
res = self.client.post(
reverse("authentik_api:certificatekeypair-generate"),
data={"common_name": cert.name, "subject_alt_name": "bar,baz", "validity_days": 3},
)
self.assertEqual(res.status_code, 400)
self.assertJSONEqual(res.content, {"common_name": ["This field must be unique."]})
def test_builder_api_empty_san(self):
"""Test Builder (via API)"""
self.client.force_login(create_test_admin_user())

View File

@ -16,13 +16,28 @@ class RACProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer):
class Meta:
model = RACProvider
fields = ProviderSerializer.Meta.fields + [
fields = [
"pk",
"name",
"authentication_flow",
"authorization_flow",
"property_mappings",
"component",
"assigned_application_slug",
"assigned_application_name",
"assigned_backchannel_application_slug",
"assigned_backchannel_application_name",
"verbose_name",
"verbose_name_plural",
"meta_model_name",
"settings",
"outpost_set",
"connection_expiry",
"delete_token_on_disconnect",
]
extra_kwargs = ProviderSerializer.Meta.extra_kwargs
extra_kwargs = {
"authorization_flow": {"required": True, "allow_null": False},
}
class RACProviderViewSet(UsedByMixin, ModelViewSet):

View File

@ -3,7 +3,7 @@
{% load authentik_core %}
{% block head %}
{% versioned_script "dist/enterprise/rac/index-%v.js" %}
<script src="{% versioned_script 'dist/enterprise/rac/index-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<link rel="icon" href="{{ tenant.branding_favicon }}">

View File

@ -0,0 +1,46 @@
"""Test RAC Provider"""
from datetime import timedelta
from time import mktime
from unittest.mock import MagicMock, patch
from django.urls import reverse
from django.utils.timezone import now
from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.enterprise.license import LicenseKey
from authentik.enterprise.models import License
from authentik.lib.generators import generate_id
class TestAPI(APITestCase):
"""Test Provider API"""
def setUp(self) -> None:
self.user = create_test_admin_user()
@patch(
"authentik.enterprise.license.LicenseKey.validate",
MagicMock(
return_value=LicenseKey(
aud="",
exp=int(mktime((now() + timedelta(days=3000)).timetuple())),
name=generate_id(),
internal_users=100,
external_users=100,
)
),
)
def test_create(self):
"""Test creation of RAC Provider"""
License.objects.create(key=generate_id())
self.client.force_login(self.user)
response = self.client.post(
reverse("authentik_api:racprovider-list"),
data={
"name": generate_id(),
"authorization_flow": create_test_flow().pk,
},
)
self.assertEqual(response.status_code, 201)

View File

@ -68,7 +68,6 @@ class TestEndpointsAPI(APITestCase):
"name": self.provider.name,
"authentication_flow": None,
"authorization_flow": None,
"invalidation_flow": None,
"property_mappings": [],
"connection_expiry": "hours=8",
"delete_token_on_disconnect": False,
@ -121,7 +120,6 @@ class TestEndpointsAPI(APITestCase):
"name": self.provider.name,
"authentication_flow": None,
"authorization_flow": None,
"invalidation_flow": None,
"property_mappings": [],
"component": "ak-provider-rac-form",
"assigned_application_slug": self.app.slug,
@ -151,7 +149,6 @@ class TestEndpointsAPI(APITestCase):
"name": self.provider.name,
"authentication_flow": None,
"authorization_flow": None,
"invalidation_flow": None,
"property_mappings": [],
"component": "ak-provider-rac-form",
"assigned_application_slug": self.app.slug,

View File

@ -18,7 +18,7 @@ window.authentik.flow = {
{% endblock %}
{% block head %}
{% versioned_script "dist/flow/FlowInterface-%v.js" %}
<script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script>
<style>
:root {
--ak-flow-background: url("{{ flow.background_url }}");

View File

@ -89,6 +89,10 @@ class PasswordPolicy(Policy):
def passes_static(self, password: str, request: PolicyRequest) -> PolicyResult:
"""Check static rules"""
error_message = self.error_message
if error_message == "":
error_message = _("Invalid password.")
if len(password) < self.length_min:
LOGGER.debug("password failed", check="static", reason="length")
return PolicyResult(False, self.error_message)

View File

@ -11,13 +11,16 @@ class Migration(migrations.Migration):
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddIndex(
model_name="accesstoken",
index=models.Index(fields=["token"], name="authentik_p_token_4bc870_idx"),
),
migrations.AddIndex(
model_name="refreshtoken",
index=models.Index(fields=["token"], name="authentik_p_token_1a841f_idx"),
),
]
# Original preserved
# See https://github.com/goauthentik/authentik/issues/11874
# operations = [
# migrations.AddIndex(
# model_name="accesstoken",
# index=models.Index(fields=["token"], name="authentik_p_token_4bc870_idx"),
# ),
# migrations.AddIndex(
# model_name="refreshtoken",
# index=models.Index(fields=["token"], name="authentik_p_token_1a841f_idx"),
# ),
# ]
operations = []

View File

@ -11,21 +11,24 @@ class Migration(migrations.Migration):
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveIndex(
model_name="accesstoken",
name="authentik_p_token_4bc870_idx",
),
migrations.RemoveIndex(
model_name="refreshtoken",
name="authentik_p_token_1a841f_idx",
),
migrations.AddIndex(
model_name="accesstoken",
index=models.Index(fields=["token", "provider"], name="authentik_p_token_f99422_idx"),
),
migrations.AddIndex(
model_name="refreshtoken",
index=models.Index(fields=["token", "provider"], name="authentik_p_token_a1d921_idx"),
),
]
# Original preserved
# See https://github.com/goauthentik/authentik/issues/11874
# operations = [
# migrations.RemoveIndex(
# model_name="accesstoken",
# name="authentik_p_token_4bc870_idx",
# ),
# migrations.RemoveIndex(
# model_name="refreshtoken",
# name="authentik_p_token_1a841f_idx",
# ),
# migrations.AddIndex(
# model_name="accesstoken",
# index=models.Index(fields=["token", "provider"], name="authentik_p_token_f99422_idx"),
# ),
# migrations.AddIndex(
# model_name="refreshtoken",
# index=models.Index(fields=["token", "provider"], name="authentik_p_token_a1d921_idx"),
# ),
# ]
operations = []

View File

@ -0,0 +1,31 @@
# Generated by Django 5.0.9 on 2024-10-31 14:28
import django.contrib.postgres.indexes
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0040_provider_invalidation_flow"),
("authentik_providers_oauth2", "0022_remove_accesstoken_session_id_and_more"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RunSQL("DROP INDEX IF EXISTS authentik_p_token_f99422_idx;"),
migrations.RunSQL("DROP INDEX IF EXISTS authentik_p_token_a1d921_idx;"),
migrations.AddIndex(
model_name="accesstoken",
index=django.contrib.postgres.indexes.HashIndex(
fields=["token"], name="authentik_p_token_e00883_hash"
),
),
migrations.AddIndex(
model_name="refreshtoken",
index=django.contrib.postgres.indexes.HashIndex(
fields=["token"], name="authentik_p_token_32e2b7_hash"
),
),
]

View File

@ -13,6 +13,7 @@ from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
from dacite.core import from_dict
from django.contrib.postgres.indexes import HashIndex
from django.db import models
from django.http import HttpRequest
from django.templatetags.static import static
@ -418,7 +419,7 @@ class AccessToken(SerializerModel, ExpiringModel, BaseGrantModel):
class Meta:
indexes = [
models.Index(fields=["token", "provider"]),
HashIndex(fields=["token"]),
]
verbose_name = _("OAuth2 Access Token")
verbose_name_plural = _("OAuth2 Access Tokens")
@ -464,7 +465,7 @@ class RefreshToken(SerializerModel, ExpiringModel, BaseGrantModel):
class Meta:
indexes = [
models.Index(fields=["token", "provider"]),
HashIndex(fields=["token"]),
]
verbose_name = _("OAuth2 Refresh Token")
verbose_name_plural = _("OAuth2 Refresh Tokens")

View File

@ -3,6 +3,7 @@
from urllib.parse import urlencode
from django.urls import reverse
from rest_framework.test import APIClient
from authentik.core.models import Application, Group
from authentik.core.tests.utils import create_test_admin_user, create_test_brand, create_test_flow
@ -34,7 +35,10 @@ class TesOAuth2DeviceInit(OAuthTestCase):
self.brand.flow_device_code = self.device_flow
self.brand.save()
def test_device_init(self):
self.api_client = APIClient()
self.api_client.force_login(self.user)
def test_device_init_get(self):
"""Test device init"""
res = self.client.get(reverse("authentik_providers_oauth2_root:device-login"))
self.assertEqual(res.status_code, 302)
@ -48,6 +52,76 @@ class TesOAuth2DeviceInit(OAuthTestCase):
),
)
def test_device_init_post(self):
"""Test device init"""
res = self.api_client.get(reverse("authentik_providers_oauth2_root:device-login"))
self.assertEqual(res.status_code, 302)
self.assertEqual(
res.url,
reverse(
"authentik_core:if-flow",
kwargs={
"flow_slug": self.device_flow.slug,
},
),
)
res = self.api_client.get(
reverse(
"authentik_api:flow-executor",
kwargs={
"flow_slug": self.device_flow.slug,
},
),
)
self.assertEqual(res.status_code, 200)
self.assertJSONEqual(
res.content,
{
"component": "ak-provider-oauth2-device-code",
"flow_info": {
"background": "/static/dist/assets/images/flow_background.jpg",
"cancel_url": "/flows/-/cancel/",
"layout": "stacked",
"title": self.device_flow.title,
},
},
)
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
)
Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
token = DeviceToken.objects.create(
provider=provider,
)
res = self.api_client.post(
reverse(
"authentik_api:flow-executor",
kwargs={
"flow_slug": self.device_flow.slug,
},
),
data={
"component": "ak-provider-oauth2-device-code",
"code": token.user_code,
},
)
self.assertEqual(res.status_code, 200)
self.assertJSONEqual(
res.content,
{
"component": "xak-flow-redirect",
"to": reverse(
"authentik_core:if-flow",
kwargs={
"flow_slug": provider.authorization_flow.slug,
},
),
},
)
def test_no_flow(self):
"""Test no flow"""
self.brand.flow_device_code = None

View File

@ -5,7 +5,7 @@ from typing import Any
from django.http import HttpRequest, HttpResponse
from django.utils.translation import gettext as _
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, IntegerField
from rest_framework.fields import CharField
from structlog.stdlib import get_logger
from authentik.brands.models import Brand
@ -47,6 +47,9 @@ class CodeValidatorView(PolicyAccessView):
self.provider = self.token.provider
self.application = self.token.provider.application
def post(self, request: HttpRequest, *args, **kwargs):
return self.get(request, *args, **kwargs)
def get(self, request: HttpRequest, *args, **kwargs):
scope_descriptions = UserInfoView().get_scope_descriptions(self.token.scope, self.provider)
planner = FlowPlanner(self.provider.authorization_flow)
@ -122,7 +125,7 @@ class OAuthDeviceCodeChallenge(Challenge):
class OAuthDeviceCodeChallengeResponse(ChallengeResponse):
"""Response that includes the user-entered device code"""
code = IntegerField()
code = CharField()
component = CharField(default="ak-provider-oauth2-device-code")
def validate_code(self, code: int) -> HttpResponse | None:

View File

@ -17,6 +17,7 @@ class CaptchaStageSerializer(StageSerializer):
"private_key",
"js_url",
"api_url",
"interactive",
"score_min_threshold",
"score_max_threshold",
"error_on_invalid_score",

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.9 on 2024-10-30 14:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_captcha", "0003_captchastage_error_on_invalid_score_and_more"),
]
operations = [
migrations.AddField(
model_name="captchastage",
name="interactive",
field=models.BooleanField(default=False),
),
]

View File

@ -9,11 +9,13 @@ from authentik.flows.models import Stage
class CaptchaStage(Stage):
"""Verify the user is human using Google's reCaptcha."""
"""Verify the user is human using Google's reCaptcha/other compatible CAPTCHA solutions."""
public_key = models.TextField(help_text=_("Public key, acquired your captcha Provider."))
private_key = models.TextField(help_text=_("Private key, acquired your captcha Provider."))
interactive = models.BooleanField(default=False)
score_min_threshold = models.FloatField(default=0.5) # Default values for reCaptcha
score_max_threshold = models.FloatField(default=1.0) # Default values for reCaptcha

View File

@ -3,7 +3,7 @@
from django.http.response import HttpResponse
from django.utils.translation import gettext as _
from requests import RequestException
from rest_framework.fields import CharField
from rest_framework.fields import BooleanField, CharField
from rest_framework.serializers import ValidationError
from structlog.stdlib import get_logger
@ -24,10 +24,12 @@ PLAN_CONTEXT_CAPTCHA = "captcha"
class CaptchaChallenge(WithUserInfoChallenge):
"""Site public key"""
site_key = CharField()
js_url = CharField()
component = CharField(default="ak-stage-captcha")
site_key = CharField(required=True)
js_url = CharField(required=True)
interactive = BooleanField(required=True)
def verify_captcha_token(stage: CaptchaStage, token: str, remote_ip: str):
"""Validate captcha token"""
@ -103,6 +105,7 @@ class CaptchaStageView(ChallengeStageView):
data={
"js_url": self.executor.current_stage.js_url,
"site_key": self.executor.current_stage.public_key,
"interactive": self.executor.current_stage.interactive,
}
)

View File

@ -223,6 +223,7 @@ class IdentificationStageView(ChallengeStageView):
{
"js_url": current_stage.captcha_stage.js_url,
"site_key": current_stage.captcha_stage.public_key,
"interactive": current_stage.captcha_stage.interactive,
}
if current_stage.captcha_stage
else None

View File

@ -21,7 +21,7 @@ from authentik.flows.challenge import (
WithUserInfoChallenge,
)
from authentik.flows.exceptions import StageInvalidException
from authentik.flows.models import Flow, FlowDesignation, Stage
from authentik.flows.models import Flow, Stage
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
from authentik.flows.stage import ChallengeStageView
from authentik.lib.utils.reflection import path_to_class
@ -141,11 +141,11 @@ class PasswordStageView(ChallengeStageView):
"allow_show_password": self.executor.current_stage.allow_show_password,
}
)
recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY)
if recovery_flow.exists():
recovery_flow: Flow | None = self.request.brand.flow_recovery
if recovery_flow:
recover_url = reverse(
"authentik_core:if-flow",
kwargs={"flow_slug": recovery_flow.first().slug},
kwargs={"flow_slug": recovery_flow.slug},
)
challenge.initial_data["recovery_url"] = self.request.build_absolute_uri(recover_url)
return challenge

View File

@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch
from django.core.exceptions import PermissionDenied
from django.urls import reverse
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.core.tests.utils import create_test_admin_user, create_test_brand, create_test_flow
from authentik.flows.markers import StageMarker
from authentik.flows.models import FlowDesignation, FlowStageBinding
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
@ -57,6 +57,9 @@ class TestPasswordStage(FlowTestCase):
def test_recovery_flow_link(self):
"""Test link to the default recovery flow"""
flow = create_test_flow(designation=FlowDesignation.RECOVERY)
brand = create_test_brand()
brand.flow_recovery = flow
brand.save()
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
session = self.client.session

View File

@ -101,7 +101,6 @@ entries:
- !KeyOf prompt-field-email
- !KeyOf prompt-field-password
- !KeyOf prompt-field-password-repeat
validation_policies: []
id: stage-default-oobe-password
identifiers:
name: stage-default-oobe-password

View File

@ -2,6 +2,17 @@ version: 1
metadata:
name: Default - Password change flow
entries:
- attrs:
check_static_rules: true
check_zxcvbn: true
length_min: 8
password_field: password
zxcvbn_score_threshold: 2
error_message: Password needs to be 8 characters or longer.
identifiers:
name: default-password-change-password-policy
model: authentik_policies_password.passwordpolicy
id: default-password-change-password-policy
- attrs:
designation: stage_configuration
name: Change Password
@ -39,6 +50,8 @@ entries:
fields:
- !KeyOf prompt-field-password
- !KeyOf prompt-field-password-repeat
validation_policies:
- !KeyOf default-password-change-password-policy
identifiers:
name: default-password-change-prompt
id: default-password-change-prompt

View File

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://goauthentik.io/blueprints/schema.json",
"type": "object",
"title": "authentik 2024.10.0 Blueprint schema",
"title": "authentik 2024.10.2 Blueprint schema",
"required": [
"version",
"entries"
@ -6974,7 +6974,7 @@
"spnego_server_name": {
"type": "string",
"title": "Spnego server name",
"description": "Force the use of a specific server name for SPNEGO"
"description": "Force the use of a specific server name for SPNEGO. Must be in the form HTTP@hostname"
},
"spnego_keytab": {
"type": "string",
@ -9781,6 +9781,10 @@
"minLength": 1,
"title": "Api url"
},
"interactive": {
"type": "boolean",
"title": "Interactive"
},
"score_min_threshold": {
"type": "number",
"title": "Score min threshold"
@ -13383,12 +13387,6 @@
"title": "Authorization flow",
"description": "Flow used when authorizing this provider."
},
"invalidation_flow": {
"type": "string",
"format": "uuid",
"title": "Invalidation flow",
"description": "Flow used ending the session from a provider."
},
"property_mappings": {
"type": "array",
"items": {

View File

@ -31,7 +31,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.10.0}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.10.2}
restart: unless-stopped
command: server
environment:
@ -52,7 +52,7 @@ services:
- postgresql
- redis
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.10.0}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.10.2}
restart: unless-stopped
command: worker
environment:

2
go.mod
View File

@ -29,7 +29,7 @@ require (
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2024100.1
goauthentik.io/api/v3 v3.2024083.13
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.23.0
golang.org/x/sync v0.8.0

4
go.sum
View File

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

View File

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

View File

@ -23,6 +23,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
"goauthentik.io/api/v3"
"goauthentik.io/internal/config"
"goauthentik.io/internal/outpost/ak"
"goauthentik.io/internal/outpost/proxyv2/constants"
"goauthentik.io/internal/outpost/proxyv2/hs256"
@ -121,6 +122,14 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server, old
bs := string(h.Sum([]byte(*p.ClientId)))
sessionName := fmt.Sprintf("authentik_proxy_%s", bs[:8])
// When HOST_BROWSER is set, use that as Host header for token requests to make the issuer match
// otherwise we use the internally configured authentik_host
tokenEndpointHost := server.API().Outpost.Config["authentik_host"].(string)
if config.Get().AuthentikHostBrowser != "" {
tokenEndpointHost = config.Get().AuthentikHostBrowser
}
publicHTTPClient := web.NewHostInterceptor(c, tokenEndpointHost)
a := &Application{
Host: externalHost.Host,
log: muxLogger,
@ -131,7 +140,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server, old
tokenVerifier: verifier,
proxyConfig: p,
httpClient: c,
publicHostHTTPClient: web.NewHostInterceptor(c, server.API().Outpost.Config["authentik_host"].(string)),
publicHostHTTPClient: publicHTTPClient,
mux: mux,
errorTemplates: templates.GetTemplates(),
ak: server.API(),

View File

@ -14,8 +14,10 @@ type hostInterceptor struct {
}
func (t hostInterceptor) RoundTrip(r *http.Request) (*http.Response, error) {
r.Host = t.host
r.Header.Set("X-Forwarded-Proto", t.scheme)
if r.Host != t.host {
r.Host = t.host
r.Header.Set("X-Forwarded-Proto", t.scheme)
}
return t.inner.RoundTrip(r)
}

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-28 00:09+0000\n"
"POT-Creation-Date: 2024-10-23 16:39+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -2614,7 +2614,12 @@ msgid "Captcha Stages"
msgstr ""
#: authentik/stages/captcha/stage.py
msgid "Invalid captcha response. Retrying may solve this issue."
msgid "Unknown error"
msgstr ""
#: authentik/stages/captcha/stage.py
#, python-brace-format
msgid "Failed to validate token: {error}"
msgstr ""
#: authentik/stages/captcha/stage.py

View File

@ -11,17 +11,15 @@
# Marco Vitale, 2024
# Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2024
# albanobattistella <albanobattistella@gmail.com>, 2024
# Nicola Mersi, 2024
# tom max, 2024
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-28 00:09+0000\n"
"POT-Creation-Date: 2024-10-18 00:09+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: tom max, 2024\n"
"Last-Translator: albanobattistella <albanobattistella@gmail.com>, 2024\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"
@ -585,28 +583,6 @@ msgstr "Limite massimo di connessioni raggiunto."
msgid "(You are already connected in another tab/window)"
msgstr "(Sei già connesso in un'altra scheda/finestra)"
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
msgid "Endpoint Authenticator Google Device Trust Connector Stage"
msgstr ""
"Fase di autenticazione per la verifica dispositivo Google tramite endpoint"
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
msgid "Endpoint Authenticator Google Device Trust Connector Stages"
msgstr ""
"Fasi di autenticazione per la verifica dispositivo Google tramite endpoint"
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
msgid "Endpoint Device"
msgstr "Dispositivo di Accesso"
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
msgid "Endpoint Devices"
msgstr "Dispositivi di Accesso"
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/stage.py
msgid "Verifying your browser..."
msgstr "Verifica del tuo browser..."
#: authentik/enterprise/stages/source/models.py
msgid ""
"Amount of time a user can take to return from the source to continue the "
@ -2041,124 +2017,6 @@ msgstr ""
msgid "Used recovery-link to authenticate."
msgstr "Utilizzato il link di recupero per autenticarsi."
#: authentik/sources/kerberos/models.py
msgid "Kerberos realm"
msgstr "Dominio Kerberos"
#: authentik/sources/kerberos/models.py
msgid "Custom krb5.conf to use. Uses the system one by default"
msgstr ""
"krb5.conf personalizzato da usare. Usa la configurazione di sistema per "
"default"
#: authentik/sources/kerberos/models.py
msgid "Sync users from Kerberos into authentik"
msgstr "Sincronizza utenti da Kerberos a authentik"
#: authentik/sources/kerberos/models.py
msgid "When a user changes their password, sync it back to Kerberos"
msgstr "Quando un utente cambia la sua password, sincronizzala in Kerberos"
#: authentik/sources/kerberos/models.py
msgid "Principal to authenticate to kadmin for sync."
msgstr "Entità da autenticare su kadmin per la sincronizzazione."
#: authentik/sources/kerberos/models.py
msgid "Password to authenticate to kadmin for sync"
msgstr "Password per autenticarsi in kadmin per sincronizzare"
#: authentik/sources/kerberos/models.py
msgid ""
"Keytab to authenticate to kadmin for sync. Must be base64-encoded or in the "
"form TYPE:residual"
msgstr ""
"Keytab per autenticarsi su kadmin per la sincronizzazione. Deve essere con "
"codifica base64 o nel formato TYPE:residual"
#: authentik/sources/kerberos/models.py
msgid ""
"Credentials cache to authenticate to kadmin for sync. Must be in the form "
"TYPE:residual"
msgstr ""
"Credenziali memorizzate nella cache per autenticarsi su kadmin per la "
"sincronizzazione. Devono essere nel formato TYPE:residual"
#: authentik/sources/kerberos/models.py
msgid ""
"Force the use of a specific server name for SPNEGO. Must be in the form "
"HTTP@hostname"
msgstr ""
"Forza l'uso di un nome server specifico per SPNEGO. Deve essere nel formato "
"HTTP@nomehost"
#: authentik/sources/kerberos/models.py
msgid "SPNEGO keytab base64-encoded or path to keytab in the form FILE:path"
msgstr ""
"keytab SPNEGO con codifica base64 o percorso del keytab nel formato "
"FILE:percorso"
#: authentik/sources/kerberos/models.py
msgid "Credential cache to use for SPNEGO in form type:residual"
msgstr ""
"Cache delle credenziali da utilizzare per SPNEGO nella forma type:residual"
#: authentik/sources/kerberos/models.py
msgid ""
"If enabled, the authentik-stored password will be updated upon login with "
"the Kerberos password backend"
msgstr ""
"Se abilitato, la password memorizzata in authentik verrà aggiornata al login"
" nel backend Kerberos"
#: authentik/sources/kerberos/models.py
msgid "Kerberos Source"
msgstr "Sorgente Kerberos"
#: authentik/sources/kerberos/models.py
msgid "Kerberos Sources"
msgstr "Sorgenti Kerberos"
#: authentik/sources/kerberos/models.py
msgid "Kerberos Source Property Mapping"
msgstr "Mappa delle proprietà della sorgente kerberos"
#: authentik/sources/kerberos/models.py
msgid "Kerberos Source Property Mappings"
msgstr "Mappe delle proprietà della sorgente kerberos"
#: authentik/sources/kerberos/models.py
msgid "User Kerberos Source Connection"
msgstr "Connessione sorgente dell'utente kerberos"
#: authentik/sources/kerberos/models.py
msgid "User Kerberos Source Connections"
msgstr " Connessioni alle sorgente dell'utente kerberos"
#: authentik/sources/kerberos/models.py
msgid "Group Kerberos Source Connection"
msgstr " Connessione sorgente del gruppo kerberos"
#: authentik/sources/kerberos/models.py
msgid "Group Kerberos Source Connections"
msgstr "Connessioni alle sorgenti del gruppo kerberos"
#: authentik/sources/kerberos/views.py
msgid "SPNEGO authentication required"
msgstr "autenticazione SPNEGO necessaria"
#: authentik/sources/kerberos/views.py
msgid ""
"\n"
" Make sure you have valid tickets (obtainable via kinit)\n"
" and configured the browser correctly.\n"
" Please contact your administrator.\n"
" "
msgstr ""
"\n"
"Assicurati di avere un ticket valido (ottenibile tramite kinit)\n"
" e di aver configurato correttamente il browser. \n"
"Contatta il tuo amministratore."
#: authentik/sources/ldap/api.py
msgid "Only a single LDAP Source with password synchronization is allowed"
msgstr ""
@ -2877,10 +2735,13 @@ msgid "Captcha Stages"
msgstr "Fasi Captcha"
#: authentik/stages/captcha/stage.py
msgid "Invalid captcha response. Retrying may solve this issue."
msgstr ""
"Risposta captcha non valida. Un nuovo tentativo potrebbe risolvere il "
"problema."
msgid "Unknown error"
msgstr "Errore sconosciuto"
#: authentik/stages/captcha/stage.py
#, python-brace-format
msgid "Failed to validate token: {error}"
msgstr "Impossibile convalidare il token: {error}"
#: authentik/stages/captcha/stage.py
msgid "Invalid captcha response"
@ -3253,10 +3114,6 @@ msgstr "Database utente + password app"
msgid "User database + LDAP password"
msgstr "Database utenti + password LDAP"
#: authentik/stages/password/models.py
msgid "User database + Kerberos password"
msgstr "Database utenti + password Kerberos"
#: authentik/stages/password/models.py
msgid "Selection of backends to test the password against."
msgstr "Selezione di backend su cui testare la password."

Binary file not shown.

View File

@ -15,7 +15,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-28 00:09+0000\n"
"POT-Creation-Date: 2024-10-23 16:39+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: deluxghost, 2024\n"
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
@ -2649,8 +2649,13 @@ msgid "Captcha Stages"
msgstr "验证码阶段"
#: authentik/stages/captcha/stage.py
msgid "Invalid captcha response. Retrying may solve this issue."
msgstr "无效的验证码响应。重试可能会解决此问题。"
msgid "Unknown error"
msgstr "未知错误"
#: authentik/stages/captcha/stage.py
#, python-brace-format
msgid "Failed to validate token: {error}"
msgstr "验证令牌失败:{error}"
#: authentik/stages/captcha/stage.py
msgid "Invalid captcha response"

View File

@ -14,7 +14,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-10-28 00:09+0000\n"
"POT-Creation-Date: 2024-10-23 16:39+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: deluxghost, 2024\n"
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
@ -2648,8 +2648,13 @@ msgid "Captcha Stages"
msgstr "验证码阶段"
#: authentik/stages/captcha/stage.py
msgid "Invalid captcha response. Retrying may solve this issue."
msgstr "无效的验证码响应。重试可能会解决此问题。"
msgid "Unknown error"
msgstr "未知错误"
#: authentik/stages/captcha/stage.py
#, python-brace-format
msgid "Failed to validate token: {error}"
msgstr "验证令牌失败:{error}"
#: authentik/stages/captcha/stage.py
msgid "Invalid captcha response"

View File

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

28
poetry.lock generated
View File

@ -3896,13 +3896,13 @@ pytest = ">=4.0.0"
[[package]]
name = "pytest-randomly"
version = "3.16.0"
version = "3.15.0"
description = "Pytest plugin to randomly order tests and control random.seed."
optional = false
python-versions = ">=3.9"
python-versions = ">=3.8"
files = [
{file = "pytest_randomly-3.16.0-py3-none-any.whl", hash = "sha256:8633d332635a1a0983d3bba19342196807f6afb17c3eef78e02c2f85dade45d6"},
{file = "pytest_randomly-3.16.0.tar.gz", hash = "sha256:11bf4d23a26484de7860d82f726c0629837cf4064b79157bd18ec9d41d7feb26"},
{file = "pytest_randomly-3.15.0-py3-none-any.whl", hash = "sha256:0516f4344b29f4e9cdae8bce31c4aeebf59d0b9ef05927c33354ff3859eeeca6"},
{file = "pytest_randomly-3.15.0.tar.gz", hash = "sha256:b908529648667ba5e54723088edd6f82252f540cc340d748d1fa985539687047"},
]
[package.dependencies]
@ -4354,13 +4354,13 @@ django-query = ["django (>=3.2)"]
[[package]]
name = "selenium"
version = "4.26.0"
version = "4.25.0"
description = "Official Python bindings for Selenium WebDriver"
optional = false
python-versions = ">=3.8"
files = [
{file = "selenium-4.26.0-py3-none-any.whl", hash = "sha256:48013f36e812de5b3948ef53d04e73f77bc923ee3e1d7d99eaf0618179081b99"},
{file = "selenium-4.26.0.tar.gz", hash = "sha256:f0780f85f10310aa5d085b81e79d73d3c93b83d8de121d0400d543a50ee963e8"},
{file = "selenium-4.25.0-py3-none-any.whl", hash = "sha256:3798d2d12b4a570bc5790163ba57fef10b2afee958bf1d80f2a3cf07c4141f33"},
{file = "selenium-4.25.0.tar.gz", hash = "sha256:95d08d3b82fb353f3c474895154516604c7f0e6a9a565ae6498ef36c9bac6921"},
]
[package.dependencies]
@ -4425,13 +4425,13 @@ tornado = ["tornado (>=6)"]
[[package]]
name = "service-identity"
version = "24.2.0"
version = "24.1.0"
description = "Service identity verification for pyOpenSSL & cryptography."
optional = false
python-versions = ">=3.8"
files = [
{file = "service_identity-24.2.0-py3-none-any.whl", hash = "sha256:6b047fbd8a84fd0bb0d55ebce4031e400562b9196e1e0d3e0fe2b8a59f6d4a85"},
{file = "service_identity-24.2.0.tar.gz", hash = "sha256:b8683ba13f0d39c6cd5d625d2c5f65421d6d707b013b375c355751557cbe8e09"},
{file = "service_identity-24.1.0-py3-none-any.whl", hash = "sha256:a28caf8130c8a5c1c7a6f5293faaf239bbfb7751e4862436920ee6f2616f568a"},
{file = "service_identity-24.1.0.tar.gz", hash = "sha256:6829c9d62fb832c2e1c435629b0a8c476e1929881f28bee4d20bc24161009221"},
]
[package.dependencies]
@ -4441,7 +4441,7 @@ pyasn1 = "*"
pyasn1-modules = "*"
[package.extras]
dev = ["coverage[toml] (>=5.0.2)", "idna", "mypy", "pyopenssl", "pytest", "types-pyopenssl"]
dev = ["pyopenssl", "service-identity[idna,mypy,tests]"]
docs = ["furo", "myst-parser", "pyopenssl", "sphinx", "sphinx-notfound-page"]
idna = ["idna"]
mypy = ["idna", "mypy", "types-pyopenssl"]
@ -4751,13 +4751,13 @@ wsproto = ">=0.14"
[[package]]
name = "twilio"
version = "9.3.6"
version = "9.3.5"
description = "Twilio API client and TwiML generator"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "twilio-9.3.6-py2.py3-none-any.whl", hash = "sha256:c5d7f4cfeb50a7928397b8f819c8f7fb2bb956a1a2cabbda1df1d7a40f9ce1d7"},
{file = "twilio-9.3.6.tar.gz", hash = "sha256:d42691f7fe1faaa5ba82942f169bfea4d7f01a0a542a456d82018fb49bd1f5b2"},
{file = "twilio-9.3.5-py2.py3-none-any.whl", hash = "sha256:d6a97a77b98cc176a61c960f11894af385bc1c11b93e2e8b79fdfb9601788fb0"},
{file = "twilio-9.3.5.tar.gz", hash = "sha256:608d78a903d403465aac1840c58a6546a090b7e222d2bf539a93c3831072880c"},
]
[package.dependencies]

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "authentik"
version = "2024.10.0"
version = "2024.10.2"
description = ""
authors = ["authentik Team <hello@goauthentik.io>"]

View File

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2024.10.0
version: 2024.10.2
description: Making authentication simple.
contact:
email: hello@goauthentik.io
@ -39220,7 +39220,10 @@ components:
type: string
js_url:
type: string
interactive:
type: boolean
required:
- interactive
- js_url
- pending_user
- pending_user_avatar
@ -39276,6 +39279,8 @@ components:
type: string
api_url:
type: string
interactive:
type: boolean
score_min_threshold:
type: number
format: double
@ -39322,6 +39327,8 @@ components:
api_url:
type: string
minLength: 1
interactive:
type: boolean
score_min_threshold:
type: number
format: double
@ -42975,7 +42982,8 @@ components:
readOnly: true
spnego_server_name:
type: string
description: Force the use of a specific server name for SPNEGO
description: Force the use of a specific server name for SPNEGO. Must be
in the form HTTP@hostname
spnego_ccache:
type: string
description: Credential cache to use for SPNEGO in form type:residual
@ -43144,7 +43152,8 @@ components:
be in the form TYPE:residual
spnego_server_name:
type: string
description: Force the use of a specific server name for SPNEGO
description: Force the use of a specific server name for SPNEGO. Must be
in the form HTTP@hostname
spnego_keytab:
type: string
writeOnly: true
@ -44934,7 +44943,8 @@ components:
minLength: 1
default: ak-provider-oauth2-device-code
code:
type: integer
type: string
minLength: 1
required:
- code
OAuthDeviceCodeFinishChallenge:
@ -47730,6 +47740,8 @@ components:
api_url:
type: string
minLength: 1
interactive:
type: boolean
score_min_threshold:
type: number
format: double
@ -48448,7 +48460,8 @@ components:
be in the form TYPE:residual
spnego_server_name:
type: string
description: Force the use of a specific server name for SPNEGO
description: Force the use of a specific server name for SPNEGO. Must be
in the form HTTP@hostname
spnego_keytab:
type: string
writeOnly: true
@ -49461,10 +49474,6 @@ components:
type: string
format: uuid
description: Flow used when authorizing this provider.
invalidation_flow:
type: string
format: uuid
description: Flow used ending the session from a provider.
property_mappings:
type: array
items:
@ -51696,10 +51705,6 @@ components:
type: string
format: uuid
description: Flow used when authorizing this provider.
invalidation_flow:
type: string
format: uuid
description: Flow used ending the session from a provider.
property_mappings:
type: array
items:
@ -51757,7 +51762,6 @@ components:
- assigned_backchannel_application_slug
- authorization_flow
- component
- invalidation_flow
- meta_model_name
- name
- outpost_set
@ -51781,10 +51785,6 @@ components:
type: string
format: uuid
description: Flow used when authorizing this provider.
invalidation_flow:
type: string
format: uuid
description: Flow used ending the session from a provider.
property_mappings:
type: array
items:
@ -51801,7 +51801,6 @@ components:
description: When set to true, connection tokens will be deleted upon disconnect.
required:
- authorization_flow
- invalidation_flow
- name
RadiusCheckAccess:
type: object

View File

@ -66,7 +66,6 @@ const rawCssImportMaps = [
'import PFSwitch from "@patternfly/patternfly/components/Switch/switch.css";',
'import PFTable from "@patternfly/patternfly/components/Table/table.css";',
'import PFTabs from "@patternfly/patternfly/components/Tabs/tabs.css";',
'import PFText from "@patternfly/patternfly/utilities/Text/text.css";',
'import PFTitle from "@patternfly/patternfly/components/Title/title.css";',
'import PFToggleGroup from "@patternfly/patternfly/components/ToggleGroup/toggle-group.css";',
'import PFToolbar from "@patternfly/patternfly/components/Toolbar/toolbar.css";',

View File

@ -119,13 +119,22 @@ async function buildOneSource(source, dest) {
Date.now() - start
}ms`,
);
return 0;
} catch (exc) {
console.error(`[${new Date(Date.now()).toISOString()}] Failed to build ${source}: ${exc}`);
return 1;
}
}
async function buildAuthentik(interfaces) {
await Promise.allSettled(interfaces.map(([source, dest]) => buildOneSource(source, dest)));
const code = await Promise.allSettled(
interfaces.map(([source, dest]) => buildOneSource(source, dest)),
);
const finalCode = code.reduce((a, res) => a + res.value, 0);
if (finalCode > 0) {
return 1;
}
return 0;
}
let timeoutId = null;
@ -163,11 +172,12 @@ if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] ===
});
} else if (process.argv.length > 2 && (process.argv[2] === "-p" || process.argv[2] === "--proxy")) {
// There's no watch-for-proxy, sorry.
await buildAuthentik(
interfaces.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
process.exit(
await buildAuthentik(
interfaces.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
),
);
process.exit(0);
} else {
// And the fallback: just build it.
await buildAuthentik(interfaces);
process.exit(await buildAuthentik(interfaces));
}

341
web/package-lock.json generated
View File

@ -23,7 +23,7 @@
"@floating-ui/dom": "^1.6.11",
"@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.6.0",
"@goauthentik/api": "^2024.10.0-1730331602",
"@goauthentik/api": "^2024.10.1-1731327664",
"@lit-labs/ssr": "^3.2.2",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2",
@ -1014,9 +1014,9 @@
}
},
"node_modules/@codemirror/commands": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.7.0.tgz",
"integrity": "sha512-+cduIZ2KbesDhbykV02K25A5xIVrquSPz4UxxYBemRlAT2aW8dhwUgLDwej7q/RJUHKk4nALYcR1puecDvbdqw==",
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.2.tgz",
"integrity": "sha512-Fq7eWOl1Rcbrfn6jD8FPCj9Auaxdm5nIK5RYOeW7ughnd/rY5AmPg6b+CfsG39ZHdwiwe8lde3q8uR7CF5S0yQ==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0",
@ -1775,9 +1775,9 @@
}
},
"node_modules/@goauthentik/api": {
"version": "2024.10.0-1730331602",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.10.0-1730331602.tgz",
"integrity": "sha512-VaXywdDCFkIs9RgmHVYt8jGf5xnc+czsu5ILEThNQOuXvBjkGa0J8aPWVSdfP++GiHnkjddWVFzJ6R6LOoHbWQ=="
"version": "2024.10.1-1731327664",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.10.1-1731327664.tgz",
"integrity": "sha512-svzKZAXsmsrSfGbTOhhFgE5kAb0vv2sIJAhXSYd1i7ua6OglZV6Qs531XhoK5QU8AFL55D8Un1U5QZ16ZFGANA=="
},
"node_modules/@goauthentik/web": {
"resolved": "",
@ -1953,9 +1953,9 @@
}
},
"node_modules/@inquirer/figures": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.7.tgz",
"integrity": "sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.6.tgz",
"integrity": "sha512-yfZzps3Cso2UbM7WlxKwZQh2Hs6plrbjs1QnzQDZhK2DgyCo6D8AaHps9olkNcUFlcYERMqU3uJSp1gmy3s/qQ==",
"dev": true,
"engines": {
"node": ">=18"
@ -2425,9 +2425,9 @@
}
},
"node_modules/@lezer/javascript": {
"version": "1.4.19",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.19.tgz",
"integrity": "sha512-j44kbR1QL26l6dMunZ1uhKBFteVGLVCBGNUD2sUaMnic+rbTviVuoK0CD1l9FTW31EueWvFFswCKMH7Z+M3JRA==",
"version": "1.4.18",
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.18.tgz",
"integrity": "sha512-Y8BeHOt4LtcxJgXwadtfSeWPrh0XzklcCHnCVT+vOsxqH4gWmunP2ykX+VVOlM/dusyVyiNfG3lv0f10UK+mgA==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.1.3",
@ -2507,9 +2507,9 @@
"license": "MIT"
},
"node_modules/@lit/context": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.3.tgz",
"integrity": "sha512-Auh37F4S0PZM93HTDfZWs97mmzaQ7M3vnTc9YvxAGyP3UItSK/8Fs0vTOGT+njuvOwbKio/l8Cx/zWL4vkutpQ==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.2.tgz",
"integrity": "sha512-S0nw2C6Tkm7fVX5TGYqeROGD+Z9Coa2iFpW+ysYBDH3YvCqOY3wVQvSgwbaliLJkjTnSEYCBe9qFqKV8WUFpVw==",
"dependencies": {
"@lit/reactive-element": "^1.6.2 || ^2.0.0"
}
@ -3517,6 +3517,12 @@
"win32"
]
},
"node_modules/@scarf/scarf": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz",
"integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==",
"hasInstallScript": true
},
"node_modules/@sec-ant/readable-stream": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
@ -3673,9 +3679,9 @@
}
},
"node_modules/@spotlightjs/overlay": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-2.6.0.tgz",
"integrity": "sha512-UnvWi6J8MTxhUHaBxd+k2mVyQh+0sJ5MImb/UfnEOA0WhNaFl2Foo/R7ByoOIDzDGT42+mZtfEyhJzNZ5naAaQ=="
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-2.5.2.tgz",
"integrity": "sha512-2YCxkTCRWn9Q4x6Aan0b43EvUJEgQBLvcws1c97LO7Cgnb0iKjiLIRW0Fa8f6PO8r9AcDvaFzhk5Z93YIkwlGQ=="
},
"node_modules/@spotlightjs/sidecar": {
"version": "1.8.0",
@ -3694,11 +3700,11 @@
}
},
"node_modules/@spotlightjs/spotlight": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-2.5.0.tgz",
"integrity": "sha512-tOlefTjOUuNGyHtt1+r1IdY5vq9Hq9Vi2HqPENZ9orS/12KMEK6rVFliWT0/IXJLH5LdunNGaw3kan08bsA+NQ==",
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-2.4.2.tgz",
"integrity": "sha512-d7wEvG6fyP9OsqgJ3fD2YZ2zjtD9MzIuOpqTg+LAT1FXl7yBK9LRrLW/LU6OvwRdDCzUsbnxUv0giJ5DjV+2Lw==",
"dependencies": {
"@spotlightjs/overlay": "2.6.0",
"@spotlightjs/overlay": "2.5.2",
"@spotlightjs/sidecar": "1.8.0",
"import-meta-resolve": "^4.1.0"
},
@ -5879,9 +5885,9 @@
"dev": true
},
"node_modules/@types/mocha": {
"version": "10.0.9",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz",
"integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==",
"version": "10.0.8",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.8.tgz",
"integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==",
"dev": true
},
"node_modules/@types/mute-stream": {
@ -5894,9 +5900,9 @@
}
},
"node_modules/@types/node": {
"version": "22.7.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz",
"integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==",
"version": "22.7.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz",
"integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -6077,16 +6083,16 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz",
"integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.0.tgz",
"integrity": "sha512-wORFWjU30B2WJ/aXBfOm1LX9v9nyt9D3jsSOxC3cCaTQGCW5k4jNpmjFv3U7p/7s4yvdjHzwtv2Sd2dOyhjS0A==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/type-utils": "8.8.1",
"@typescript-eslint/utils": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1",
"@typescript-eslint/scope-manager": "8.8.0",
"@typescript-eslint/type-utils": "8.8.0",
"@typescript-eslint/utils": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
@ -6110,15 +6116,15 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz",
"integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.0.tgz",
"integrity": "sha512-uEFUsgR+tl8GmzmLjRqz+VrDv4eoaMqMXW7ruXfgThaAShO9JTciKpEsB+TvnfFfbg5IpujgMXVV36gOJRLtZg==",
"dev": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/typescript-estree": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1",
"@typescript-eslint/scope-manager": "8.8.0",
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/typescript-estree": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0",
"debug": "^4.3.4"
},
"engines": {
@ -6138,13 +6144,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz",
"integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.0.tgz",
"integrity": "sha512-EL8eaGC6gx3jDd8GwEFEV091210U97J0jeEHrAYvIYosmEGet4wJ+g0SYmLu+oRiAwbSA5AVrt6DxLHfdd+bUg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1"
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -6155,13 +6161,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz",
"integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.0.tgz",
"integrity": "sha512-IKwJSS7bCqyCeG4NVGxnOP6lLT9Okc3Zj8hLO96bpMkJab+10HIfJbMouLrlpyOr3yrQ1cA413YPFiGd1mW9/Q==",
"dev": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "8.8.1",
"@typescript-eslint/utils": "8.8.1",
"@typescript-eslint/typescript-estree": "8.8.0",
"@typescript-eslint/utils": "8.8.0",
"debug": "^4.3.4",
"ts-api-utils": "^1.3.0"
},
@ -6179,9 +6185,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz",
"integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.0.tgz",
"integrity": "sha512-QJwc50hRCgBd/k12sTykOJbESe1RrzmX6COk8Y525C9l7oweZ+1lw9JiU56im7Amm8swlz00DRIlxMYLizr2Vw==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -6192,13 +6198,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz",
"integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.0.tgz",
"integrity": "sha512-ZaMJwc/0ckLz5DaAZ+pNLmHv8AMVGtfWxZe/x2JVEkD5LnmhWiQMMcYT7IY7gkdJuzJ9P14fRy28lUrlDSWYdw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/visitor-keys": "8.8.1",
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/visitor-keys": "8.8.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@ -6220,15 +6226,15 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz",
"integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.0.tgz",
"integrity": "sha512-QE2MgfOTem00qrlPgyByaCHay9yb1+9BjnMFnSFkUKQfu7adBXDTnCAivURnuPPAG/qiB+kzKkZKmKfaMT0zVg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.8.1",
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/typescript-estree": "8.8.1"
"@typescript-eslint/scope-manager": "8.8.0",
"@typescript-eslint/types": "8.8.0",
"@typescript-eslint/typescript-estree": "8.8.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -6242,12 +6248,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz",
"integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.0.tgz",
"integrity": "sha512-8mq51Lx6Hpmd7HnA2fcHQo3YgfX1qbccxQOgZcb4tvasu//zXRaA1j5ZRFeCw/VRAdFi4mRM9DnZw0Nu0Q2d1g==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "8.8.1",
"@typescript-eslint/types": "8.8.0",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
@ -6843,9 +6849,9 @@
}
},
"node_modules/@wdio/cli/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -6971,9 +6977,9 @@
}
},
"node_modules/@wdio/local-runner/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -7024,9 +7030,9 @@
}
},
"node_modules/@wdio/mocha-framework/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -7051,9 +7057,9 @@
}
},
"node_modules/@wdio/repl/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -7076,9 +7082,9 @@
}
},
"node_modules/@wdio/reporter/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -7107,9 +7113,9 @@
}
},
"node_modules/@wdio/runner/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -7156,9 +7162,9 @@
}
},
"node_modules/@wdio/types/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -9005,9 +9011,9 @@
"dev": true
},
"node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz",
"integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA=="
},
"node_modules/consola": {
"version": "3.2.3",
@ -9052,9 +9058,9 @@
"dev": true
},
"node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"dev": true,
"engines": {
"node": ">= 0.6"
@ -9855,9 +9861,9 @@
}
},
"node_modules/deepmerge-ts": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.3.tgz",
"integrity": "sha512-qCSH6I0INPxd9Y1VtAiLpnYvz5O//6rCfJXKk0z66Up9/VOSr+1yS8XSKA5IWRxjocFGlzPyaZYe+jxq7OOLtQ==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.1.tgz",
"integrity": "sha512-M27OAbyR/XgJujhAd6ZlYvZGzejbzvGPSZWwuzezPCdKLT9VMtK0kpRNDc5LeUDYqFN3e254gWG1yKpjidCtow==",
"dev": true,
"engines": {
"node": ">=16.0.0"
@ -10272,9 +10278,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.33",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz",
"integrity": "sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA==",
"version": "1.5.32",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz",
"integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==",
"dev": true
},
"node_modules/emoji-regex": {
@ -11032,16 +11038,16 @@
"dev": true
},
"node_modules/eslint-plugin-wc": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-2.2.0.tgz",
"integrity": "sha512-kjPp+aXz23fOl0JZJOJS+6adwhEv98KjZ2FJqWpc4vtmk4Oenz/JJmmNZrGSARgtyR0BLIF/kVWC6GSlHA+5MA==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-2.1.1.tgz",
"integrity": "sha512-GfJo05ZgWfwAFbW6Gkf+9CMOIU6fmbd3b4nm+PKESHgUdUTmi7vawlELCrzOhdiQjXUPZxDfFIVxYt9D/v/GdQ==",
"dev": true,
"dependencies": {
"is-valid-element-name": "^1.0.0",
"js-levenshtein-esm": "^1.2.0"
},
"peerDependencies": {
"eslint": ">=8.40.0"
"eslint": ">=5"
}
},
"node_modules/eslint-scope": {
@ -11405,9 +11411,9 @@
}
},
"node_modules/express": {
"version": "4.21.0",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
"integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
"version": "4.21.1",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz",
"integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==",
"dev": true,
"dependencies": {
"accepts": "~1.3.8",
@ -11415,7 +11421,7 @@
"body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
"cookie": "0.6.0",
"cookie": "0.7.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
@ -14293,9 +14299,9 @@
}
},
"node_modules/knip": {
"version": "5.33.1",
"resolved": "https://registry.npmjs.org/knip/-/knip-5.33.1.tgz",
"integrity": "sha512-SeuH+6IcDNNFRdVsi2uGnO6gsSDlx1V+TcQkKnzciF2Z7QHHasKseGUf9GMNVm3bSCKDeqaKPMp0F6BOiKuYRA==",
"version": "5.31.0",
"resolved": "https://registry.npmjs.org/knip/-/knip-5.31.0.tgz",
"integrity": "sha512-4hR+qHx/id7mniCWWUqA4MXwGjYFN75xv3qLmEkl9Hm6eCKAhv0wGP0CyrXKUYxVyDplJQsqQaAlsjuRKYsdPA==",
"dev": true,
"funding": [
{
@ -14317,7 +14323,7 @@
"easy-table": "1.2.0",
"enhanced-resolve": "^5.17.1",
"fast-glob": "^3.3.2",
"jiti": "^2.3.3",
"jiti": "^2.1.0",
"js-yaml": "^4.1.0",
"minimist": "^1.2.8",
"picocolors": "^1.0.0",
@ -14342,9 +14348,9 @@
}
},
"node_modules/knip/node_modules/jiti": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.3.3.tgz",
"integrity": "sha512-EX4oNDwcXSivPrw2qKH2LB5PoFxEvgtv2JgwW0bU858HoLQ+kutSvjLMUqBd0PeJYEinLWhoI9Ol0eYMqj/wNQ==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.2.1.tgz",
"integrity": "sha512-weIl/Bv3G0J3UKamLxEA2G+FfQ33Z1ZkQJGPjKFV21zQdKWu2Pi6o4elpj2uEl5XdFJZ9xzn1fsanWTFSt45zw==",
"dev": true,
"bin": {
"jiti": "lib/jiti-cli.mjs"
@ -14489,9 +14495,9 @@
"dev": true
},
"node_modules/lit": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz",
"integrity": "sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.2.0.tgz",
"integrity": "sha512-s6tI33Lf6VpDu7u4YqsSX78D28bYQulM+VAzsGch4fx2H0eLZnJsUBsPWmGYSGoKDNbjtRv02rio1o+UdPVwvw==",
"dependencies": {
"@lit/reactive-element": "^2.0.4",
"lit-element": "^4.1.0",
@ -14525,9 +14531,9 @@
"dev": true
},
"node_modules/lit-element": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.1.tgz",
"integrity": "sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.0.tgz",
"integrity": "sha512-gSejRUQJuMQjV2Z59KAS/D4iElUhwKpIyJvZ9w+DIagIQjfJnhR20h2Q5ddpzXGS+fF0tMZ/xEYGMnKmaI/iww==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.2.0",
"@lit/reactive-element": "^2.0.4",
@ -14535,9 +14541,9 @@
}
},
"node_modules/lit-html": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.1.tgz",
"integrity": "sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.0.tgz",
"integrity": "sha512-pwT/HwoxqI9FggTrYVarkBKFN9MlTUpLrDHubTmW4SrkL3kkqW5gxwbxMMUnbbRHBC0WTZnYHcjDSCM559VyfA==",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
@ -15201,14 +15207,14 @@
"optional": true
},
"node_modules/mlly": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.2.tgz",
"integrity": "sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==",
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz",
"integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==",
"dependencies": {
"acorn": "^8.12.1",
"acorn": "^8.11.3",
"pathe": "^1.1.2",
"pkg-types": "^1.2.0",
"ufo": "^1.5.4"
"pkg-types": "^1.1.1",
"ufo": "^1.5.3"
}
},
"node_modules/mocha": {
@ -16586,9 +16592,9 @@
"dev": true
},
"node_modules/package-manager-detector": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.1.tgz",
"integrity": "sha512-/hVW2fZvAdEas+wyKh0SnlZ2mx0NIa1+j11YaQkogEJkcMErbwchHCuo8z7lEtajZJQZ6rgZNVTWMVVd71Bjng=="
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.0.tgz",
"integrity": "sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog=="
},
"node_modules/pako": {
"version": "1.0.11",
@ -16900,12 +16906,12 @@
}
},
"node_modules/pkg-types": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz",
"integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.0.tgz",
"integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==",
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.2",
"confbox": "^0.1.7",
"mlly": "^1.7.1",
"pathe": "^1.1.2"
}
},
@ -19538,11 +19544,12 @@
}
},
"node_modules/swagger-client": {
"version": "3.29.4",
"resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.29.4.tgz",
"integrity": "sha512-Me8tdPyRAQbnwNBCZ0BpG0vyci9e+FW6YV3+c6/x8SwPmLpslpFNXoT4PtVApf1CVSvV7Sc7Bfb4DPgpEqBdHw==",
"version": "3.31.0",
"resolved": "https://registry.npmjs.org/swagger-client/-/swagger-client-3.31.0.tgz",
"integrity": "sha512-hVYift5XB8nOgNJVl6cbNtVTVPT2Fdx2wCOcIvuAFcyq0Mwe6+70ezoZ5WfiaIAzzwWfq72jyaLeg8TViGNSmw==",
"dependencies": {
"@babel/runtime-corejs3": "^7.22.15",
"@scarf/scarf": "=1.4.0",
"@swagger-api/apidom-core": ">=1.0.0-alpha.9 <1.0.0-beta.0",
"@swagger-api/apidom-error": ">=1.0.0-alpha.9 <1.0.0-beta.0",
"@swagger-api/apidom-json-pointer": ">=1.0.0-alpha.9 <1.0.0-beta.0",
@ -20646,14 +20653,14 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.1.tgz",
"integrity": "sha512-R0dsXFt6t4SAFjUSKFjMh4pXDtq04SsFKCVGDP3ZOzNP7itF0jBcZYU4fMsZr4y7O7V7Nc751dDeESbe4PbQMQ==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.0.tgz",
"integrity": "sha512-BjIT/VwJ8+0rVO01ZQ2ZVnjE1svFBiRczcpr1t1Yxt7sT25VSbPfrJtDsQ8uQTy2pilX5nI9gwxhUyLULNentw==",
"dev": true,
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.8.1",
"@typescript-eslint/parser": "8.8.1",
"@typescript-eslint/utils": "8.8.1"
"@typescript-eslint/eslint-plugin": "8.8.0",
"@typescript-eslint/parser": "8.8.0",
"@typescript-eslint/utils": "8.8.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -20911,17 +20918,17 @@
"integrity": "sha512-08/DA66UF65OlpUDIQtbJyrqTR0jTAlJ+jsnkQ4jxR7+K5g5YG1APZKQSMCE1vqqmD+2pv6+IdEjmopFatacvg=="
},
"node_modules/untyped": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/untyped/-/untyped-1.5.1.tgz",
"integrity": "sha512-reBOnkJBFfBZ8pCKaeHgfZLcehXtM6UTxc+vqs1JvCps0c4amLNp3fhdGBZwYp+VLyoY9n3X5KOP7lCyWBUX9A==",
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/untyped/-/untyped-1.5.0.tgz",
"integrity": "sha512-o2Vjmn2dal08BzCcINxSmWuAteReUUiXseii5VRhmxyLF0b21K0iKZQ9fMYK7RWspVkY+0saqaVQNq4roe3Efg==",
"dev": true,
"optional": true,
"dependencies": {
"@babel/core": "^7.25.7",
"@babel/standalone": "^7.25.7",
"@babel/types": "^7.25.7",
"@babel/core": "^7.25.2",
"@babel/standalone": "^7.25.6",
"@babel/types": "^7.25.6",
"defu": "^6.1.4",
"jiti": "^2.3.1",
"jiti": "^2.0.0",
"mri": "^1.2.0",
"scule": "^1.3.0"
},
@ -20945,9 +20952,9 @@
}
},
"node_modules/untyped/node_modules/jiti": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.3.3.tgz",
"integrity": "sha512-EX4oNDwcXSivPrw2qKH2LB5PoFxEvgtv2JgwW0bU858HoLQ+kutSvjLMUqBd0PeJYEinLWhoI9Ol0eYMqj/wNQ==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.2.1.tgz",
"integrity": "sha512-weIl/Bv3G0J3UKamLxEA2G+FfQ33Z1ZkQJGPjKFV21zQdKWu2Pi6o4elpj2uEl5XdFJZ9xzn1fsanWTFSt45zw==",
"dev": true,
"optional": true,
"bin": {
@ -21881,9 +21888,9 @@
}
},
"node_modules/webdriver/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"
@ -21936,9 +21943,9 @@
}
},
"node_modules/webdriverio/node_modules/@types/node": {
"version": "20.16.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
"integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
"version": "20.16.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
"integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
"dev": true,
"dependencies": {
"undici-types": "~6.19.2"

View File

@ -11,7 +11,7 @@
"@floating-ui/dom": "^1.6.11",
"@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.6.0",
"@goauthentik/api": "^2024.10.0-1730331602",
"@goauthentik/api": "^2024.10.1-1731327664",
"@lit-labs/ssr": "^3.2.2",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2",

View File

@ -71,7 +71,6 @@ export class ApplicationWizardApplicationDetails extends WithBrandConfig(BasePro
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${provider?.invalidationFlow}
.brandFlow=${this.brand.flowInvalidation}
defaultFlowSlug="default-invalidation-flow"
required
></ak-branded-flow-search>
<p class="pf-c-form__helper-text">${msg("Flow used for unbinding users.")}</p>

View File

@ -86,7 +86,7 @@ export class ApplicationWizardAuthenticationByRadius extends WithBrandConfig(Bas
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${provider?.invalidationFlow}
defaultFlowSlug="default-invalidation-flow"
defaultFlowSlug="default-provider-invalidation-flow"
required
></ak-flow-search>
<p class="pf-c-form__helper-text">

View File

@ -157,7 +157,6 @@ export class LDAPProviderFormPage extends WithBrandConfig(BaseProviderForm<LDAPP
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${this.instance?.invalidationFlow}
.brandFlow=${this.brand.flowInvalidation}
defaultFlowSlug="default-invalidation-flow"
required
></ak-branded-flow-search>
<p class="pf-c-form__helper-text">

View File

@ -176,7 +176,7 @@ export class RadiusProviderFormPage extends WithBrandConfig(BaseProviderForm<Rad
<ak-flow-search
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${this.instance?.invalidationFlow}
defaultFlowSlug="default-invalidation-flow"
defaultFlowSlug="default-provider-invalidation-flow"
required
></ak-flow-search>
<p class="pf-c-form__helper-text">

View File

@ -2,6 +2,7 @@ import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-number-input";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
@ -80,6 +81,15 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
)}
</p>
</ak-form-element-horizontal>
<ak-switch-input
name="interactive"
label=${msg("Interactive")}
?checked="${this.instance?.interactive}"
help=${msg(
"Enable this flag if the configured captcha requires User-interaction. Required for reCAPTCHA v2, hCaptcha and Cloudflare Turnstile.",
)}
>
</ak-switch-input>
<ak-number-input
label=${msg("Score minimum threshold")}
required

View File

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

View File

@ -10,10 +10,14 @@ export const DOM_PURIFY_STRICT: DOMPurify.Config = {
ALLOWED_TAGS: ["#text"],
};
export async function renderStatic(input: TemplateResult): Promise<string> {
return await collectResult(render(input));
}
export function purify(input: TemplateResult): TemplateResult {
return html`${until(
(async () => {
const rendered = await collectResult(render(input));
const rendered = await renderStatic(input);
const purified = DOMPurify.sanitize(rendered);
return html`${unsafeHTML(purified)}`;
})(),

View File

@ -44,12 +44,6 @@ export class Alert extends AKElement implements IAlert {
@property({ type: Boolean })
inline = false;
/**
* When true, removes the background color and status line; the text and icon are retained and
* colored.
*
* @attr
*/
@property({ type: Boolean })
plain = false;

View File

@ -6,14 +6,6 @@ import { customElement } from "lit/decorators.js";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
/**
* @class Divider
* @element ak-divider
*
* Divider is a horizontal rule, an in-page element to separate displayed items.
*
* @slot - HTML to display in-line in the middle of the horizontal rule.
*/
@customElement("ak-divider")
export class Divider extends AKElement {
static get styles() {

View File

@ -15,38 +15,14 @@ export interface IExpand {
textClosed?: string;
}
/**
* @class Expand
* @element ak-expand
*
* An `ak-expand` is used to hide cluttering details that a user may wish to reveal, such as the raw
* details of an alert or event.
*
* slot - The contents to be hidden or displayed.
*/
@customElement("ak-expand")
export class Expand extends AKElement implements IExpand {
/**
* The state of the expanded content
*
* @attr
*/
@property({ type: Boolean, reflect: true })
@property({ type: Boolean })
expanded = false;
/**
* The text to display next to the open/close control when the accordion is open.
*
* @attr
*/
@property({ type: String, attribute: "text-open" })
textOpen = msg("Show less");
/**
* The text to display next to the open/close control when the accordion is closed.
*
* @attr
*/
@property({ type: String, attribute: "text-closed" })
textClosed = msg("Show more");

View File

@ -12,23 +12,9 @@ export interface ILoadingOverlay {
topmost?: boolean;
}
/**
* @class LoadingOverlay
* @element ak-loading-overlay
*
* The LoadingOverlay is meant to cover the container element completely, hiding the content behind
* a dimming filter, while content loads.
*
* @slot - [Optional] message content to display while the overlay is visible.
*/
@customElement("ak-loading-overlay")
export class LoadingOverlay extends AKElement implements ILoadingOverlay {
/**
* When true, forces the overlay onto the top layer of the display stack.
* Do not camelize: https://www.merriam-webster.com/dictionary/topmost
*
* @attr
*/
// Do not camelize: https://www.merriam-webster.com/dictionary/topmost
@property({ type: Boolean, attribute: "topmost" })
topmost = false;

View File

@ -4,9 +4,9 @@ import { Meta } from "@storybook/web-components";
import { TemplateResult, html } from "lit";
import "./ak-action-button";
import { ActionButton } from "./ak-action-button";
import AKActionButton from "./ak-action-button";
const metadata: Meta<ActionButton> = {
const metadata: Meta<AKActionButton> = {
title: "Elements / <ak-action-button>",
component: "ak-action-button",
parameters: {

View File

@ -1,14 +1,9 @@
import { MessageLevel } from "@goauthentik/common/messages";
import {
BaseTaskButton,
type IBaseTaskButton,
} from "@goauthentik/elements/buttons/SpinnerButton/BaseTaskButton";
import { BaseTaskButton } from "@goauthentik/elements/buttons/SpinnerButton/BaseTaskButton";
import { showMessage } from "@goauthentik/elements/messages/MessageContainer";
import { customElement, property } from "lit/decorators.js";
type IActionButton = IBaseTaskButton & { apiRequest: () => Promise<unknown> };
/**
* A button associated with an event handler for loading data. Takes an asynchronous function as its
* only property.
@ -24,7 +19,7 @@ type IActionButton = IBaseTaskButton & { apiRequest: () => Promise<unknown> };
*/
@customElement("ak-action-button")
export class ActionButton extends BaseTaskButton implements IActionButton {
export class ActionButton extends BaseTaskButton {
/**
* The command to run when the button is pressed. Must return a promise. If the promise is a
* reject or throw, we process the content of the promise and deliver it to the Notification
@ -32,6 +27,7 @@ export class ActionButton extends BaseTaskButton implements IActionButton {
*
* @attr
*/
@property({ attribute: false })
apiRequest: () => Promise<unknown> = () => {
throw new Error();

View File

@ -36,10 +36,6 @@ const StatusMap = new Map<TaskStatus, string>([
const SPINNER_TIMEOUT = 1000 * 1.5; // milliseconds
export interface IBaseTaskButton {
disabled?: boolean;
}
/**
* BaseTaskButton
*
@ -50,6 +46,7 @@ export interface IBaseTaskButton {
* `onFailure` call their `super.` equivalents.
*
*/
export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
eventPrefix = "ak-button";

View File

@ -1,7 +1,7 @@
import { customElement } from "lit/decorators.js";
import { property } from "lit/decorators.js";
import { BaseTaskButton, type IBaseTaskButton } from "./BaseTaskButton";
import { BaseTaskButton } from "./BaseTaskButton";
/**
* A button associated with an event handler for loading data. Takes an asynchronous function as its
@ -17,10 +17,8 @@ import { BaseTaskButton, type IBaseTaskButton } from "./BaseTaskButton";
* @fires ak-button-reset - When the button is reset after the async process completes
*/
type ISpinnerButton = IBaseTaskButton & { callAction: () => Promise<unknown> };
@customElement("ak-spinner-button")
export class SpinnerButton extends BaseTaskButton implements ISpinnerButton {
export class SpinnerButton extends BaseTaskButton {
/**
* The command to run when the button is pressed. Must return a promise. We don't do anything
* with that promise other than check if it's a resolve or reject, and rethrow the event after.

View File

@ -107,7 +107,7 @@ export class AuthenticatorValidateStageWebAuthn extends BaseDeviceStage<
?loading="${this.authenticating}"
header=${this.authenticating
? msg("Authenticating...")
: this.errorMessage || msg("Failed to authenticate")}
: this.errorMessage || msg("Loading")}
icon="fa-times"
>
</ak-empty-state>

View File

@ -10,7 +10,7 @@ import "../../../stories/flow-interface";
import "./CaptchaStage";
export default {
title: "Flow / Stages / CaptchaStage",
title: "Flow / Stages / Captcha",
};
export const LoadingNoChallenge = () => {
@ -25,92 +25,60 @@ export const LoadingNoChallenge = () => {
</ak-storybook-interface>`;
};
export const ChallengeGoogleReCaptcha: StoryObj = {
render: ({ theme, challenge }) => {
return html`<ak-storybook-interface theme=${theme}>
<div class="pf-c-login">
<div class="pf-c-login__container">
<div class="pf-c-login__main">
<ak-stage-captcha .challenge=${challenge}></ak-stage-captcha>
</div>
</div></div
></ak-storybook-interface>`;
},
args: {
theme: "automatic",
challenge: {
pendingUser: "foo",
pendingUserAvatar: "https://picsum.photos/64",
jsUrl: "https://www.google.com/recaptcha/api.js",
siteKey: "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI",
} as CaptchaChallenge,
},
argTypes: {
theme: {
options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark],
control: {
type: "select",
function captchaFactory(challenge: CaptchaChallenge): StoryObj {
return {
render: ({ theme, challenge }) => {
return html`<ak-storybook-interface theme=${theme}>
<div class="pf-c-login">
<div class="pf-c-login__container">
<div class="pf-c-login__main">
<ak-stage-captcha .challenge=${challenge}></ak-stage-captcha>
</div>
</div></div
></ak-storybook-interface>`;
},
args: {
theme: "automatic",
challenge: challenge,
},
argTypes: {
theme: {
options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark],
control: {
type: "select",
},
},
},
},
};
};
}
export const ChallengeHCaptcha: StoryObj = {
render: ({ theme, challenge }) => {
return html`<ak-storybook-interface theme=${theme}>
<div class="pf-c-login">
<div class="pf-c-login__container">
<div class="pf-c-login__main">
<ak-stage-captcha .challenge=${challenge}></ak-stage-captcha>
</div>
</div></div
></ak-storybook-interface>`;
},
args: {
theme: "automatic",
challenge: {
pendingUser: "foo",
pendingUserAvatar: "https://picsum.photos/64",
jsUrl: "https://js.hcaptcha.com/1/api.js",
siteKey: "10000000-ffff-ffff-ffff-000000000001",
} as CaptchaChallenge,
},
argTypes: {
theme: {
options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark],
control: {
type: "select",
},
},
},
};
export const ChallengeHCaptcha = captchaFactory({
pendingUser: "foo",
pendingUserAvatar: "https://picsum.photos/64",
jsUrl: "https://js.hcaptcha.com/1/api.js",
siteKey: "10000000-ffff-ffff-ffff-000000000001",
interactive: true,
} as CaptchaChallenge);
export const ChallengeTurnstile: StoryObj = {
render: ({ theme, challenge }) => {
return html`<ak-storybook-interface theme=${theme}>
<div class="pf-c-login">
<div class="pf-c-login__container">
<div class="pf-c-login__main">
<ak-stage-captcha .challenge=${challenge}></ak-stage-captcha>
</div>
</div></div
></ak-storybook-interface>`;
},
args: {
theme: "automatic",
challenge: {
pendingUser: "foo",
pendingUserAvatar: "https://picsum.photos/64",
jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js",
siteKey: "1x00000000000000000000BB",
} as CaptchaChallenge,
},
argTypes: {
theme: {
options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark],
control: {
type: "select",
},
},
},
};
// https://developers.cloudflare.com/turnstile/troubleshooting/testing/
export const ChallengeTurnstileVisible = captchaFactory({
pendingUser: "foo",
pendingUserAvatar: "https://picsum.photos/64",
jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js",
siteKey: "1x00000000000000000000AA",
interactive: true,
} as CaptchaChallenge);
export const ChallengeTurnstileInvisible = captchaFactory({
pendingUser: "foo",
pendingUserAvatar: "https://picsum.photos/64",
jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js",
siteKey: "1x00000000000000000000BB",
interactive: true,
} as CaptchaChallenge);
export const ChallengeTurnstileForce = captchaFactory({
pendingUser: "foo",
pendingUserAvatar: "https://picsum.photos/64",
jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js",
siteKey: "3x00000000000000000000FF",
interactive: true,
} as CaptchaChallenge);

View File

@ -1,16 +1,17 @@
///<reference types="@hcaptcha/types"/>
import { renderStatic } from "@goauthentik/common/purify";
import "@goauthentik/elements/EmptyState";
import "@goauthentik/elements/forms/FormElement";
import { randomId } from "@goauthentik/elements/utils/randomId";
import "@goauthentik/flow/FormStatic";
import { BaseStage } from "@goauthentik/flow/stages/base";
import type { TurnstileObject } from "turnstile-types";
import { msg } from "@lit/localize";
import { CSSResult, PropertyValues, html } from "lit";
import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFForm from "@patternfly/patternfly/components/Form/form.css";
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -24,12 +25,22 @@ interface TurnstileWindow extends Window {
}
type TokenHandler = (token: string) => void;
const captchaContainerID = "captcha-container";
@customElement("ak-stage-captcha")
export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeResponseRequest> {
static get styles(): CSSResult[] {
return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton];
return [
PFBase,
PFLogin,
PFForm,
PFFormControl,
PFTitle,
css`
iframe {
width: 100%;
height: 73px; /* tmp */
}
`,
];
}
handlers = [this.handleGReCaptcha, this.handleHCaptcha, this.handleTurnstile];
@ -38,14 +49,17 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
error?: string;
@state()
captchaInteractive: boolean = true;
captchaFrame: HTMLIFrameElement;
@state()
captchaContainer: HTMLDivElement;
captchaDocumentContainer: HTMLDivElement;
@state()
scriptElement?: HTMLScriptElement;
@property({ type: Boolean })
embedded = false;
@property()
onTokenChange: TokenHandler = (token: string) => {
this.host.submit({ component: "ak-stage-captcha", token });
@ -53,8 +67,70 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
constructor() {
super();
this.captchaContainer = document.createElement("div");
this.captchaContainer.id = captchaContainerID;
this.captchaFrame = document.createElement("iframe");
this.captchaFrame.src = "about:blank";
this.captchaFrame.id = `ak-captcha-${randomId()}`;
this.captchaDocumentContainer = document.createElement("div");
this.captchaDocumentContainer.id = `ak-captcha-${randomId()}`;
this.messageCallback = this.messageCallback.bind(this);
}
connectedCallback(): void {
super.connectedCallback();
window.addEventListener("message", this.messageCallback);
}
disconnectedCallback(): void {
super.disconnectedCallback();
window.removeEventListener("message", this.messageCallback);
if (!this.challenge.interactive) {
document.removeChild(this.captchaDocumentContainer);
}
}
messageCallback(
ev: MessageEvent<{
source?: string;
context?: string;
message: string;
token: string;
}>,
) {
const msg = ev.data;
if (msg.source !== "goauthentik.io" || msg.context !== "flow-executor") {
return;
}
if (msg.message !== "captcha") {
return;
}
this.onTokenChange(msg.token);
}
async renderFrame(captchaElement: TemplateResult) {
this.captchaFrame.contentWindow?.document.open();
this.captchaFrame.contentWindow?.document.write(
await renderStatic(
html`<!doctype html>
<html>
<body style="display:flex;flex-direction:row;justify-content:center;">
${captchaElement}
<script src=${this.challenge.jsUrl}></script>
<script>
function callback(token) {
window.parent.postMessage({
message: "captcha",
source: "goauthentik.io",
context: "flow-executor",
token: token,
});
}
</script>
</body>
</html>`,
),
);
this.captchaFrame.contentWindow?.document.close();
}
updated(changedProperties: PropertyValues<this>) {
@ -64,15 +140,15 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
this.scriptElement.async = true;
this.scriptElement.defer = true;
this.scriptElement.dataset.akCaptchaScript = "true";
this.scriptElement.onload = () => {
this.scriptElement.onload = async () => {
console.debug("authentik/stages/captcha: script loaded");
let found = false;
let lastError = undefined;
this.handlers.forEach((handler) => {
this.handlers.forEach(async (handler) => {
let handlerFound = false;
try {
console.debug(`authentik/stages/captcha[${handler.name}]: trying handler`);
handlerFound = handler.apply(this);
handlerFound = await handler.apply(this);
if (handlerFound) {
console.debug(
`authentik/stages/captcha[${handler.name}]: handler succeeded`,
@ -96,51 +172,79 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
.querySelectorAll("[data-ak-captcha-script=true]")
.forEach((el) => el.remove());
document.head.appendChild(this.scriptElement);
if (!this.challenge.interactive) {
document.appendChild(this.captchaDocumentContainer);
}
}
}
handleGReCaptcha(): boolean {
async handleGReCaptcha(): Promise<boolean> {
if (!Object.hasOwn(window, "grecaptcha")) {
return false;
}
this.captchaInteractive = false;
document.body.appendChild(this.captchaContainer);
grecaptcha.ready(() => {
const captchaId = grecaptcha.render(this.captchaContainer, {
if (this.challenge.interactive) {
this.renderFrame(
html`<div
class="g-recaptcha"
data-sitekey="${this.challenge.siteKey}"
data-callback="callback"
></div>`,
);
} else {
grecaptcha.ready(() => {
const captchaId = grecaptcha.render(this.captchaDocumentContainer, {
sitekey: this.challenge.siteKey,
callback: this.onTokenChange,
size: "invisible",
});
grecaptcha.execute(captchaId);
});
}
return true;
}
async handleHCaptcha(): Promise<boolean> {
if (!Object.hasOwn(window, "hcaptcha")) {
return false;
}
if (this.challenge.interactive) {
this.renderFrame(
html`<div
class="h-captcha"
data-sitekey="${this.challenge.siteKey}"
data-theme="${this.activeTheme ? this.activeTheme : "light"}"
data-callback="callback"
></div> `,
);
} else {
const captchaId = hcaptcha.render(this.captchaDocumentContainer, {
sitekey: this.challenge.siteKey,
callback: this.onTokenChange,
size: "invisible",
});
grecaptcha.execute(captchaId);
});
return true;
}
handleHCaptcha(): boolean {
if (!Object.hasOwn(window, "hcaptcha")) {
return false;
hcaptcha.execute(captchaId);
}
this.captchaInteractive = false;
document.body.appendChild(this.captchaContainer);
const captchaId = hcaptcha.render(this.captchaContainer, {
sitekey: this.challenge.siteKey,
callback: this.onTokenChange,
size: "invisible",
});
hcaptcha.execute(captchaId);
return true;
}
handleTurnstile(): boolean {
async handleTurnstile(): Promise<boolean> {
if (!Object.hasOwn(window, "turnstile")) {
return false;
}
this.captchaInteractive = false;
document.body.appendChild(this.captchaContainer);
(window as unknown as TurnstileWindow).turnstile.render(`#${captchaContainerID}`, {
sitekey: this.challenge.siteKey,
callback: this.onTokenChange,
});
if (this.challenge.interactive) {
this.renderFrame(
html`<div
class="cf-turnstile"
data-sitekey="${this.challenge.siteKey}"
data-callback="callback"
></div>`,
);
} else {
(window as unknown as TurnstileWindow).turnstile.render(this.captchaDocumentContainer, {
sitekey: this.challenge.siteKey,
callback: this.onTokenChange,
});
}
return true;
}
@ -148,13 +252,19 @@ export class CaptchaStage extends BaseStage<CaptchaChallenge, CaptchaChallengeRe
if (this.error) {
return html`<ak-empty-state icon="fa-times" header=${this.error}> </ak-empty-state>`;
}
if (this.captchaInteractive) {
return html`${this.captchaContainer}`;
if (this.challenge.interactive) {
return html`${this.captchaFrame}`;
}
return html`<ak-empty-state loading header=${msg("Verifying...")}></ak-empty-state>`;
}
render() {
if (this.embedded) {
if (!this.challenge.interactive) {
return html``;
}
return this.renderBody();
}
if (!this.challenge) {
return html`<ak-empty-state loading> </ak-empty-state>`;
}

View File

@ -0,0 +1,87 @@
import type { StoryObj } from "@storybook/web-components";
import { html } from "lit";
import "@patternfly/patternfly/components/Login/login.css";
import { FlowDesignationEnum, IdentificationChallenge, UiThemeEnum } from "@goauthentik/api";
import "../../../stories/flow-interface";
import "./IdentificationStage";
export default {
title: "Flow / Stages / Identification",
};
export const LoadingNoChallenge = () => {
return html`<ak-storybook-interface theme=${UiThemeEnum.Dark}>
<div class="pf-c-login">
<div class="pf-c-login__container">
<div class="pf-c-login__main">
<ak-stage-identification></ak-stage-identification>
</div>
</div>
</div>
</ak-storybook-interface>`;
};
function identificationFactory(challenge: IdentificationChallenge): StoryObj {
return {
render: ({ theme, challenge }) => {
return html`<ak-storybook-interface theme=${theme}>
<div class="pf-c-login">
<div class="pf-c-login__container">
<div class="pf-c-login__main">
<ak-stage-identification
.challenge=${challenge}
></ak-stage-identification>
</div>
</div></div
></ak-storybook-interface>`;
},
args: {
theme: "automatic",
challenge: challenge,
},
argTypes: {
theme: {
options: [UiThemeEnum.Automatic, UiThemeEnum.Light, UiThemeEnum.Dark],
control: {
type: "select",
},
},
},
};
}
export const ChallengeDefault = identificationFactory({
userFields: ["username"],
passwordFields: false,
flowDesignation: FlowDesignationEnum.Authentication,
primaryAction: "Login",
showSourceLabels: false,
// jsUrl: "https://js.hcaptcha.com/1/api.js",
// siteKey: "10000000-ffff-ffff-ffff-000000000001",
// interactive: true,
});
// https://developers.cloudflare.com/turnstile/troubleshooting/testing/
export const ChallengeCaptchaTurnstileVisible = identificationFactory({
userFields: ["username"],
passwordFields: false,
flowDesignation: FlowDesignationEnum.Authentication,
primaryAction: "Login",
showSourceLabels: false,
flowInfo: {
layout: "stacked",
cancelUrl: "",
title: "Foo",
},
captchaStage: {
pendingUser: "",
pendingUserAvatar: "",
jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js",
siteKey: "1x00000000000000000000AA",
interactive: true,
},
});

View File

@ -282,11 +282,11 @@ export class IdentificationStage extends BaseStage<
? html`
<input name="captchaToken" type="hidden" .value="${this.captchaToken}" />
<ak-stage-captcha
style="visibility: hidden; position:absolute;"
.challenge=${this.challenge.captchaStage}
.onTokenChange=${(token: string) => {
this.captchaToken = token;
}}
embedded
></ak-stage-captcha>
`
: nothing}

View File

@ -5819,6 +5819,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
@ -5963,6 +5966,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -7014,18 +7020,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -6084,6 +6084,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
@ -6228,6 +6231,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -7279,18 +7285,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -5736,6 +5736,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
@ -5880,6 +5883,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -6931,18 +6937,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -7646,6 +7646,10 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>Pour nginx auth_request ou traefik forwardAuth par domaine racine</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC est en aperçu.</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>Type d'utilisateur pour les utilisateurs nouvellement créés.</target>
@ -7838,6 +7842,10 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<source>Create Endpoint</source>
<target>Créer un point de terminaison</target>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
<target>RAC est en aperçu.</target>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
<target>Mettre à jour le fournisseur RAC</target>
@ -9240,18 +9248,6 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

File diff suppressed because it is too large Load Diff

View File

@ -7616,6 +7616,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>루트 도메인 당 Nginx의 auth_request 또는 Traefik의 forwardAuth 경우</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC 는 현재 프리뷰입니다.</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>새로 생성된 사용자에 사용되는 사용자 유형입니다.</target>
@ -7810,6 +7814,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -8846,18 +8853,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -7396,6 +7396,9 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
<trans-unit id="sf79f8681e5ffaee2">
<source>Assign to new user</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="saabeb4cab074b0b9">
<source>User Object Permissions</source>
</trans-unit>
@ -7483,6 +7486,9 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -8693,18 +8699,6 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -7650,6 +7650,10 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>Dla nginx's auth_request lub traefik's forwardAuth dla domeny głównej</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC jest w fazie zapoznawczej.</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>Typ użytkownika używany dla nowo utworzonych użytkowników.</target>
@ -7842,6 +7846,10 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
<source>Create Endpoint</source>
<target>Utwórz punkt końcowy</target>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
<target>RAC jest w fazie zapoznawczej.</target>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
<target>Aktualizuj dostawcę RAC</target>
@ -9110,18 +9118,6 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -7594,6 +7594,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>Ƒōŕ ńĝĩńx'ś àũţĥ_ŕēǫũēśţ ōŕ ţŕàēƒĩķ'ś ƒōŕŵàŕďÀũţĥ ƥēŕ ŕōōţ ďōḿàĩń</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>ŔßÀĆ ĩś ĩń ƥŕēvĩēŵ.</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>Ũśēŕ ţŷƥē ũśēď ƒōŕ ńēŵĺŷ ćŕēàţēď ũśēŕś.</target>
@ -7786,6 +7790,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Create Endpoint</source>
<target>Ćŕēàţē Ēńďƥōĩńţ</target>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
<target>ŔÀĆ ĩś ĩń ƥŕēvĩēŵ.</target>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
<target>Ũƥďàţē ŔÀĆ Ƥŕōvĩďēŕ</target>
@ -9150,16 +9158,4 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body></file></xliff>

View File

@ -7649,6 +7649,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>Для nginx's auth_request или traefik's forwardAuth для корневого домена</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC находится в предварительной версии.</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>Тип пользователя, используемый для вновь созданных пользователей.</target>
@ -7841,6 +7845,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Create Endpoint</source>
<target>Создать конечную точку</target>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
<target>RAC находится в предварительной версии.</target>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
<target>Обновить RAC провайдера</target>
@ -9173,18 +9181,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -5729,6 +5729,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
@ -5873,6 +5876,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -6924,18 +6930,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -1375,6 +1375,9 @@
<trans-unit id="s9fb28be12e2c6317">
<source>Superuser</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="sa1db89262360550b">
<source>Send us feedback!</source>
</trans-unit>
@ -1911,6 +1914,9 @@ doesn't pass when either or both of the selected options are equal or above the
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -5863,18 +5869,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -7648,6 +7648,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>适用于按根域名配置的 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC 目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>新创建用户使用的用户类型。</target>
@ -7840,6 +7844,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Create Endpoint</source>
<target>创建端点</target>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
<target>RAC 目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
<target>更新 RAC 提供程序</target>
@ -9120,147 +9128,99 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="sbfee780fa0a2c83e">
<source>Device type <x id="0" equiv-text="${device.verboseName}"/> cannot be deleted</source>
<target>设备类型 <x id="0" equiv-text="${device.verboseName}"/> 无法被删除</target>
</trans-unit>
<trans-unit id="s336936629cdeb3e5">
<source>Stage used to verify users' browsers using Google Chrome Device Trust. This stage can be used in authentication/authorization flows.</source>
<target>通过 Google Chrome 设备信任来验证用户浏览器的阶段。此阶段可在身份验证/授权流程中使用。</target>
</trans-unit>
<trans-unit id="s85fe794c71b4ace8">
<source>Google Verified Access API</source>
<target>Google Verified Access API</target>
</trans-unit>
<trans-unit id="s013620384af7c8b4">
<source>Device type <x id="0" equiv-text="${device.verboseName}"/> cannot be edited</source>
<target>设备类型 <x id="0" equiv-text="${device.verboseName}"/> 无法被编辑</target>
</trans-unit>
<trans-unit id="s4347135696fc7cde">
<source>Advanced flow settings</source>
<target>高级流程设置</target>
</trans-unit>
<trans-unit id="sf52ff57fd136cc2f">
<source>Enable this option to write password changes made in authentik back to Kerberos. Ignored if sync is disabled.</source>
<target>启用此选项会将 authentik 作出的密码修改写入回 Kerberos。如果未启用同步则忽略。</target>
</trans-unit>
<trans-unit id="s14a16542f956e11d">
<source>Realm settings</source>
<target>领域设置</target>
</trans-unit>
<trans-unit id="s9c2eae548d3c1c30">
<source>Realm</source>
<target>领域</target>
</trans-unit>
<trans-unit id="s6b032212997e2491">
<source>Kerberos 5 configuration</source>
<target>Kerberos 5 配置</target>
</trans-unit>
<trans-unit id="sbf50181022f47de3">
<source>Kerberos 5 configuration. See man krb5.conf(5) for configuration format. If left empty, a default krb5.conf will be used.</source>
<target>Kerberos 5 配置。请阅读 man krb5.conf(5) 了解配置格式。如果留空,则使用默认的 krb5.conf。</target>
</trans-unit>
<trans-unit id="s2386539a0bd62fab">
<source>Sync connection settings</source>
<target>同步连接设置</target>
</trans-unit>
<trans-unit id="s0d1a6f3fe81351f8">
<source>Sync principal</source>
<target>同步主体</target>
</trans-unit>
<trans-unit id="sa691d6e1974295fa">
<source>Principal used to authenticate to the KDC for syncing.</source>
<target>向 KDC 进行身份验证以进行同步的主体。</target>
</trans-unit>
<trans-unit id="s977b9c629eed3d33">
<source>Sync password</source>
<target>同步密码</target>
</trans-unit>
<trans-unit id="s77772860385de948">
<source>Password used to authenticate to the KDC for syncing. Optional if Sync keytab or Sync credentials cache is provided.</source>
<target>向 KDC 进行身份验证以进行同步的密码。如果提供了同步 Keytab 或同步凭据缓存,则此选项是可选的。</target>
</trans-unit>
<trans-unit id="sc59ec59c3d5e74dc">
<source>Sync keytab</source>
<target>同步 Keytab</target>
</trans-unit>
<trans-unit id="scd42997958453f05">
<source>Keytab used to authenticate to the KDC for syncing. Optional if Sync password or Sync credentials cache is provided. Must be base64 encoded or in the form TYPE:residual.</source>
<target>向 KDC 进行身份验证以进行同步的 Keytab。如果提供了同步密码或同步凭据缓存则此选项是可选的。必须以 Base64 编码,或者形式为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="s60eaf439ccdca1f2">
<source>Sync credentials cache</source>
<target>同步凭据缓存</target>
</trans-unit>
<trans-unit id="s95722900b0c9026f">
<source>Credentials cache used to authenticate to the KDC for syncing. Optional if Sync password or Sync keytab is provided. Must be in the form TYPE:residual.</source>
<target>向 KDC 进行身份验证以进行同步的凭据缓存。如果提供了同步密码或同步 Keytab则此选项是可选的。形式必须为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="sf9c055db98d7994a">
<source>SPNEGO settings</source>
<target>SPNEGO 设置</target>
</trans-unit>
<trans-unit id="sab580a45dc46937f">
<source>SPNEGO server name</source>
<target>SPNEGO 服务器名称</target>
</trans-unit>
<trans-unit id="s7a79d6174d17ab2d">
<source>Force the use of a specific server name for SPNEGO. Must be in the form HTTP@domain</source>
<target>强制为 SPNEGO 使用特定服务器名称。形式必须为 HTTP@域名</target>
</trans-unit>
<trans-unit id="sa4ba2b2081472ccd">
<source>SPNEGO keytab</source>
<target>SPNEGO Keytab</target>
</trans-unit>
<trans-unit id="s64adda975c1106c0">
<source>Keytab used for SPNEGO. Optional if SPNEGO credentials cache is provided. Must be base64 encoded or in the form TYPE:residual.</source>
<target>SPNEGO 使用的 Keytab。如果提供了 SPNEGO 凭据缓存,则此选项是可选的。必须以 Base64 编码,或者形式为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="s92247825b92587b5">
<source>SPNEGO credentials cache</source>
<target>SPNEGO 凭据缓存</target>
</trans-unit>
<trans-unit id="sd9757c345e4062f8">
<source>Credentials cache used for SPNEGO. Optional if SPNEGO keytab is provided. Must be in the form TYPE:residual.</source>
<target>SPNEGO 使用的凭据缓存。如果提供了 SPNEGO Keytab则此选项是可选的。形式必须为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="s734ab8fbcae0b69e">
<source>Kerberos Attribute mapping</source>
<target>Kerberos 属性映射</target>
</trans-unit>
<trans-unit id="s2c378e86e025fdb2">
<source>Update Kerberos Source</source>
<target>更新 Kerberos 源</target>
</trans-unit>
<trans-unit id="s03e4044abe0b556c">
<source>User database + Kerberos password</source>
<target>用户数据库 + Kerberos 密码</target>
</trans-unit>
<trans-unit id="s98bb2ae796f1ceef">
<source>Select another authentication method</source>
<target>选择另一种身份验证方法</target>
</trans-unit>
<trans-unit id="s21d95b4651ad7a1e">
<source>Enter a one-time recovery code for this user.</source>
<target>为此用户输入一次性恢复代码。</target>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
<target>请输入来自您身份验证设备的代码。</target>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
<target>Kerberos 源目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
<target>验证码阶段</target>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
<target>设置后,添加与验证码阶段完全相同的功能,但融入识别阶段。</target>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
<target>端点 Google Chrome 设备信任处于预览状态。</target>
</trans-unit>
</body>
</file>

View File

@ -5777,6 +5777,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
@ -5921,6 +5924,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -6972,18 +6978,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -6618,6 +6618,11 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Please enter your code</source>
<target>请输入您的代码</target>
</trans-unit>
<trans-unit id="s18b910437b73e8e8">
<source>Return to device picker</source>
<target>返回设备选择器</target>
</trans-unit>
<trans-unit id="se409d01b52c4e12f">
<source>Retry authentication</source>
@ -7648,6 +7653,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>适用于按根域名配置的 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC 目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>新创建用户使用的用户类型。</target>
@ -7840,6 +7849,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Create Endpoint</source>
<target>创建端点</target>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
<target>RAC 目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
<target>更新 RAC 提供程序</target>
@ -9117,150 +9130,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s8a598f7aef81c3bc">
<source>Key used to encrypt the tokens.</source>
<target>用于加密令牌的密钥。</target>
</trans-unit>
<trans-unit id="sbfee780fa0a2c83e">
<source>Device type <x id="0" equiv-text="${device.verboseName}"/> cannot be deleted</source>
<target>设备类型 <x id="0" equiv-text="${device.verboseName}"/> 无法被删除</target>
</trans-unit>
<trans-unit id="s336936629cdeb3e5">
<source>Stage used to verify users' browsers using Google Chrome Device Trust. This stage can be used in authentication/authorization flows.</source>
<target>通过 Google Chrome 设备信任来验证用户浏览器的阶段。此阶段可在身份验证/授权流程中使用。</target>
</trans-unit>
<trans-unit id="s85fe794c71b4ace8">
<source>Google Verified Access API</source>
<target>Google Verified Access API</target>
</trans-unit>
<trans-unit id="s013620384af7c8b4">
<source>Device type <x id="0" equiv-text="${device.verboseName}"/> cannot be edited</source>
<target>设备类型 <x id="0" equiv-text="${device.verboseName}"/> 无法被编辑</target>
</trans-unit>
<trans-unit id="s4347135696fc7cde">
<source>Advanced flow settings</source>
<target>高级流程设置</target>
</trans-unit>
<trans-unit id="sf52ff57fd136cc2f">
<source>Enable this option to write password changes made in authentik back to Kerberos. Ignored if sync is disabled.</source>
<target>启用此选项会将 authentik 作出的密码修改写入回 Kerberos。如果未启用同步则忽略。</target>
</trans-unit>
<trans-unit id="s14a16542f956e11d">
<source>Realm settings</source>
<target>领域设置</target>
</trans-unit>
<trans-unit id="s9c2eae548d3c1c30">
<source>Realm</source>
<target>领域</target>
</trans-unit>
<trans-unit id="s6b032212997e2491">
<source>Kerberos 5 configuration</source>
<target>Kerberos 5 配置</target>
</trans-unit>
<trans-unit id="sbf50181022f47de3">
<source>Kerberos 5 configuration. See man krb5.conf(5) for configuration format. If left empty, a default krb5.conf will be used.</source>
<target>Kerberos 5 配置。请阅读 man krb5.conf(5) 了解配置格式。如果留空,则使用默认的 krb5.conf。</target>
</trans-unit>
<trans-unit id="s2386539a0bd62fab">
<source>Sync connection settings</source>
<target>同步连接设置</target>
</trans-unit>
<trans-unit id="s0d1a6f3fe81351f8">
<source>Sync principal</source>
<target>同步主体</target>
</trans-unit>
<trans-unit id="sa691d6e1974295fa">
<source>Principal used to authenticate to the KDC for syncing.</source>
<target>向 KDC 进行身份验证以进行同步的主体。</target>
</trans-unit>
<trans-unit id="s977b9c629eed3d33">
<source>Sync password</source>
<target>同步密码</target>
</trans-unit>
<trans-unit id="s77772860385de948">
<source>Password used to authenticate to the KDC for syncing. Optional if Sync keytab or Sync credentials cache is provided.</source>
<target>向 KDC 进行身份验证以进行同步的密码。如果提供了同步 Keytab 或同步凭据缓存,则此选项是可选的。</target>
</trans-unit>
<trans-unit id="sc59ec59c3d5e74dc">
<source>Sync keytab</source>
<target>同步 Keytab</target>
</trans-unit>
<trans-unit id="scd42997958453f05">
<source>Keytab used to authenticate to the KDC for syncing. Optional if Sync password or Sync credentials cache is provided. Must be base64 encoded or in the form TYPE:residual.</source>
<target>向 KDC 进行身份验证以进行同步的 Keytab。如果提供了同步密码或同步凭据缓存则此选项是可选的。必须以 Base64 编码,或者形式为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="s60eaf439ccdca1f2">
<source>Sync credentials cache</source>
<target>同步凭据缓存</target>
</trans-unit>
<trans-unit id="s95722900b0c9026f">
<source>Credentials cache used to authenticate to the KDC for syncing. Optional if Sync password or Sync keytab is provided. Must be in the form TYPE:residual.</source>
<target>向 KDC 进行身份验证以进行同步的凭据缓存。如果提供了同步密码或同步 Keytab则此选项是可选的。形式必须为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="sf9c055db98d7994a">
<source>SPNEGO settings</source>
<target>SPNEGO 设置</target>
</trans-unit>
<trans-unit id="sab580a45dc46937f">
<source>SPNEGO server name</source>
<target>SPNEGO 服务器名称</target>
</trans-unit>
<trans-unit id="s7a79d6174d17ab2d">
<source>Force the use of a specific server name for SPNEGO. Must be in the form HTTP@domain</source>
<target>强制为 SPNEGO 使用特定服务器名称。形式必须为 HTTP@域名</target>
</trans-unit>
<trans-unit id="sa4ba2b2081472ccd">
<source>SPNEGO keytab</source>
<target>SPNEGO Keytab</target>
</trans-unit>
<trans-unit id="s64adda975c1106c0">
<source>Keytab used for SPNEGO. Optional if SPNEGO credentials cache is provided. Must be base64 encoded or in the form TYPE:residual.</source>
<target>SPNEGO 使用的 Keytab。如果提供了 SPNEGO 凭据缓存,则此选项是可选的。必须以 Base64 编码,或者形式为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="s92247825b92587b5">
<source>SPNEGO credentials cache</source>
<target>SPNEGO 凭据缓存</target>
</trans-unit>
<trans-unit id="sd9757c345e4062f8">
<source>Credentials cache used for SPNEGO. Optional if SPNEGO keytab is provided. Must be in the form TYPE:residual.</source>
<target>SPNEGO 使用的凭据缓存。如果提供了 SPNEGO Keytab则此选项是可选的。形式必须为 TYPE:residual。</target>
</trans-unit>
<trans-unit id="s734ab8fbcae0b69e">
<source>Kerberos Attribute mapping</source>
<target>Kerberos 属性映射</target>
</trans-unit>
<trans-unit id="s2c378e86e025fdb2">
<source>Update Kerberos Source</source>
<target>更新 Kerberos 源</target>
</trans-unit>
<trans-unit id="s03e4044abe0b556c">
<source>User database + Kerberos password</source>
<target>用户数据库 + Kerberos 密码</target>
</trans-unit>
<trans-unit id="s98bb2ae796f1ceef">
<source>Select another authentication method</source>
<target>选择另一种身份验证方法</target>
</trans-unit>
<trans-unit id="s21d95b4651ad7a1e">
<source>Enter a one-time recovery code for this user.</source>
<target>为此用户输入一次性恢复代码。</target>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
<target>请输入来自您身份验证设备的代码。</target>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
<target>Kerberos 源目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
<target>验证码阶段</target>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
<target>设置后,添加与验证码阶段完全相同的功能,但融入识别阶段。</target>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
<target>端点 Google Chrome 设备信任处于预览状态。</target>
</trans-unit>
</body>
</file>

View File

@ -7590,6 +7590,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>適用於每個主網域的 nginx 的「auth_request」或 traefik 的「forwardAuth」</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC 正處於預覽版本。</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>用於建立使用者的使用者類型。</target>
@ -7756,6 +7760,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
</trans-unit>
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
</trans-unit>
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
</trans-unit>
@ -8807,18 +8814,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s2e1d5a7d320c25ef">
<source>Enter the code from your authenticator device.</source>
</trans-unit>
<trans-unit id="scc1a17d28912e974">
<source>Kerberos Source is in preview.</source>
</trans-unit>
<trans-unit id="s54154a8d64a3597b">
<source>Captcha stage</source>
</trans-unit>
<trans-unit id="s0c250af62ddbf801">
<source>When set, adds functionality exactly like a Captcha stage, but baked into the Identification stage.</source>
</trans-unit>
<trans-unit id="sabf8a430d504f8c8">
<source>Endpoint Google Chrome Device Trust is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -1,6 +1,5 @@
---
title: Applications
slug: /applications
---
Applications, as defined in authentik, are used to configure and separate the authorization/access control and the appearance of a specific software application in the **My applications** page.

View File

@ -2,15 +2,17 @@
title: Captcha stage
---
This stage adds a form of verification using [Google's ReCaptcha](https://www.google.com/recaptcha/intro/v3.html) or compatible services. Currently supported implementations:
This stage adds a form of verification using [Google's reCAPTCHA](https://www.google.com/recaptcha/intro/v3.html) or compatible services.
- ReCaptcha
- hCaptcha
- Turnstile
Currently supported implementations:
- [Google reCAPTCHA](#google-recaptcha)
- [hCaptcha](#hcaptcha)
- [Cloudflare Turnstile](#cloudflare-turnstile)
## Captcha provider configuration
### Google ReCaptcha
### Google reCAPTCHA
This stage has two required fields: Public key and private key. These can both be acquired at https://www.google.com/recaptcha/admin.
@ -18,10 +20,11 @@ This stage has two required fields: Public key and private key. These can both b
#### Configuration options
- JS URL: `https://www.recaptcha.net/recaptcha/api.js`
- API URL: `https://www.recaptcha.net/recaptcha/api/siteverify`
- Interactive: Enabled when using reCAPTCHA v3
- Score minimum threshold: `0.5`
- Score maximum threshold: `1`
- JS URL: `https://www.recaptcha.net/recaptcha/api.js`
- API URL: `https://www.recaptcha.net/recaptcha/api/siteverify`
### hCaptcha
@ -29,6 +32,7 @@ See https://docs.hcaptcha.com/switch
#### Configuration options
- Interactive: Enabled
- JS URL: `https://js.hcaptcha.com/1/api.js`
- API URL: `https://api.hcaptcha.com/siteverify`
@ -37,16 +41,13 @@ See https://docs.hcaptcha.com/switch
- Score minimum threshold: `0`
- Score maximum threshold: `0.5`
### Turnstile
### Cloudflare Turnstile
See https://developers.cloudflare.com/turnstile/get-started/migrating-from-recaptcha
:::warning
To use Cloudflare Turnstile, the site must be configured to use the "Invisible" mode, otherwise the widget will be rendered incorrectly.
:::
#### Configuration options
- Interactive: Enabled if the Turnstile instance is configured as visible or managed
- JS URL: `https://challenges.cloudflare.com/turnstile/v0/api.js`
- API URL: `https://challenges.cloudflare.com/turnstile/v0/siteverify`

View File

@ -32,6 +32,10 @@ This policy can enforce regular password rotation by expiring set passwords afte
### Password Policy
:::warning
By default, authentik's Password policy is compliant with [NIST's recommendations](https://pages.nist.gov/800-63-4/sp800-63b.html#password) for passwords. To remain compliant with NIST, be cautious when editing the default values. For additional hardening configuration settings, refer to [Hardening authentik](../../security/security-hardening.md#password-policy).
:::
This policy allows you to specify password rules, such as length and required characters.
The following rules can be set:

File diff suppressed because it is too large Load Diff

View File

@ -286,20 +286,6 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.8
- web: Fix missing integrity fields in package-lock.json (#11509)
- web/admin: fix Authentication flow being required (cherry-pick #11496) (#11497)
## Fixed in 2024.8.4
- blueprints: fix validation error when using internal storage (cherry-pick #11654) (#11656)
- core: fix permission check for scoped impersonation (cherry-pick #11603) (#11650)
- internal: restore /ping behaviour for embedded outpost (cherry-pick #11568) (#11570)
- policies/event_matcher: fix inconsistent behaviour (cherry-pick #11724) (#11726)
- providers/oauth2: don't overwrite attributes when updating service account (cherry-pick #11709) (#11723)
- providers/saml: fix incorrect ds:Reference URI (cherry-pick #11699) (#11701)
- providers/scim: add comparison with existing group on update and delta update users (cherry-pick #11414) (#11796)
- providers/scim: clamp batch size for patch requests (cherry-pick #11797) (#11802)
- providers/scim: handle no members in group in consistency check (cherry-pick #11801) (#11812)
- web/admin: fix invalid create date shown for MFA registered before date was saved (cherry-pick #11728) (#11729)
- web/admin: fix sync single button throwing error (cherry-pick #11727) (#11730)
## API Changes
#### What's New

View File

@ -4,6 +4,17 @@ title: Hardening authentik
While authentik is secure out of the box, you can take steps to further increase the security of an authentik instance. As everyone knows, there is a consequential tradeoff between security and convenience. All of these hardening practices have an impact on the user experience and should only be applied knowing this tradeoff.
### Password policy
authentik's default Password policy complies with the [NIST SP 800-63 Digital Identity Guidelines](https://pages.nist.gov/800-63-4/sp800-63b.html#password).
However, for further hardening compliant to the NIST Guidelines, consider
- setting the length of the password to a minimum of 15 characters, and
- enabling the "Check haveibeenpwned.com" blocklist comparison (note that this cannot be used on Air-gapped instances)
For further options, see [Password policy](../customize/policies/index.md#password-policy).
### Expressions
[Expressions](../customize/policies/expression.mdx) allow super-users and other highly privileged users to create custom logic within authentik to modify its behaviour. Editing/creating these expressions is, by default, limited to super-users and any related events are fully logged.

View File

@ -8895,9 +8895,9 @@
"integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ=="
},
"node_modules/elliptic": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz",
"integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==",
"version": "6.5.7",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
"integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
"dependencies": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",