stages/authenticator_duo: improved import (#3601)

* prepare for duo admin integration

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* make duo import params required

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* add UI to import devices

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* rework form, automatic import

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* limit amount of concurrent tasks on worker

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* load tasks

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* fix API codes

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* fix tests and such

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* add tests

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* sigh

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* make stage better

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

* basic stage test

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens L 2022-09-17 12:10:47 +02:00 committed by GitHub
parent 02e2c117ac
commit be64296494
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1219 additions and 106 deletions

View File

@ -312,6 +312,7 @@ LOCALE_PATHS = ["./locale"]
# Add a 10 minute timeout to all Celery tasks.
CELERY_TASK_SOFT_TIME_LIMIT = 600
CELERY_WORKER_MAX_TASKS_PER_CHILD = 50
CELERY_WORKER_CONCURRENCY = 2
CELERY_BEAT_SCHEDULE = {
"clean_expired_models": {
"task": "authentik.core.tasks.clean_expired_models",

View File

@ -2,32 +2,28 @@
from django.http import Http404
from django_filters.rest_framework.backends import DjangoFilterBackend
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import (
OpenApiParameter,
OpenApiResponse,
extend_schema,
inline_serializer,
)
from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer
from guardian.shortcuts import get_objects_for_user
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.fields import ChoiceField
from rest_framework.fields import CharField, ChoiceField, IntegerField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from structlog.stdlib import get_logger
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.api.decorators import permission_required
from authentik.core.api.used_by import UsedByMixin
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice
from authentik.stages.authenticator_duo.stage import (
SESSION_KEY_DUO_ACTIVATION_CODE,
SESSION_KEY_DUO_USER_ID,
)
from authentik.stages.authenticator_duo.stage import SESSION_KEY_DUO_ENROLL
from authentik.stages.authenticator_duo.tasks import duo_import_devices
LOGGER = get_logger()
class AuthenticatorDuoStageSerializer(StageSerializer):
@ -41,9 +37,12 @@ class AuthenticatorDuoStageSerializer(StageSerializer):
"client_id",
"client_secret",
"api_hostname",
"admin_integration_key",
"admin_secret_key",
]
extra_kwargs = {
"client_secret": {"write_only": True},
"admin_secret_key": {"write_only": True},
}
@ -85,57 +84,90 @@ class AuthenticatorDuoStageViewSet(UsedByMixin, ModelViewSet):
stage: AuthenticatorDuoStage = AuthenticatorDuoStage.objects.filter(pk=pk).first()
if not stage:
raise Http404
client = stage.client
user_id = self.request.session.get(SESSION_KEY_DUO_USER_ID)
activation_code = self.request.session.get(SESSION_KEY_DUO_ACTIVATION_CODE)
if not user_id or not activation_code:
client = stage.auth_client()
enroll = self.request.session.get(SESSION_KEY_DUO_ENROLL)
if not enroll:
return Response(status=400)
status = client.enroll_status(user_id, activation_code)
status = client.enroll_status(enroll["user_id"], enroll["activation_code"])
return Response({"duo_response": status})
@permission_required(
"", ["authentik_stages_authenticator_duo.add_duodevice", "authentik_core.view_user"]
)
@extend_schema(
parameters=[
OpenApiParameter(
name="duo_user_id", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY
),
OpenApiParameter(
name="username", type=OpenApiTypes.STR, location=OpenApiParameter.QUERY
),
],
request=None,
request=inline_serializer(
"AuthenticatorDuoStageManualDeviceImport",
{
"duo_user_id": CharField(required=True),
"username": CharField(required=True),
},
),
responses={
204: OpenApiResponse(description="Enrollment successful"),
400: OpenApiResponse(description="Device exists already"),
400: OpenApiResponse(description="Bad request"),
},
)
@action(methods=["POST"], detail=True)
# pylint: disable=invalid-name,unused-argument
def import_devices(self, request: Request, pk: str) -> Response:
def import_device_manual(self, request: Request, pk: str) -> Response:
"""Import duo devices into authentik"""
stage: AuthenticatorDuoStage = self.get_object()
user = (
get_objects_for_user(request.user, "authentik_core.view_user")
.filter(username=request.query_params.get("username", ""))
.filter(username=request.data.get("username", ""))
.first()
)
if not user:
return Response(data={"non_field_errors": ["user does not exist"]}, status=400)
device = DuoDevice.objects.filter(
duo_user_id=request.query_params.get("duo_user_id"), user=user, stage=stage
duo_user_id=request.data.get("duo_user_id"), user=user, stage=stage
).first()
if device:
return Response(data={"non_field_errors": ["device exists already"]}, status=400)
DuoDevice.objects.create(
duo_user_id=request.query_params.get("duo_user_id"),
duo_user_id=request.data.get("duo_user_id"),
user=user,
stage=stage,
name="Imported Duo Authenticator",
)
return Response(status=204)
@permission_required(
"", ["authentik_stages_authenticator_duo.add_duodevice", "authentik_core.view_user"]
)
@extend_schema(
request=None,
responses={
200: inline_serializer(
"AuthenticatorDuoStageDeviceImportResponse",
fields={
"count": IntegerField(read_only=True),
"error": CharField(read_only=True),
},
),
400: OpenApiResponse(description="Bad request"),
},
)
@action(methods=["POST"], detail=True)
# pylint: disable=invalid-name,unused-argument
def import_devices_automatic(self, request: Request, pk: str) -> Response:
"""Import duo devices into authentik"""
stage: AuthenticatorDuoStage = self.get_object()
if stage.admin_integration_key == "":
return Response(
data={
"non_field_errors": [
(
"Stage does not have Admin API configured, "
"which is required for automatic imports."
)
]
},
status=400,
)
result = duo_import_devices.delay(str(stage.pk)).get()
return Response(data=result, status=200 if result["error"] == "" else 400)
class DuoDeviceSerializer(ModelSerializer):
"""Serializer for Duo authenticator devices"""

View File

@ -1,10 +1,16 @@
"""authentik duo app config"""
from django.apps import AppConfig
from authentik.blueprints.apps import ManagedAppConfig
class AuthentikStageAuthenticatorDuoConfig(AppConfig):
class AuthentikStageAuthenticatorDuoConfig(ManagedAppConfig):
"""authentik duo config"""
name = "authentik.stages.authenticator_duo"
label = "authentik_stages_authenticator_duo"
verbose_name = "authentik Stages.Authenticator.Duo"
default = True
def reconcile_load_tasks(self):
"""Load tasks"""
self.import_module("authentik.stages.authenticator_duo.tasks")

View File

@ -0,0 +1,23 @@
# Generated by Django 4.1.1 on 2022-09-16 15:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_authenticator_duo", "0003_duodevice_last_t"),
]
operations = [
migrations.AddField(
model_name="authenticatorduostage",
name="admin_integration_key",
field=models.TextField(blank=True, default=""),
),
migrations.AddField(
model_name="authenticatorduostage",
name="admin_secret_key",
field=models.TextField(blank=True, default=""),
),
]

View File

@ -6,6 +6,7 @@ from django.db import models
from django.utils.translation import gettext_lazy as _
from django.views import View
from django_otp.models import Device
from duo_client.admin import Admin
from duo_client.auth import Auth
from rest_framework.serializers import BaseSerializer, Serializer
@ -13,14 +14,19 @@ from authentik import __version__
from authentik.core.types import UserSettingSerializer
from authentik.flows.models import ConfigurableStage, Stage
from authentik.lib.models import SerializerModel
from authentik.lib.utils.http import authentik_user_agent
class AuthenticatorDuoStage(ConfigurableStage, Stage):
"""Setup Duo authenticator devices"""
api_hostname = models.TextField()
client_id = models.TextField()
client_secret = models.TextField()
api_hostname = models.TextField()
admin_integration_key = models.TextField(blank=True, default="")
admin_secret_key = models.TextField(blank=True, default="")
@property
def serializer(self) -> type[BaseSerializer]:
@ -34,14 +40,24 @@ class AuthenticatorDuoStage(ConfigurableStage, Stage):
return AuthenticatorDuoStageView
@property
def client(self) -> Auth:
def auth_client(self) -> Auth:
"""Get an API Client to talk to duo"""
client = Auth(
return Auth(
self.client_id,
self.client_secret,
self.api_hostname,
user_agent=f"authentik {__version__}",
user_agent=authentik_user_agent(),
)
def admin_client(self) -> Admin:
"""Get an API Client to talk to duo"""
if self.admin_integration_key == "" or self.admin_secret_key == "": # nosec
raise ValueError("Admin credentials not configured")
client = Admin(
self.admin_integration_key,
self.admin_secret_key,
self.api_hostname,
user_agent=authentik_user_agent(),
)
return client

View File

@ -15,8 +15,7 @@ from authentik.flows.stage import ChallengeStageView
from authentik.flows.views.executor import InvalidStageError
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice
SESSION_KEY_DUO_USER_ID = "authentik/stages/authenticator_duo/user_id"
SESSION_KEY_DUO_ACTIVATION_CODE = "authentik/stages/authenticator_duo/activation_code"
SESSION_KEY_DUO_ENROLL = "authentik/stages/authenticator_duo/enroll"
class AuthenticatorDuoChallenge(WithUserInfoChallenge):
@ -39,11 +38,12 @@ class AuthenticatorDuoStageView(ChallengeStageView):
response_class = AuthenticatorDuoChallengeResponse
def get_challenge(self, *args, **kwargs) -> Challenge:
def duo_enroll(self):
"""Enroll User with Duo API and save results"""
user = self.get_pending_user()
stage: AuthenticatorDuoStage = self.executor.current_stage
try:
enroll = stage.client.enroll(user.username)
enroll = stage.auth_client().enroll(user.username)
except RuntimeError as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
@ -51,9 +51,14 @@ class AuthenticatorDuoStageView(ChallengeStageView):
user=user,
).from_http(self.request, user)
raise InvalidStageError(str(exc)) from exc
user_id = enroll["user_id"]
self.request.session[SESSION_KEY_DUO_USER_ID] = user_id
self.request.session[SESSION_KEY_DUO_ACTIVATION_CODE] = enroll["activation_code"]
self.request.session[SESSION_KEY_DUO_ENROLL] = enroll
return enroll
def get_challenge(self, *args, **kwargs) -> Challenge:
stage: AuthenticatorDuoStage = self.executor.current_stage
if SESSION_KEY_DUO_ENROLL not in self.request.session:
self.duo_enroll()
enroll = self.request.session[SESSION_KEY_DUO_ENROLL]
return AuthenticatorDuoChallenge(
data={
"type": ChallengeTypes.NATIVE.value,
@ -73,19 +78,19 @@ class AuthenticatorDuoStageView(ChallengeStageView):
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
# Duo Challenge has already been validated
stage: AuthenticatorDuoStage = self.executor.current_stage
user_id = self.request.session.get(SESSION_KEY_DUO_USER_ID)
activation_code = self.request.session.get(SESSION_KEY_DUO_ACTIVATION_CODE)
enroll_status = stage.client.enroll_status(user_id, activation_code)
enroll = self.request.session.get(SESSION_KEY_DUO_ENROLL)
enroll_status = stage.auth_client().enroll_status(
enroll["user_id"], enroll["activation_code"]
)
if enroll_status != "success":
return HttpResponse(status=420)
existing_device = DuoDevice.objects.filter(duo_user_id=user_id).first()
self.request.session.pop(SESSION_KEY_DUO_USER_ID)
self.request.session.pop(SESSION_KEY_DUO_ACTIVATION_CODE)
return self.executor.stage_invalid(f"Invalid enrollment status: {enroll_status}.")
existing_device = DuoDevice.objects.filter(duo_user_id=enroll["user_id"]).first()
self.request.session.pop(SESSION_KEY_DUO_ENROLL)
if not existing_device:
DuoDevice.objects.create(
name="Duo Authenticator",
user=self.get_pending_user(),
duo_user_id=user_id,
duo_user_id=enroll["user_id"],
stage=stage,
last_t=now(),
)
@ -94,5 +99,4 @@ class AuthenticatorDuoStageView(ChallengeStageView):
return self.executor.stage_ok()
def cleanup(self):
self.request.session.pop(SESSION_KEY_DUO_USER_ID, None)
self.request.session.pop(SESSION_KEY_DUO_ACTIVATION_CODE, None)
self.request.session.pop(SESSION_KEY_DUO_ENROLL, None)

View File

@ -0,0 +1,46 @@
"""duo tasks"""
from structlog.stdlib import get_logger
from authentik.core.models import User
from authentik.root.celery import CELERY_APP
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice
LOGGER = get_logger()
@CELERY_APP.task()
def duo_import_devices(stage_pk: str):
"""Import duo devices"""
created = 0
stage: AuthenticatorDuoStage = AuthenticatorDuoStage.objects.filter(pk=stage_pk).first()
if not stage:
LOGGER.info("No stage found", pk=stage_pk)
return {"error": "No stage found", "count": created}
if stage.admin_integration_key == "":
LOGGER.info("Stage does not have admin integration configured", stage=stage)
return {"error": "Stage does not have admin integration configured", "count": created}
client = stage.admin_client()
try:
for duo_user in client.get_users_iterator():
user_id = duo_user.get("user_id")
username = duo_user.get("username")
user = User.objects.filter(username=username).first()
if not user:
LOGGER.debug("User not found", username=username)
continue
device = DuoDevice.objects.filter(duo_user_id=user_id, user=user, stage=stage).first()
if device:
LOGGER.debug("User already has a device with ID", id=user_id)
continue
DuoDevice.objects.create(
duo_user_id=user_id,
user=user,
stage=stage,
name="Imported Duo Authenticator",
)
created += 1
return {"error": "", "count": created}
except RuntimeError as exc:
LOGGER.warning("failed to get users from duo", exc=exc)
return {"error": str(exc), "count": created}

View File

@ -0,0 +1,290 @@
"""Test duo stage"""
from unittest.mock import MagicMock, patch
from uuid import uuid4
from django.test.client import RequestFactory
from django.urls import reverse
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.flows.models import FlowStageBinding
from authentik.flows.tests import FlowTestCase
from authentik.lib.generators import generate_id
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice
from authentik.stages.authenticator_duo.stage import SESSION_KEY_DUO_ENROLL
from authentik.stages.identification.models import IdentificationStage, UserFields
class AuthenticatorDuoStageTests(FlowTestCase):
"""Test duo stage"""
def setUp(self) -> None:
self.user = create_test_admin_user()
self.request_factory = RequestFactory()
def test_client(self):
"""Test Duo client setup"""
stage = AuthenticatorDuoStage(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
admin_integration_key=generate_id(),
admin_secret_key=generate_id(),
api_hostname=generate_id(),
)
self.assertEqual(stage.auth_client().ikey, stage.client_id)
self.assertEqual(stage.admin_client().ikey, stage.admin_integration_key)
stage.admin_integration_key = ""
with self.assertRaises(ValueError):
self.assertEqual(stage.admin_client().ikey, stage.admin_integration_key)
def test_api_enrollment_invalid(self):
"""Test `enrollment_status`"""
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-enrollment-status",
kwargs={
"pk": str(uuid4()),
},
)
)
self.assertEqual(response.status_code, 404)
def test_api_enrollment(self):
"""Test `enrollment_status`"""
stage = AuthenticatorDuoStage.objects.create(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
api_hostname=generate_id(),
)
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-enrollment-status",
kwargs={
"pk": str(stage.pk),
},
)
)
self.assertEqual(response.status_code, 400)
session = self.client.session
session[SESSION_KEY_DUO_ENROLL] = {"user_id": "foo", "activation_code": "bar"}
session.save()
with patch("duo_client.auth.Auth.enroll_status", MagicMock(return_value="foo")):
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-enrollment-status",
kwargs={
"pk": str(stage.pk),
},
)
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), '{"duo_response":"foo"}')
def test_api_import_manual_invalid_username(self):
"""Test `import_device_manual`"""
self.client.force_login(self.user)
stage = AuthenticatorDuoStage.objects.create(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
api_hostname=generate_id(),
)
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-import-device-manual",
kwargs={
"pk": str(stage.pk),
},
),
data={
"username": generate_id(),
},
)
self.assertEqual(response.status_code, 400)
def test_api_import_manual_duplicate_device(self):
"""Test `import_device_manual`"""
self.client.force_login(self.user)
stage = AuthenticatorDuoStage.objects.create(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
api_hostname=generate_id(),
)
device = DuoDevice.objects.create(
name="foo",
duo_user_id=generate_id(),
user=self.user,
stage=stage,
)
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-import-device-manual",
kwargs={
"pk": str(stage.pk),
},
),
data={
"username": self.user.username,
"duo_user_id": device.duo_user_id,
},
)
self.assertEqual(response.status_code, 400)
def test_api_import_manual(self):
"""Test `import_device_manual`"""
self.client.force_login(self.user)
stage = AuthenticatorDuoStage.objects.create(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
api_hostname=generate_id(),
)
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-import-device-manual",
kwargs={
"pk": str(stage.pk),
},
),
data={
"username": self.user.username,
"duo_user_id": "foo",
},
)
self.assertEqual(response.status_code, 204)
def test_api_import_automatic_invalid(self):
"""test `import_devices_automatic`"""
self.client.force_login(self.user)
stage = AuthenticatorDuoStage.objects.create(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
api_hostname=generate_id(),
)
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-import-devices-automatic",
kwargs={
"pk": str(stage.pk),
},
),
)
self.assertEqual(response.status_code, 400)
def test_api_import_automatic(self):
"""test `import_devices_automatic`"""
self.client.force_login(self.user)
stage = AuthenticatorDuoStage.objects.create(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
admin_integration_key=generate_id(),
admin_secret_key=generate_id(),
api_hostname=generate_id(),
)
device = DuoDevice.objects.create(
name="foo",
duo_user_id=generate_id(),
user=self.user,
stage=stage,
)
with patch(
"duo_client.admin.Admin.get_users_iterator",
MagicMock(
return_value=[
{
"user_id": "foo",
"username": "bar",
},
{
"user_id": device.duo_user_id,
"username": self.user.username,
},
{
"user_id": generate_id(),
"username": self.user.username,
},
]
),
):
response = self.client.post(
reverse(
"authentik_api:authenticatorduostage-import-devices-automatic",
kwargs={
"pk": str(stage.pk),
},
),
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content.decode(), '{"error":"","count":1}')
def test_stage_enroll_basic(self):
"""Test stage"""
conf_stage = IdentificationStage.objects.create(
name=generate_id(),
user_fields=[
UserFields.USERNAME,
],
)
stage = AuthenticatorDuoStage.objects.create(
name=generate_id(),
client_id=generate_id(),
client_secret=generate_id(),
api_hostname=generate_id(),
)
flow = create_test_flow()
FlowStageBinding.objects.create(target=flow, stage=conf_stage, order=0)
FlowStageBinding.objects.create(target=flow, stage=stage, order=1)
response = self.client.post(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
{"uid_field": self.user.username},
)
self.assertEqual(response.status_code, 302)
enroll_mock = MagicMock(
return_value={
"user_id": "foo",
"activation_barcode": "bar",
"activation_code": "bar",
}
)
with patch("duo_client.auth.Auth.enroll", enroll_mock):
response = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
follow=True,
)
self.assertStageResponse(
response,
flow,
component="ak-stage-authenticator-duo",
pending_user=self.user.username,
activation_barcode="bar",
activation_code="bar",
)
response = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
follow=True,
)
self.assertStageResponse(
response,
flow,
component="ak-stage-authenticator-duo",
pending_user=self.user.username,
activation_barcode="bar",
activation_code="bar",
)
self.assertEqual(enroll_mock.call_count, 1)
with patch("duo_client.auth.Auth.enroll_status", MagicMock(return_value="success")):
response = self.client.post(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), {}
)
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))

View File

@ -175,7 +175,7 @@ def validate_challenge_duo(device_pk: int, stage_view: StageView, user: User) ->
).name
try:
response = stage.client.auth(
response = stage.auth_client().auth(
"auto",
user_id=device.duo_user_id,
ipaddr=get_client_ip(stage_view.request),

View File

@ -44,14 +44,18 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
stage=stage,
)
with patch(
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.client",
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.auth_client",
MagicMock(
auth=MagicMock(
return_value={
"result": "allow",
"status": "allow",
"status_msg": "Success. Logging you in...",
}
MagicMock(
return_value=MagicMock(
auth=MagicMock(
return_value={
"result": "allow",
"status": "allow",
"status_msg": "Success. Logging you in...",
}
)
)
)
),
):
@ -70,8 +74,8 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
),
)
with patch(
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.client",
MagicMock(auth=MagicMock(return_value={"result": "deny"})),
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.auth_client",
MagicMock(return_value=MagicMock(auth=MagicMock(return_value={"result": "deny"}))),
):
with self.assertRaises(ValidationError):
validate_challenge_duo(

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-16 15:57+0000\n"
"POT-Creation-Date: 2022-09-16 21:25+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"
@ -1328,19 +1328,19 @@ msgstr ""
msgid "SAML Sources"
msgstr ""
#: authentik/stages/authenticator_duo/models.py:65
#: authentik/stages/authenticator_duo/models.py:80
msgid "Duo Authenticator Setup Stage"
msgstr ""
#: authentik/stages/authenticator_duo/models.py:66
#: authentik/stages/authenticator_duo/models.py:81
msgid "Duo Authenticator Setup Stages"
msgstr ""
#: authentik/stages/authenticator_duo/models.py:90
#: authentik/stages/authenticator_duo/models.py:105
msgid "Duo Device"
msgstr ""
#: authentik/stages/authenticator_duo/models.py:91
#: authentik/stages/authenticator_duo/models.py:106
msgid "Duo Devices"
msgstr ""

View File

@ -18650,15 +18650,11 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/stages/authenticator/duo/{stage_uuid}/import_devices/:
/stages/authenticator/duo/{stage_uuid}/import_device_manual/:
post:
operationId: stages_authenticator_duo_import_devices_create
operationId: stages_authenticator_duo_import_device_manual_create
description: Import duo devices into authentik
parameters:
- in: query
name: duo_user_id
schema:
type: string
- in: path
name: stage_uuid
schema:
@ -18666,19 +18662,52 @@ paths:
format: uuid
description: A UUID string identifying this Duo Authenticator Setup Stage.
required: true
- in: query
name: username
schema:
type: string
tags:
- stages
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AuthenticatorDuoStageManualDeviceImportRequest'
required: true
security:
- authentik: []
responses:
'204':
description: Enrollment successful
'400':
description: Device exists already
description: Bad request
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/stages/authenticator/duo/{stage_uuid}/import_devices_automatic/:
post:
operationId: stages_authenticator_duo_import_devices_automatic_create
description: Import duo devices into authentik
parameters:
- in: path
name: stage_uuid
schema:
type: string
format: uuid
description: A UUID string identifying this Duo Authenticator Setup Stage.
required: true
tags:
- stages
security:
- authentik: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/AuthenticatorDuoStageDeviceImportResponse'
description: ''
'400':
description: Bad request
'403':
content:
application/json:
@ -24983,6 +25012,8 @@ components:
type: string
api_hostname:
type: string
admin_integration_key:
type: string
required:
- api_hostname
- client_id
@ -24992,6 +25023,30 @@ components:
- pk
- verbose_name
- verbose_name_plural
AuthenticatorDuoStageDeviceImportResponse:
type: object
properties:
count:
type: integer
readOnly: true
error:
type: string
readOnly: true
required:
- count
- error
AuthenticatorDuoStageManualDeviceImportRequest:
type: object
properties:
duo_user_id:
type: string
minLength: 1
username:
type: string
minLength: 1
required:
- duo_user_id
- username
AuthenticatorDuoStageRequest:
type: object
description: AuthenticatorDuoStage Serializer
@ -25019,6 +25074,11 @@ components:
api_hostname:
type: string
minLength: 1
admin_integration_key:
type: string
admin_secret_key:
type: string
writeOnly: true
required:
- api_hostname
- client_id
@ -32518,6 +32578,11 @@ components:
api_hostname:
type: string
minLength: 1
admin_integration_key:
type: string
admin_secret_key:
type: string
writeOnly: true
PatchedAuthenticatorSMSStageRequest:
type: object
description: AuthenticatorSMSStage Serializer

View File

@ -141,8 +141,10 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
</select>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Context`} name="context">
<ak-codemirror mode="yaml" value=${YAML.stringify(first(this.request?.context, {}))}
>>
<ak-codemirror
mode="yaml"
value=${YAML.stringify(first(this.request?.context, {}))}
>
</ak-codemirror>
<p class="pf-c-form__helper-text">
${t`Set custom attributes using YAML or JSON.`}

View File

@ -33,6 +33,7 @@ import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { until } from "lit/directives/until.js";
import { Stage, StagesApi } from "@goauthentik/api";
@ -99,6 +100,22 @@ export class StageListPage extends TablePage<Stage> {
</ak-forms-delete-bulk>`;
}
async renderStageActions(stage: Stage): Promise<TemplateResult> {
if (stage.component === "ak-stage-authenticator-duo-form") {
await import("@goauthentik/admin/stages/authenticator_duo/DuoDeviceImportForm");
return html`<ak-forms-modal>
<span slot="submit">${t`Import`}</span>
<span slot="header">${t`Import Duo device`}</span>
<ak-stage-authenticator-duo-device-import-form slot="form" .instancePk=${stage.pk}>
</ak-stage-authenticator-duo-device-import-form>
<button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-file-import"></i>
</button>
</ak-forms-modal>`;
}
return html``;
}
row(item: Stage): TemplateResult[] {
return [
html`<div>
@ -114,21 +131,22 @@ export class StageListPage extends TablePage<Stage> {
</li>`;
})}
</ul>`,
html` <ak-forms-modal>
<span slot="submit"> ${t`Update`} </span>
<span slot="header"> ${t`Update ${item.verboseName}`} </span>
<ak-proxy-form
slot="form"
.args=${{
instancePk: item.pk,
}}
type=${ifDefined(item.component)}
>
</ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-edit"></i>
</button>
</ak-forms-modal>`,
html`<ak-forms-modal>
<span slot="submit"> ${t`Update`} </span>
<span slot="header"> ${t`Update ${item.verboseName}`} </span>
<ak-proxy-form
slot="form"
.args=${{
instancePk: item.pk,
}}
type=${ifDefined(item.component)}
>
</ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-plain">
<i class="fas fa-edit"></i>
</button>
</ak-forms-modal>
${until(this.renderStageActions(item))}`,
];
}

View File

@ -61,8 +61,20 @@ export class AuthenticatorDuoStageForm extends ModelForm<AuthenticatorDuoStage,
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`API Hostname`}
?required=${true}
name="apiHostname"
>
<input
type="text"
value="${first(this.instance?.apiHostname, "")}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}>
<span slot="header"> ${t`Stage-specific settings`} </span>
<span slot="header"> ${t`Duo Auth API`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`Integration key`}
@ -84,18 +96,37 @@ export class AuthenticatorDuoStageForm extends ModelForm<AuthenticatorDuoStage,
>
<input type="text" value="" class="pf-c-form-control" required />
</ak-form-element-horizontal>
</div>
</ak-form-group>
<ak-form-group>
<span slot="header">${t`Duo Admin API (optional)`}</span>
<span slot="description">
${t`When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.
This will allow authentik to import devices automatically.`}
</span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal
label=${t`API Hostname`}
?required=${true}
name="apiHostname"
label=${t`Integration key`}
name="adminIntegrationKey"
>
<input
type="text"
value="${first(this.instance?.apiHostname, "")}"
value="${first(this.instance?.adminIntegrationKey, "")}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Secret key`}
?writeOnly=${this.instance !== undefined}
name="adminSecretKey"
>
<input type="text" value="" class="pf-c-form-control" />
</ak-form-element-horizontal>
</div>
</ak-form-group>
<ak-form-group .expanded=${true}>
<span slot="header"> ${t`Stage-specific settings`} </span>
<div slot="body" class="pf-c-form">
<ak-form-element-horizontal label=${t`Configuration flow`} name="configureFlow">
<select class="pf-c-form-control">
<option

View File

@ -0,0 +1,113 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { MessageLevel } from "@goauthentik/common/messages";
import "@goauthentik/elements/Divider";
import "@goauthentik/elements/buttons/ActionButton";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModalForm } from "@goauthentik/elements/forms/ModalForm";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import { showMessage } from "@goauthentik/elements/messages/MessageContainer";
import { UserOption } from "@goauthentik/elements/user/utils";
import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { until } from "lit/directives/until.js";
import {
AuthenticatorDuoStage,
CoreApi,
StagesApi,
StagesAuthenticatorDuoImportDeviceManualCreateRequest,
} from "@goauthentik/api";
@customElement("ak-stage-authenticator-duo-device-import-form")
export class DuoDeviceImportForm extends ModelForm<AuthenticatorDuoStage, string> {
loadInstance(pk: string): Promise<AuthenticatorDuoStage> {
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorDuoRetrieve({
stageUuid: pk,
});
}
getSuccessMessage(): string {
return t`Successfully imported device.`;
}
send = (data: AuthenticatorDuoStage): Promise<void> => {
const importData = data as unknown as StagesAuthenticatorDuoImportDeviceManualCreateRequest;
importData.stageUuid = this.instancePk;
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorDuoImportDeviceManualCreate(
importData,
);
};
renderForm(): TemplateResult {
return html`${this.instance?.adminIntegrationKey !== ""
? this.renderFormAutomatic()
: html``}
${this.renderFormManual()}`;
}
renderFormManual(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`User`} ?required=${true} name="username">
<select class="pf-c-form-control">
${until(
new CoreApi(DEFAULT_CONFIG)
.coreUsersList({
ordering: "username",
})
.then((users) => {
return users.results.map((user) => {
return html`<option value=${user.username}>
${UserOption(user)}
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">
${t`The user in authentik this device will be assigned to.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Duo User ID`} ?required=${true} name="duoUserId">
<input type="text" class="pf-c-form-control" required />
<p class="pf-c-form__helper-text">
${t`The user ID in Duo.`}
${t`Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user).`}
</p>
</ak-form-element-horizontal>
</form>`;
}
renderFormAutomatic(): TemplateResult {
return html`
<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${t`Automatic import`}>
<ak-action-button
class="pf-m-primary"
.apiRequest=${() => {
return new StagesApi(DEFAULT_CONFIG)
.stagesAuthenticatorDuoImportDevicesAutomaticCreate({
stageUuid: this.instance?.pk || "",
})
.then((res) => {
showMessage({
level: MessageLevel.info,
message: t`Successfully imported ${res.count} devices.`,
});
const modal = this.parentElement as ModalForm;
modal.open = false;
});
}}
>
${t`Start automatic import`}
</ak-action-button>
</ak-form-element-horizontal>
</form>
<ak-divider>${t`Or manually import`}</ak-divider>
<br />
`;
}
}

View File

@ -23,7 +23,7 @@ export class ModalForm extends ModalButton {
@property({ type: String })
cancelText = t`Cancel`;
confirm(): Promise<void> {
async confirm(): Promise<void> {
const form = this.querySelector<Form<unknown>>("[slot=form]");
if (!form) {
return Promise.reject(t`No form found`);

View File

@ -832,6 +832,10 @@ msgstr ""
msgid "Callback URL"
msgstr "Callback URL"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "Kann das Format \"unix://\" haben, wenn eine Verbindung zu einem lokalen Docker-Daemon besteht, oder \"https://:2376\", wenn eine Verbindung zu einem entfernten System besteht."
@ -1837,10 +1841,22 @@ msgstr "Dummy-Stage zum Testen verwendet. Zeigt eine einfache Schaltfläche zum
#~ msgid "Duo"
#~ msgstr "Duo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Duo-Authentifikatoren"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Duo-Aktivierung"
@ -2772,9 +2788,16 @@ msgstr "Identitätswechsel gestarted"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "Importieren"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "Ablauf importieren"
@ -2821,6 +2844,7 @@ msgstr "Ansprüche in id_token berücksichtigen"
msgid "Integration"
msgstr "Integration"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "Integrationsschlüssel"
@ -3138,6 +3162,7 @@ msgstr "Wird geladen"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4756,6 +4781,7 @@ msgstr "Suchmodus"
msgid "Search..."
msgstr "Suche..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "Geheimer Schlüssel"
@ -5438,6 +5464,10 @@ msgstr "Zertifikat-Schlüsselpaar erfolgreich generiert."
msgid "Successfully generated recovery link"
msgstr "Erfolgreich generierter Wiederherstellungslink"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "Ablauf erfolgreich importiert."
@ -5826,6 +5856,14 @@ msgstr "Der Anfang für gidNumbers, diese Zahl wird zu einer aus der group.Pk ge
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "Der Anfang für uidNumbers, diese Zahl wird zu user.Pk hinzugefügt, um sicherzustellen, dass die Zahlen für POSIX-Benutzer nicht zu niedrig sind. Standardwert ist 2000, um sicherzustellen, dass wir nicht mit lokalen uidNumbers der Benutzer kollidieren"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "Diese Bindungen steuern, ob diese Stufe auf den Ablauf angewendet wird."
@ -6430,6 +6468,7 @@ msgstr "Nutze diese Umgebung für jede Domain, die keine eigene Umgebung hat."
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6845,6 +6884,12 @@ msgstr "Wenn diese Option aktiviert ist, werden alle Ausführungen dieser Richtl
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "Bei Verwendung in Verbindung mit einer User Write-Phase verwenden Sie attributes.foo zum Schreiben von Attributen."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "Falls eine externe Protokollierlösung zum archivieren genutzt wird, könnte dies auf „minutes=5“ gesetzt werden."

View File

@ -829,6 +829,10 @@ msgstr "Caddy (Standalone)"
msgid "Callback URL"
msgstr "Callback URL"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
#: src/pages/outposts/ServiceConnectionDockerForm.ts
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
@ -1863,10 +1867,22 @@ msgstr "Dummy stage used for testing. Shows a simple continue button and always
#~ msgid "Duo"
#~ msgstr "Duo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr "Duo Admin API (optional)"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr "Duo Auth API"
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Duo Authenticators"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr "Duo User ID"
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Duo activation"
@ -2817,9 +2833,16 @@ msgstr "Impersonation started"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "Import"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr "Import Duo device"
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "Import Flow"
@ -2866,6 +2889,7 @@ msgstr "Include claims in id_token"
msgid "Integration"
msgstr "Integration"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "Integration key"
@ -3190,6 +3214,7 @@ msgstr "Loading"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4836,6 +4861,7 @@ msgstr "Search mode"
msgid "Search..."
msgstr "Search..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "Secret key"
@ -5544,6 +5570,10 @@ msgstr "Successfully generated certificate-key pair."
msgid "Successfully generated recovery link"
msgstr "Successfully generated recovery link"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr "Successfully imported device."
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "Successfully imported flow."
@ -5942,6 +5972,14 @@ msgstr "The start for gidNumbers, this number is added to a number generated fro
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr "The user ID in Duo."
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr "The user in authentik this device will be assigned to."
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "These bindings control if this stage will be applied to the flow."
@ -6551,6 +6589,7 @@ msgstr "Use this tenant for each domain that doesn't have a dedicated tenant."
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6975,6 +7014,14 @@ msgstr "When this option is enabled, all executions of this policy will be logge
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "When using an external logging solution for archiving, this can be set to \"minutes=5\"."

View File

@ -822,6 +822,10 @@ msgstr ""
msgid "Callback URL"
msgstr "URL de devolución de llamada"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "Puede tener el formato «unix://» cuando se conecta a un demonio de docker local, o «https://:2376» cuando se conecta a un sistema remoto."
@ -1828,10 +1832,22 @@ msgstr "Escenario ficticio utilizado para las pruebas. Muestra un botón de cont
#~ msgid "Duo"
#~ msgstr "Dúo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Autenticadores duo"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Activación dúo"
@ -2763,9 +2779,16 @@ msgstr "Se ha iniciado la suplantación"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "Importación"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "Flujo de importación"
@ -2812,6 +2835,7 @@ msgstr "Incluir reclamos en id_token"
msgid "Integration"
msgstr "Integración"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "Clave de integración"
@ -3131,6 +3155,7 @@ msgstr "Cargando"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4749,6 +4774,7 @@ msgstr "Modo de búsqueda"
msgid "Search..."
msgstr "Buscar..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "Clave secreta"
@ -5432,6 +5458,10 @@ msgstr "Se ha generado correctamente el par de claves de certificado."
msgid "Successfully generated recovery link"
msgstr "Enlace de recuperación generado correctamente"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "El flujo se importó correctamente."
@ -5820,6 +5850,14 @@ msgstr "El comienzo de GIDNumbers, este número se agrega a un número generado
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "El comienzo de UIDNumbers, este número se agrega a User.pk para asegurarse de que los números no sean demasiado bajos para los usuarios de POSIX. El valor predeterminado es 2000 para garantizar que no colisionemos con el UIDNumber de los usuarios locales"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "Estos enlaces controlan si esta etapa se aplicará al flujo."
@ -6424,6 +6462,7 @@ msgstr "Use este inquilino para cada dominio que no tenga un inquilino dedicado.
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6839,6 +6878,12 @@ msgstr "Cuando se habilita esta opción, se registrarán todas las ejecuciones d
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "Cuando se usa junto con una etapa User Write, use attribues.foo para escribir atributos."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "Cuando se utiliza una solución de registro externa para archivar, se puede establecer en «minutes = 5\"."

View File

@ -828,6 +828,10 @@ msgstr ""
msgid "Callback URL"
msgstr "URL de rappel"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#: src/pages/outposts/ServiceConnectionDockerForm.ts
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "Peut être au format \"unix://\" pour une connexion à un service docker local, ou \"https://:2376\" pour une connexion à un système distant."
@ -1846,10 +1850,22 @@ msgstr "Étape factice utilisée pour les tests. Montre un simple bouton continu
#~ msgid "Duo"
#~ msgstr "Duo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Authentificateurs Duo"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Activation Duo"
@ -2793,9 +2809,16 @@ msgstr "Début de l'appropriation utilisateur"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "Importer"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "Importer un flux"
@ -2842,6 +2865,7 @@ msgstr "Include les demandes utilisateurs dans id_token"
msgid "Integration"
msgstr "Intégration"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "Clé d'intégration"
@ -3162,6 +3186,7 @@ msgstr "Chargement en cours"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4797,6 +4822,7 @@ msgstr ""
msgid "Search..."
msgstr "Rechercher..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "Clé secrète"
@ -5493,6 +5519,10 @@ msgstr "Paire clé/certificat générée avec succès."
msgid "Successfully generated recovery link"
msgstr "Lien de récupération généré avec succès"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "Flux importé avec succès"
@ -5880,6 +5910,14 @@ msgstr "Ce nombre est ajouté au nombre généré à partir de group.Pk pour s'a
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "Ce nombre est ajouté au nombre généré à partir de user.Pk pour s'assurer que ceux-ci ne sont pas trop bas pour les utilisateurs POSIX. La valeur par défaut est 2000 pour éviter des collisions avec les uidNumber des utilisateurs locaux."
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "Ces liaisons contrôlent si cette étape sera appliquée au flux."
@ -6482,6 +6520,7 @@ msgstr "Utilisez ce locataire pour chaque domaine qui ne dispose pas d'un locata
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6902,6 +6941,12 @@ msgstr "Si activée, toutes les exécutions de cette politique seront enregistr
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "En cas d'utilisation d'une solution de journalisation externe pour l'archivage, cette valeur peut être fixée à \"minutes=5\"."

View File

@ -819,6 +819,10 @@ msgstr ""
msgid "Callback URL"
msgstr "URL wywołania zwrotnego"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "Może mieć format „unix://” w przypadku łączenia się z lokalnym demonem dockera lub „https://:2376” w przypadku łączenia się z systemem zdalnym."
@ -1825,10 +1829,22 @@ msgstr "Atrapa etapu używana do testowania. Pokazuje prosty przycisk kontynuuj
#~ msgid "Duo"
#~ msgstr "Duo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Uwierzytelniacze Duo"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Aktywacja Duo"
@ -2760,9 +2776,16 @@ msgstr "Rozpoczęto podszywanie się"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "Importuj"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "Importuj przepływ"
@ -2809,6 +2832,7 @@ msgstr "Uwzględnij roszczenia w id_token"
msgid "Integration"
msgstr "Integracja"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "Klucz integracji"
@ -3128,6 +3152,7 @@ msgstr "Ładowanie"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4746,6 +4771,7 @@ msgstr "Tryb szukania"
msgid "Search..."
msgstr "Szukaj..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "Sekretny klucz"
@ -5429,6 +5455,10 @@ msgstr "Pomyślnie wygenerowana para certyfikat-klucz."
msgid "Successfully generated recovery link"
msgstr "Pomyślnie wygenerowano link odzyskiwania"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "Pomyślnie zaimportowano przepływ."
@ -5817,6 +5847,14 @@ msgstr "Początek gidNumbers, liczba ta jest dodawana do liczby wygenerowanej z
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "Początek dla uidNumbers, ten numer jest dodawany do user.Pk, aby upewnić się, że liczby nie są zbyt niskie dla użytkowników POSIX. Wartość domyślna to 2000, aby zapewnić, że nie kolidujemy z lokalnymi użytkownikami uidNumber"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "Te powiązania kontrolują, czy ten etap zostanie zastosowany do przepływu."
@ -6421,6 +6459,7 @@ msgstr "Użyj tego najemcy dla każdej domeny, która nie ma dedykowanej najmecy
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6836,6 +6875,12 @@ msgstr "Gdy ta opcja jest włączona, wszystkie wykonania tej zasady będą reje
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "W przypadku użycia w połączeniu z etapem zapisu użytkownika, użyj attribute.foo do zapisania atrybutów."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "W przypadku korzystania z zewnętrznego rozwiązania rejestrującego do archiwizacji można to ustawić na „minuty=5”."

View File

@ -821,6 +821,10 @@ msgstr ""
msgid "Callback URL"
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#: src/pages/outposts/ServiceConnectionDockerForm.ts
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr ""
@ -1849,10 +1853,22 @@ msgstr ""
#~ msgid "Duo"
#~ msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr ""
@ -2801,9 +2817,16 @@ msgstr ""
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr ""
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr ""
@ -2850,6 +2873,7 @@ msgstr ""
msgid "Integration"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr ""
@ -3172,6 +3196,7 @@ msgstr ""
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4816,6 +4841,7 @@ msgstr ""
msgid "Search..."
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr ""
@ -5524,6 +5550,10 @@ msgstr ""
msgid "Successfully generated recovery link"
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr ""
@ -5916,6 +5946,14 @@ msgstr ""
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr ""
@ -6521,6 +6559,7 @@ msgstr ""
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6943,6 +6982,12 @@ msgstr ""
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr ""

View File

@ -822,6 +822,10 @@ msgstr ""
msgid "Callback URL"
msgstr "Geri arama URL'si"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "Yerel bir docker serine bağlanırken 'unix: //' biçiminde veya uzak bir sisteme bağlanırken 'https://:2376' biçiminde olabilir."
@ -1828,10 +1832,22 @@ msgstr "Test için kullanılan kukla aşama. Basit bir devam düğmesi gösterir
#~ msgid "Duo"
#~ msgstr "İkili"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Duo Kimlik Doğrulayıcıları"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "İkili aktivasyon"
@ -2764,9 +2780,16 @@ msgstr "Kimliğe bürünme başladı"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "İçe Aktar"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "Akışı İçe Aktar"
@ -2813,6 +2836,7 @@ msgstr "İd_token'a hak taleplerini dahil et"
msgid "Integration"
msgstr "Entegrasyon"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "Entegrasyon anahtarı"
@ -3132,6 +3156,7 @@ msgstr "Yükleniyor"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4751,6 +4776,7 @@ msgstr "Arama modu"
msgid "Search..."
msgstr "Ara..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "Gizli anahtar"
@ -5434,6 +5460,10 @@ msgstr "Sertifika-anahtar çifti başarıyla oluşturuldu."
msgid "Successfully generated recovery link"
msgstr "Kurtarma bağlantısı başarıyla oluşturuldu"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "Akış başarıyla aktarıldı."
@ -5822,6 +5852,14 @@ msgstr "gidNumbers'ın başlangıcı, bu sayı group.Pk öğesinden oluşturulan
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "UidNumbers'ın başlangıcında, bu sayı, POSIX kullanıcıları için sayıların çok düşük olmadığından emin olmak için user.Pk öğesine eklenir. Varsayılan 2000 yerel kullanıcılarla çarpışmadığımızdan emin olmak için uidNumber"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "Bu bağlamalar, bu aşama akışa uygulanacak olup olmadığını denetler."
@ -6426,6 +6464,7 @@ msgstr "Bu sakini, ayrılmış bir sakine sahip olmayan her etki alanı için ku
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6841,6 +6880,12 @@ msgstr "Bu seçenek etkinleştirildiğinde, bu ilkenin tüm yürütmeleri günl
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "Kullanıcı Yazma aşaması ile birlikte kullanıldığında, öznitelikleri yazmak için attributes.foo kullanın."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "Arşivleme için harici bir günlük çözümü kullanırken, bu “Dakika = 5\" olarak ayarlanabilir."

View File

@ -817,6 +817,10 @@ msgstr ""
msgid "Callback URL"
msgstr "回调 URL"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "连接到本地 Docker 守护进程时可以采用 'unix://' 格式,或者在连接到远程系统时采用 'https://:2376' 格式。"
@ -1821,10 +1825,22 @@ msgstr "用于测试的虚拟阶段。显示一个简单的“继续”按钮,
#~ msgid "Duo"
#~ msgstr "Duo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Duo 身份验证器"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Duo 激活"
@ -2748,9 +2764,16 @@ msgstr "已开始模拟身份"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "导入"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "导入流程"
@ -2797,6 +2820,7 @@ msgstr "在 id_token 中包含声明"
msgid "Integration"
msgstr "集成"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "集成密钥"
@ -3115,6 +3139,7 @@ msgstr "正在加载"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4717,6 +4742,7 @@ msgstr "搜索模式"
msgid "Search..."
msgstr "搜索..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "Secret 密钥"
@ -5398,6 +5424,10 @@ msgstr "已成功生成证书密钥对。"
msgid "Successfully generated recovery link"
msgstr "已成功生成恢复链接"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "已成功导入流程。"
@ -5785,6 +5815,14 @@ msgstr "起始 gidNumbers这个数字会被添加到从 group.Pk 生成的数
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "起始 uidNumbers这个数字会被添加到 user.Pk 中,以确保对于 POSIX 用户来说,这个数字不会太低。默认值为 2000以确保我们不会与本地用户的 uidNumber 发生冲突"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "这些绑定控制是否将此阶段应用于流程。"
@ -6387,6 +6425,7 @@ msgstr "所有未设置专用租户的域名都将使用此租户。"
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6803,6 +6842,12 @@ msgstr "启用此选项后,将记录此策略的所有执行日志。默认情
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "当与用户写入阶段结合使用时,请使用 attributes.foo 来编写属性。"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "使用外部日志记录解决方案进行存档时,可以将其设置为 \"minutes=5\"。"

View File

@ -819,6 +819,10 @@ msgstr ""
msgid "Callback URL"
msgstr "回调 URL"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "连接到本地 docker 守护进程时可以采用 'unix://' 的格式,或者在连接到远程系统时采用 'https://:2376' 的格式。"
@ -1824,10 +1828,22 @@ msgstr "用于测试的虚拟阶段。显示一个简单的 “继续” 按钮
#~ msgid "Duo"
#~ msgstr "Duo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Duo 身份验证器"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Duo 激活"
@ -2751,9 +2767,16 @@ msgstr "模拟已开始"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "导入"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "导入流程"
@ -2800,6 +2823,7 @@ msgstr "在 id_token 中包含声明"
msgid "Integration"
msgstr "整合"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "集成密钥"
@ -3119,6 +3143,7 @@ msgstr "正在加载"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4723,6 +4748,7 @@ msgstr "搜索模式"
msgid "Search..."
msgstr "搜索..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "密钥"
@ -5405,6 +5431,10 @@ msgstr "成功生成证书密钥对。"
msgid "Successfully generated recovery link"
msgstr "成功生成恢复链接"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "已成功导入流程。"
@ -5792,6 +5822,14 @@ msgstr "对于 GIDNumbers 来说,这个数字被添加到从 group.pk 生成
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "对于UIDNumbers来说这个数字被添加到User.pk中以确保对于POSIX用户来说这个数字不会太低。默认值为 2000以确保我们不会与本地用户 uidNumber 发生冲突"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "这些绑定控制是否将此阶段应用于流程。"
@ -6396,6 +6434,7 @@ msgstr "对于没有专用租户的每个域,请使用此租户。"
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6813,6 +6852,12 @@ msgstr "启用此选项后,将记录此策略的所有执行。默认情况下
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "当与用户写入阶段结合使用时,请使用 attributes.foo 来编写属性。"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "使用外部日志记录解决方案进行存档时,可以将其设置为 “minutes=5”。"

View File

@ -819,6 +819,10 @@ msgstr ""
msgid "Callback URL"
msgstr "回调 URL"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Can be either the username (found in the Users list) or the ID (can be found in the URL after clicking on a user)."
msgstr ""
#~ msgid "Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system."
#~ msgstr "连接到本地 docker 守护进程时可以采用 'unix://' 的格式,或者在连接到远程系统时采用 'https://:2376' 的格式。"
@ -1824,10 +1828,22 @@ msgstr "用于测试的虚拟阶段。显示一个简单的 “继续” 按钮
#~ msgid "Duo"
#~ msgstr "Duo"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Admin API (optional)"
msgstr ""
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Duo Auth API"
msgstr ""
#: src/admin/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Duo Authenticators"
msgstr "Duo 身份验证器"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Duo User ID"
msgstr ""
#: src/flow/stages/authenticator_duo/AuthenticatorDuoStage.ts
msgid "Duo activation"
msgstr "Duo 激活"
@ -2751,9 +2767,16 @@ msgstr "模拟已开始"
#: src/admin/flows/FlowListPage.ts
#: src/admin/flows/FlowListPage.ts
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import"
msgstr "导入"
#: src/admin/stages/StageListPage.ts
#: src/admin/stages/StageListPage.ts
msgid "Import Duo device"
msgstr ""
#: src/admin/flows/FlowListPage.ts
msgid "Import Flow"
msgstr "导入流程"
@ -2800,6 +2823,7 @@ msgstr "在 id_token 中包含声明"
msgid "Integration"
msgstr "整合"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Integration key"
msgstr "集成密钥"
@ -3119,6 +3143,7 @@ msgstr "正在加载"
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/sources/saml/SAMLSourceForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/admin/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/admin/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
@ -4723,6 +4748,7 @@ msgstr "搜索模式"
msgid "Search..."
msgstr "搜索..."
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid "Secret key"
msgstr "密钥"
@ -5405,6 +5431,10 @@ msgstr "成功生成证书密钥对。"
msgid "Successfully generated recovery link"
msgstr "成功生成恢复链接"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported device."
msgstr ""
#: src/admin/flows/FlowImportForm.ts
msgid "Successfully imported flow."
msgstr "已成功导入流程。"
@ -5792,6 +5822,14 @@ msgstr "对于 GIDNumbers 来说,这个数字被添加到从 group.pk 生成
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
msgstr "对于UIDNumbers来说这个数字被添加到User.pk中以确保对于POSIX用户来说这个数字不会太低。默认值为 2000以确保我们不会与本地用户 uidNumber 发生冲突"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user ID in Duo."
msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "The user in authentik this device will be assigned to."
msgstr ""
#: src/admin/flows/BoundStagesList.ts
msgid "These bindings control if this stage will be applied to the flow."
msgstr "这些绑定控制是否将此阶段应用于流程。"
@ -6396,6 +6434,7 @@ msgstr "对于没有专用租户的每个域,请使用此租户。"
#: src/admin/policies/PolicyBindingForm.ts
#: src/admin/policies/PolicyTestForm.ts
#: src/admin/property-mappings/PropertyMappingTestForm.ts
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
#: src/admin/tokens/TokenForm.ts
#: src/admin/tokens/TokenListPage.ts
#: src/admin/users/RelatedUserList.ts
@ -6813,6 +6852,12 @@ msgstr "启用此选项后,将记录此策略的所有执行。默认情况下
msgid "When used in conjunction with a User Write stage, use attributes.foo to write attributes."
msgstr "当与用户写入阶段结合使用时,请使用 attributes.foo 来编写属性。"
#: src/admin/stages/authenticator_duo/AuthenticatorDuoStageForm.ts
msgid ""
"When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.\n"
"This will allow authentik to import devices automatically."
msgstr ""
#: src/admin/tenants/TenantForm.ts
msgid "When using an external logging solution for archiving, this can be set to \"minutes=5\"."
msgstr "使用外部日志记录解决方案进行存档时,可以将其设置为 “minutes=5”。"

View File

@ -13,11 +13,21 @@ Devices created reference the stage they were created with, since the API creden
## Importing users
:::info
Due to the way the Duo API works, authentik cannot automatically import existing Duo users.
Due to the way the Duo API works, authentik can only automatically import existing Duo users when a Duo MFA or higher license is active.
:::
:::info
This API requires version 2021.9.1 or later
This requires authentk 2022.9
:::
To import a device, open the Stages list in the authentik Admin interface. On the right next to the import button you'll see an import button, with which you can import Duo devices to authentik users.
The Duo username can be found by navigating to your Duo Admin dashboard and selecting _Users_ in the sidebar. Optionally if you have multiple users with the same username, you can click on a User and copy their ID from the URL, and use that to import the device.
### Older versions
:::info
This API requires authentik 2021.9.1 or later
:::
You can call the `/api/v3/stages/authenticator/duo/{stage_uuid}/import_devices/` endpoint ([see here](https://goauthentik.io/api/#post-/stages/authenticator/duo/-stage_uuid-/import_devices/)) using the following parameters: