Compare commits
	
		
			52 Commits
		
	
	
		
			website/do
			...
			enterprise
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 42a99e3672 | |||
| 4e501f2fbf | |||
| 1cca629464 | |||
| 4efdc3113e | |||
| 5a9b0f7b7a | |||
| 395ccc5af1 | |||
| c8ac4fcdd6 | |||
| 53c36394e9 | |||
| c7fe987c5a | |||
| e48739c8a0 | |||
| b2ee585c43 | |||
| 97e8ea8e76 | |||
| 1f1e0c9db1 | |||
| ca47a803fe | |||
| c606eb53b0 | |||
| 62357133b0 | |||
| 99d2d91257 | |||
| 69d9363fce | |||
| cfc7f6b993 | |||
| bebbbe9b90 | |||
| 188d3c69c1 | |||
| 877f312145 | |||
| f471a98bc7 | |||
| e874cfc21d | |||
| ec7bdf74aa | |||
| e87bc94b95 | |||
| a3865abaa9 | |||
| 7100d3c674 | |||
| c0c2d2ad3c | |||
| dc287989db | |||
| 03204f6943 | |||
| fcd369e466 | |||
| cb79407bc1 | |||
| 04a88daf34 | |||
| c6a49da5c3 | |||
| bfeeecf3fa | |||
| d86b5e7c8a | |||
| a95776891e | |||
| 031158fdba | |||
| b2fbb92498 | |||
| b1b6bf1a19 | |||
| 179d9d0721 | |||
| 8e94d58851 | |||
| 026669cfce | |||
| c83cea6963 | |||
| 8e01cc2df8 | |||
| 279cec203d | |||
| 41c5030c1e | |||
| 3206fdb7ef | |||
| d7c0868eef | |||
| 7d96a89697 | |||
| dfb0007777 | 
| @ -1,5 +1,5 @@ | |||||||
| [bumpversion] | [bumpversion] | ||||||
| current_version = 2025.6.2 | current_version = 2025.6.3 | ||||||
| tag = True | tag = True | ||||||
| commit = 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*))? | parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))? | ||||||
|  | |||||||
| @ -38,6 +38,8 @@ jobs: | |||||||
|       # Needed for attestation |       # Needed for attestation | ||||||
|       id-token: write |       id-token: write | ||||||
|       attestations: write |       attestations: write | ||||||
|  |       # Needed for checkout | ||||||
|  |       contents: read | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v4 |       - uses: actions/checkout@v4 | ||||||
|       - uses: docker/setup-qemu-action@v3.6.0 |       - uses: docker/setup-qemu-action@v3.6.0 | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								.github/workflows/ci-main-daily.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/ci-main-daily.yml
									
									
									
									
										vendored
									
									
								
							| @ -9,6 +9,7 @@ on: | |||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   test-container: |   test-container: | ||||||
|  |     if: ${{ github.repository != 'goauthentik/authentik-internal' }} | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							| @ -247,11 +247,13 @@ jobs: | |||||||
|       # Needed for attestation |       # Needed for attestation | ||||||
|       id-token: write |       id-token: write | ||||||
|       attestations: write |       attestations: write | ||||||
|  |       # Needed for checkout | ||||||
|  |       contents: read | ||||||
|     needs: ci-core-mark |     needs: ci-core-mark | ||||||
|     uses: ./.github/workflows/_reusable-docker-build.yaml |     uses: ./.github/workflows/_reusable-docker-build.yaml | ||||||
|     secrets: inherit |     secrets: inherit | ||||||
|     with: |     with: | ||||||
|       image_name: ghcr.io/goauthentik/dev-server |       image_name: ${{ github.repository == 'goauthentik/authentik-internal' && 'ghcr.io/goauthentik/internal-server' || 'ghcr.io/goauthentik/dev-server' }} | ||||||
|       release: false |       release: false | ||||||
|   pr-comment: |   pr-comment: | ||||||
|     needs: |     needs: | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							| @ -59,6 +59,7 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           jobs: ${{ toJSON(needs) }} |           jobs: ${{ toJSON(needs) }} | ||||||
|   build-container: |   build-container: | ||||||
|  |     if: ${{ github.repository != 'goauthentik/authentik-internal' }} | ||||||
|     timeout-minutes: 120 |     timeout-minutes: 120 | ||||||
|     needs: |     needs: | ||||||
|       - ci-outpost-mark |       - ci-outpost-mark | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								.github/workflows/ci-website.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci-website.yml
									
									
									
									
										vendored
									
									
								
							| @ -63,6 +63,7 @@ jobs: | |||||||
|         working-directory: website/ |         working-directory: website/ | ||||||
|         run: npm run ${{ matrix.job }} |         run: npm run ${{ matrix.job }} | ||||||
|   build-container: |   build-container: | ||||||
|  |     if: ${{ github.repository != 'goauthentik/authentik-internal' }} | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     permissions: |     permissions: | ||||||
|       # Needed to upload container images to ghcr.io |       # Needed to upload container images to ghcr.io | ||||||
| @ -122,3 +123,4 @@ jobs: | |||||||
|       - uses: re-actors/alls-green@release/v1 |       - uses: re-actors/alls-green@release/v1 | ||||||
|         with: |         with: | ||||||
|           jobs: ${{ toJSON(needs) }} |           jobs: ${{ toJSON(needs) }} | ||||||
|  |           allowed-skips: ${{ github.repository == 'goauthentik/authentik-internal' && 'build-container' || '[]' }} | ||||||
|  | |||||||
							
								
								
									
										21
									
								
								.github/workflows/repo-mirror-cleanup.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.github/workflows/repo-mirror-cleanup.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | name: "authentik-repo-mirror-cleanup" | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   workflow_dispatch: | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   to_internal: | ||||||
|  |     if: ${{ github.repository != 'goauthentik/authentik-internal' }} | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - uses: actions/checkout@v4 | ||||||
|  |         with: | ||||||
|  |           fetch-depth: 0 | ||||||
|  |       - if: ${{ env.MIRROR_KEY != '' }} | ||||||
|  |         uses: BeryJu/repository-mirroring-action@5cf300935bc2e068f73ea69bcc411a8a997208eb | ||||||
|  |         with: | ||||||
|  |           target_repo_url: git@github.com:goauthentik/authentik-internal.git | ||||||
|  |           ssh_private_key: ${{ secrets.GH_MIRROR_KEY }} | ||||||
|  |           args: --tags --force --prune | ||||||
|  |         env: | ||||||
|  |           MIRROR_KEY: ${{ secrets.GH_MIRROR_KEY }} | ||||||
							
								
								
									
										9
									
								
								.github/workflows/repo-mirror.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/repo-mirror.yml
									
									
									
									
										vendored
									
									
								
							| @ -11,11 +11,10 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           fetch-depth: 0 |           fetch-depth: 0 | ||||||
|       - if: ${{ env.MIRROR_KEY != '' }} |       - if: ${{ env.MIRROR_KEY != '' }} | ||||||
|         uses: pixta-dev/repository-mirroring-action@v1 |         uses: BeryJu/repository-mirroring-action@5cf300935bc2e068f73ea69bcc411a8a997208eb | ||||||
|         with: |         with: | ||||||
|           target_repo_url: |           target_repo_url: git@github.com:goauthentik/authentik-internal.git | ||||||
|             git@github.com:goauthentik/authentik-internal.git |           ssh_private_key: ${{ secrets.GH_MIRROR_KEY }} | ||||||
|           ssh_private_key: |           args: --tags --force | ||||||
|             ${{ secrets.GH_MIRROR_KEY }} |  | ||||||
|         env: |         env: | ||||||
|           MIRROR_KEY: ${{ secrets.GH_MIRROR_KEY }} |           MIRROR_KEY: ${{ secrets.GH_MIRROR_KEY }} | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ env: | |||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   compile: |   compile: | ||||||
|  |     if: ${{ github.repository != 'goauthentik/authentik-internal' }} | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - id: generate_token |       - id: generate_token | ||||||
|  | |||||||
| @ -75,7 +75,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \ | |||||||
|     /bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0" |     /bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0" | ||||||
|  |  | ||||||
| # Stage 4: Download uv | # Stage 4: Download uv | ||||||
| FROM ghcr.io/astral-sh/uv:0.7.14 AS uv | FROM ghcr.io/astral-sh/uv:0.7.17 AS uv | ||||||
| # Stage 5: Base python image | # Stage 5: Base python image | ||||||
| FROM ghcr.io/goauthentik/fips-python:3.13.5-slim-bookworm-fips AS python-base | FROM ghcr.io/goauthentik/fips-python:3.13.5-slim-bookworm-fips AS python-base | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
								
							| @ -150,9 +150,9 @@ gen-client-ts: gen-clean-ts  ## Build and install the authentik API for Typescri | |||||||
| 		--additional-properties=npmVersion=${NPM_VERSION} \ | 		--additional-properties=npmVersion=${NPM_VERSION} \ | ||||||
| 		--git-repo-id authentik \ | 		--git-repo-id authentik \ | ||||||
| 		--git-user-id goauthentik | 		--git-user-id goauthentik | ||||||
| 	mkdir -p web/node_modules/@goauthentik/api |  | ||||||
| 	cd ${PWD}/${GEN_API_TS} && npm i | 	cd ${PWD}/${GEN_API_TS} && npm link | ||||||
| 	\cp -rf ${PWD}/${GEN_API_TS}/* web/node_modules/@goauthentik/api | 	cd ${PWD}/web && npm link @goauthentik/api | ||||||
|  |  | ||||||
| gen-client-py: gen-clean-py ## Build and install the authentik API for Python | gen-client-py: gen-clean-py ## Build and install the authentik API for Python | ||||||
| 	docker run \ | 	docker run \ | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| from os import environ | from os import environ | ||||||
|  |  | ||||||
| __version__ = "2025.6.2" | __version__ = "2025.6.3" | ||||||
| ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -5,7 +5,6 @@ from collections.abc import Callable | |||||||
| from django.apps import apps | from django.apps import apps | ||||||
| from django.test import TestCase | from django.test import TestCase | ||||||
|  |  | ||||||
| from authentik.blueprints.v1.importer import is_model_allowed |  | ||||||
| from authentik.lib.models import SerializerModel | from authentik.lib.models import SerializerModel | ||||||
| from authentik.providers.oauth2.models import RefreshToken | from authentik.providers.oauth2.models import RefreshToken | ||||||
|  |  | ||||||
| @ -22,10 +21,13 @@ def serializer_tester_factory(test_model: type[SerializerModel]) -> Callable: | |||||||
|             return |             return | ||||||
|         model_class = test_model() |         model_class = test_model() | ||||||
|         self.assertTrue(isinstance(model_class, SerializerModel)) |         self.assertTrue(isinstance(model_class, SerializerModel)) | ||||||
|  |         # Models that have subclasses don't have to have a serializer | ||||||
|  |         if len(test_model.__subclasses__()) > 0: | ||||||
|  |             return | ||||||
|         self.assertIsNotNone(model_class.serializer) |         self.assertIsNotNone(model_class.serializer) | ||||||
|         if model_class.serializer.Meta().model == RefreshToken: |         if model_class.serializer.Meta().model == RefreshToken: | ||||||
|             return |             return | ||||||
|         self.assertEqual(model_class.serializer.Meta().model, test_model) |         self.assertTrue(issubclass(test_model, model_class.serializer.Meta().model)) | ||||||
|  |  | ||||||
|     return tester |     return tester | ||||||
|  |  | ||||||
| @ -34,6 +36,6 @@ for app in apps.get_app_configs(): | |||||||
|     if not app.label.startswith("authentik"): |     if not app.label.startswith("authentik"): | ||||||
|         continue |         continue | ||||||
|     for model in app.get_models(): |     for model in app.get_models(): | ||||||
|         if not is_model_allowed(model): |         if not issubclass(model, SerializerModel): | ||||||
|             continue |             continue | ||||||
|         setattr(TestModels, f"test_{app.label}_{model.__name__}", serializer_tester_factory(model)) |         setattr(TestModels, f"test_{app.label}_{model.__name__}", serializer_tester_factory(model)) | ||||||
|  | |||||||
| @ -43,6 +43,7 @@ from authentik.core.models import ( | |||||||
| ) | ) | ||||||
| from authentik.enterprise.license import LicenseKey | from authentik.enterprise.license import LicenseKey | ||||||
| from authentik.enterprise.models import LicenseUsage | from authentik.enterprise.models import LicenseUsage | ||||||
|  | from authentik.enterprise.providers.apple_psso.models import AppleNonce | ||||||
| from authentik.enterprise.providers.google_workspace.models import ( | from authentik.enterprise.providers.google_workspace.models import ( | ||||||
|     GoogleWorkspaceProviderGroup, |     GoogleWorkspaceProviderGroup, | ||||||
|     GoogleWorkspaceProviderUser, |     GoogleWorkspaceProviderUser, | ||||||
| @ -135,6 +136,7 @@ def excluded_models() -> list[type[Model]]: | |||||||
|         EndpointDeviceConnection, |         EndpointDeviceConnection, | ||||||
|         DeviceToken, |         DeviceToken, | ||||||
|         StreamEvent, |         StreamEvent, | ||||||
|  |         AppleNonce, | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -1082,6 +1082,12 @@ class AuthenticatedSession(SerializerModel): | |||||||
|  |  | ||||||
|     user = models.ForeignKey(User, on_delete=models.CASCADE) |     user = models.ForeignKey(User, on_delete=models.CASCADE) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def serializer(self) -> type[Serializer]: | ||||||
|  |         from authentik.core.api.authenticated_sessions import AuthenticatedSessionSerializer | ||||||
|  |  | ||||||
|  |         return AuthenticatedSessionSerializer | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         verbose_name = _("Authenticated Session") |         verbose_name = _("Authenticated Session") | ||||||
|         verbose_name_plural = _("Authenticated Sessions") |         verbose_name_plural = _("Authenticated Sessions") | ||||||
|  | |||||||
							
								
								
									
										32
									
								
								authentik/enterprise/providers/apple_psso/api/providers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								authentik/enterprise/providers/apple_psso/api/providers.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | |||||||
|  | """Apple Platform SSO Provider API Views""" | ||||||
|  |  | ||||||
|  | from rest_framework.viewsets import ModelViewSet | ||||||
|  |  | ||||||
|  | from authentik.core.api.providers import ProviderSerializer | ||||||
|  | from authentik.core.api.used_by import UsedByMixin | ||||||
|  | from authentik.enterprise.api import EnterpriseRequiredMixin | ||||||
|  | from authentik.enterprise.providers.apple_psso.models import ApplePlatformSSOProvider | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ApplePlatformSSOProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer): | ||||||
|  |     """ApplePlatformSSOProvider Serializer""" | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         model = ApplePlatformSSOProvider | ||||||
|  |         fields = [ | ||||||
|  |             "pk", | ||||||
|  |             "name", | ||||||
|  |         ] | ||||||
|  |         extra_kwargs = {} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ApplePlatformSSOProviderViewSet(UsedByMixin, ModelViewSet): | ||||||
|  |     """ApplePlatformSSOProvider Viewset""" | ||||||
|  |  | ||||||
|  |     queryset = ApplePlatformSSOProvider.objects.all() | ||||||
|  |     serializer_class = ApplePlatformSSOProviderSerializer | ||||||
|  |     filterset_fields = [ | ||||||
|  |         "name", | ||||||
|  |     ] | ||||||
|  |     search_fields = ["name"] | ||||||
|  |     ordering = ["name"] | ||||||
							
								
								
									
										13
									
								
								authentik/enterprise/providers/apple_psso/apps.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								authentik/enterprise/providers/apple_psso/apps.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | from authentik.enterprise.apps import EnterpriseConfig | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AuthentikEnterpriseProviderApplePSSOConfig(EnterpriseConfig): | ||||||
|  |  | ||||||
|  |     name = "authentik.enterprise.providers.apple_psso" | ||||||
|  |     label = "authentik_providers_apple_psso" | ||||||
|  |     verbose_name = "authentik Enterprise.Providers.Apple Platform SSO" | ||||||
|  |     default = True | ||||||
|  |     mountpoints = { | ||||||
|  |         "authentik.enterprise.providers.apple_psso.urls": "endpoint/apple/sso/", | ||||||
|  |         "authentik.enterprise.providers.apple_psso.urls_root": "", | ||||||
|  |     } | ||||||
							
								
								
									
										118
									
								
								authentik/enterprise/providers/apple_psso/http.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								authentik/enterprise/providers/apple_psso/http.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,118 @@ | |||||||
|  | from base64 import urlsafe_b64encode | ||||||
|  | from json import dumps | ||||||
|  | from secrets import token_bytes | ||||||
|  |  | ||||||
|  | from cryptography.hazmat.backends import default_backend | ||||||
|  | from cryptography.hazmat.primitives import hashes, serialization | ||||||
|  | from cryptography.hazmat.primitives.asymmetric import ec | ||||||
|  | from cryptography.hazmat.primitives.ciphers.aead import AESGCM | ||||||
|  | from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash | ||||||
|  | from django.http import HttpResponse | ||||||
|  | from jwcrypto.common import base64url_decode, base64url_encode | ||||||
|  |  | ||||||
|  | from authentik.enterprise.providers.apple_psso.models import AppleDevice | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def length_prefixed(data: bytes) -> bytes: | ||||||
|  |     length = len(data) | ||||||
|  |     return length.to_bytes(4, "big") + data | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def build_apu(public_key: ec.EllipticCurvePublicKey): | ||||||
|  |     # X9.63 representation: 0x04 || X || Y | ||||||
|  |     public_numbers = public_key.public_numbers() | ||||||
|  |  | ||||||
|  |     x_bytes = public_numbers.x.to_bytes(32, "big") | ||||||
|  |     y_bytes = public_numbers.y.to_bytes(32, "big") | ||||||
|  |  | ||||||
|  |     x963 = bytes([0x04]) + x_bytes + y_bytes | ||||||
|  |  | ||||||
|  |     result = length_prefixed(b"APPLE") + length_prefixed(x963) | ||||||
|  |  | ||||||
|  |     return result | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def encrypt_token_with_a256_gcm(body: dict, device_encryption_key: str, apv: bytes) -> str: | ||||||
|  |     ephemeral_key = ec.generate_private_key(curve=ec.SECP256R1()) | ||||||
|  |     device_public_key = serialization.load_pem_public_key( | ||||||
|  |         device_encryption_key.encode(), backend=default_backend() | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     shared_secret_z = ephemeral_key.exchange(ec.ECDH(), device_public_key) | ||||||
|  |  | ||||||
|  |     apu = build_apu(ephemeral_key.public_key()) | ||||||
|  |  | ||||||
|  |     jwe_header = { | ||||||
|  |         "enc": "A256GCM", | ||||||
|  |         "kid": "ephemeralKey", | ||||||
|  |         "epk": { | ||||||
|  |             "x": base64url_encode( | ||||||
|  |                 ephemeral_key.public_key().public_numbers().x.to_bytes(32, "big") | ||||||
|  |             ), | ||||||
|  |             "y": base64url_encode( | ||||||
|  |                 ephemeral_key.public_key().public_numbers().y.to_bytes(32, "big") | ||||||
|  |             ), | ||||||
|  |             "kty": "EC", | ||||||
|  |             "crv": "P-256", | ||||||
|  |         }, | ||||||
|  |         "typ": "platformsso-login-response+jwt", | ||||||
|  |         "alg": "ECDH-ES", | ||||||
|  |         "apu": base64url_encode(apu), | ||||||
|  |         "apv": base64url_encode(apv), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     party_u_info = length_prefixed(apu) | ||||||
|  |     party_v_info = length_prefixed(apv) | ||||||
|  |     supp_pub_info = (256).to_bytes(4, "big") | ||||||
|  |  | ||||||
|  |     other_info = length_prefixed(b"A256GCM") + party_u_info + party_v_info + supp_pub_info | ||||||
|  |  | ||||||
|  |     ckdf = ConcatKDFHash( | ||||||
|  |         algorithm=hashes.SHA256(), | ||||||
|  |         length=32, | ||||||
|  |         otherinfo=other_info, | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     derived_key = ckdf.derive(shared_secret_z) | ||||||
|  |  | ||||||
|  |     nonce = token_bytes(12) | ||||||
|  |  | ||||||
|  |     header_json = dumps(jwe_header, separators=(",", ":")).encode() | ||||||
|  |     aad = urlsafe_b64encode(header_json).rstrip(b"=") | ||||||
|  |  | ||||||
|  |     aesgcm = AESGCM(derived_key) | ||||||
|  |     ciphertext = aesgcm.encrypt(nonce, dumps(body).encode(), aad) | ||||||
|  |  | ||||||
|  |     ciphertext_body = ciphertext[:-16] | ||||||
|  |     tag = ciphertext[-16:] | ||||||
|  |  | ||||||
|  |     # base64url encoding | ||||||
|  |     protected_b64 = urlsafe_b64encode(header_json).rstrip(b"=") | ||||||
|  |     iv_b64 = urlsafe_b64encode(nonce).rstrip(b"=") | ||||||
|  |     ciphertext_b64 = urlsafe_b64encode(ciphertext_body).rstrip(b"=") | ||||||
|  |     tag_b64 = urlsafe_b64encode(tag).rstrip(b"=") | ||||||
|  |  | ||||||
|  |     jwe_compact = b".".join( | ||||||
|  |         [ | ||||||
|  |             protected_b64, | ||||||
|  |             b"", | ||||||
|  |             iv_b64, | ||||||
|  |             ciphertext_b64, | ||||||
|  |             tag_b64, | ||||||
|  |         ] | ||||||
|  |     ) | ||||||
|  |     return jwe_compact.decode() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class JWEResponse(HttpResponse): | ||||||
|  |  | ||||||
|  |     def __init__( | ||||||
|  |         self, | ||||||
|  |         data: dict, | ||||||
|  |         device: AppleDevice, | ||||||
|  |         apv: str, | ||||||
|  |     ): | ||||||
|  |         super().__init__( | ||||||
|  |             content=encrypt_token_with_a256_gcm(data, device.encryption_key, base64url_decode(apv)), | ||||||
|  |             content_type="application/platformsso-login-response+jwt", | ||||||
|  |         ) | ||||||
| @ -0,0 +1,36 @@ | |||||||
|  | # Generated by Django 5.1.11 on 2025-06-28 00:12 | ||||||
|  |  | ||||||
|  | import django.db.models.deletion | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     initial = True | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ("authentik_providers_oauth2", "0028_migrate_session"), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name="ApplePlatformSSOProvider", | ||||||
|  |             fields=[ | ||||||
|  |                 ( | ||||||
|  |                     "oauth2provider_ptr", | ||||||
|  |                     models.OneToOneField( | ||||||
|  |                         auto_created=True, | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, | ||||||
|  |                         parent_link=True, | ||||||
|  |                         primary_key=True, | ||||||
|  |                         serialize=False, | ||||||
|  |                         to="authentik_providers_oauth2.oauth2provider", | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 "abstract": False, | ||||||
|  |             }, | ||||||
|  |             bases=("authentik_providers_oauth2.oauth2provider",), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @ -0,0 +1,94 @@ | |||||||
|  | # Generated by Django 5.1.11 on 2025-06-28 15:50 | ||||||
|  |  | ||||||
|  | import django.db.models.deletion | ||||||
|  | import uuid | ||||||
|  | from django.conf import settings | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ("authentik_providers_apple_psso", "0001_initial"), | ||||||
|  |         migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name="AppleDevice", | ||||||
|  |             fields=[ | ||||||
|  |                 ( | ||||||
|  |                     "endpoint_uuid", | ||||||
|  |                     models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False), | ||||||
|  |                 ), | ||||||
|  |                 ("signing_key", models.TextField()), | ||||||
|  |                 ("encryption_key", models.TextField()), | ||||||
|  |                 ("key_exchange_key", models.TextField()), | ||||||
|  |                 ("sign_key_id", models.TextField()), | ||||||
|  |                 ("enc_key_id", models.TextField()), | ||||||
|  |                 ("creation_time", models.DateTimeField(auto_now_add=True)), | ||||||
|  |                 ( | ||||||
|  |                     "provider", | ||||||
|  |                     models.ForeignKey( | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, | ||||||
|  |                         to="authentik_providers_apple_psso.appleplatformssoprovider", | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |             ], | ||||||
|  |         ), | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name="AppleDeviceUser", | ||||||
|  |             fields=[ | ||||||
|  |                 ("uuid", models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), | ||||||
|  |                 ("signing_key", models.TextField()), | ||||||
|  |                 ("encryption_key", models.TextField()), | ||||||
|  |                 ("sign_key_id", models.TextField()), | ||||||
|  |                 ("enc_key_id", models.TextField()), | ||||||
|  |                 ( | ||||||
|  |                     "device", | ||||||
|  |                     models.ForeignKey( | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, | ||||||
|  |                         to="authentik_providers_apple_psso.appledevice", | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |                 ( | ||||||
|  |                     "user", | ||||||
|  |                     models.ForeignKey( | ||||||
|  |                         on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |             ], | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name="appledevice", | ||||||
|  |             name="users", | ||||||
|  |             field=models.ManyToManyField( | ||||||
|  |                 through="authentik_providers_apple_psso.AppleDeviceUser", | ||||||
|  |                 to=settings.AUTH_USER_MODEL, | ||||||
|  |             ), | ||||||
|  |         ), | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name="AppleNonce", | ||||||
|  |             fields=[ | ||||||
|  |                 ( | ||||||
|  |                     "id", | ||||||
|  |                     models.AutoField( | ||||||
|  |                         auto_created=True, primary_key=True, serialize=False, verbose_name="ID" | ||||||
|  |                     ), | ||||||
|  |                 ), | ||||||
|  |                 ("expires", models.DateTimeField(default=None, null=True)), | ||||||
|  |                 ("expiring", models.BooleanField(default=True)), | ||||||
|  |                 ("nonce", models.TextField()), | ||||||
|  |             ], | ||||||
|  |             options={ | ||||||
|  |                 "abstract": False, | ||||||
|  |                 "indexes": [ | ||||||
|  |                     models.Index(fields=["expires"], name="authentik_p_expires_47d534_idx"), | ||||||
|  |                     models.Index(fields=["expiring"], name="authentik_p_expirin_87253e_idx"), | ||||||
|  |                     models.Index( | ||||||
|  |                         fields=["expiring", "expires"], name="authentik_p_expirin_20a7c9_idx" | ||||||
|  |                     ), | ||||||
|  |                 ], | ||||||
|  |             }, | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | # Generated by Django 5.1.11 on 2025-06-28 22:18 | ||||||
|  |  | ||||||
|  | from django.db import migrations | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ( | ||||||
|  |             "authentik_providers_apple_psso", | ||||||
|  |             "0002_appledevice_appledeviceuser_appledevice_users_and_more", | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.RenameField( | ||||||
|  |             model_name="appledeviceuser", | ||||||
|  |             old_name="sign_key_id", | ||||||
|  |             new_name="enclave_key_id", | ||||||
|  |         ), | ||||||
|  |         migrations.RenameField( | ||||||
|  |             model_name="appledeviceuser", | ||||||
|  |             old_name="signing_key", | ||||||
|  |             new_name="secure_enclave_key", | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name="appledeviceuser", | ||||||
|  |             name="enc_key_id", | ||||||
|  |         ), | ||||||
|  |         migrations.RemoveField( | ||||||
|  |             model_name="appledeviceuser", | ||||||
|  |             name="encryption_key", | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
							
								
								
									
										85
									
								
								authentik/enterprise/providers/apple_psso/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								authentik/enterprise/providers/apple_psso/models.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,85 @@ | |||||||
|  | from uuid import uuid4 | ||||||
|  |  | ||||||
|  | from django.db import models | ||||||
|  | from django.utils.translation import gettext_lazy as _ | ||||||
|  | from rest_framework.serializers import Serializer | ||||||
|  |  | ||||||
|  | from authentik.core.models import ExpiringModel, User | ||||||
|  | from authentik.crypto.models import CertificateKeyPair | ||||||
|  | from authentik.providers.oauth2.models import ( | ||||||
|  |     ClientTypes, | ||||||
|  |     IssuerMode, | ||||||
|  |     OAuth2Provider, | ||||||
|  |     RedirectURI, | ||||||
|  |     RedirectURIMatchingMode, | ||||||
|  |     ScopeMapping, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ApplePlatformSSOProvider(OAuth2Provider): | ||||||
|  |     """Integrate with Apple Platform SSO""" | ||||||
|  |  | ||||||
|  |     def set_oauth_defaults(self): | ||||||
|  |         """Ensure all OAuth2-related settings are correct""" | ||||||
|  |         self.issuer_mode = IssuerMode.PER_PROVIDER | ||||||
|  |         self.client_type = ClientTypes.PUBLIC | ||||||
|  |         self.signing_key = CertificateKeyPair.objects.get(name="authentik Self-signed Certificate") | ||||||
|  |         self.include_claims_in_id_token = True | ||||||
|  |         scopes = ScopeMapping.objects.filter( | ||||||
|  |             managed__in=[ | ||||||
|  |                 "goauthentik.io/providers/oauth2/scope-openid", | ||||||
|  |                 "goauthentik.io/providers/oauth2/scope-profile", | ||||||
|  |                 "goauthentik.io/providers/oauth2/scope-email", | ||||||
|  |                 "goauthentik.io/providers/oauth2/scope-offline_access", | ||||||
|  |                 "goauthentik.io/providers/oauth2/scope-authentik_api", | ||||||
|  |             ] | ||||||
|  |         ) | ||||||
|  |         self.property_mappings.add(*list(scopes)) | ||||||
|  |         self.redirect_uris = [ | ||||||
|  |             RedirectURI(RedirectURIMatchingMode.STRICT, "io.goauthentik.endpoint:/oauth2redirect"), | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def component(self) -> str: | ||||||
|  |         return "ak-provider-apple-psso-form" | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def serializer(self) -> type[Serializer]: | ||||||
|  |         from authentik.enterprise.providers.apple_psso.api.providers import ( | ||||||
|  |             ApplePlatformSSOProviderSerializer, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         return ApplePlatformSSOProviderSerializer | ||||||
|  |  | ||||||
|  |     class Meta: | ||||||
|  |         verbose_name = _("Apple Platform SSO Provider") | ||||||
|  |         verbose_name_plural = _("Apple Platform SSO Providers") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AppleDevice(models.Model): | ||||||
|  |  | ||||||
|  |     endpoint_uuid = models.UUIDField(default=uuid4, primary_key=True) | ||||||
|  |  | ||||||
|  |     signing_key = models.TextField() | ||||||
|  |     encryption_key = models.TextField() | ||||||
|  |     key_exchange_key = models.TextField() | ||||||
|  |     sign_key_id = models.TextField() | ||||||
|  |     enc_key_id = models.TextField() | ||||||
|  |     creation_time = models.DateTimeField(auto_now_add=True) | ||||||
|  |     provider = models.ForeignKey(ApplePlatformSSOProvider, on_delete=models.CASCADE) | ||||||
|  |     users = models.ManyToManyField(User, through="AppleDeviceUser") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AppleDeviceUser(models.Model): | ||||||
|  |  | ||||||
|  |     uuid = models.UUIDField(default=uuid4, primary_key=True) | ||||||
|  |  | ||||||
|  |     device = models.ForeignKey(AppleDevice, on_delete=models.CASCADE) | ||||||
|  |     user = models.ForeignKey(User, on_delete=models.CASCADE) | ||||||
|  |  | ||||||
|  |     secure_enclave_key = models.TextField() | ||||||
|  |     enclave_key_id = models.TextField() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AppleNonce(ExpiringModel): | ||||||
|  |     nonce = models.TextField() | ||||||
							
								
								
									
										15
									
								
								authentik/enterprise/providers/apple_psso/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								authentik/enterprise/providers/apple_psso/urls.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | from django.urls import path | ||||||
|  |  | ||||||
|  | from authentik.enterprise.providers.apple_psso.views.nonce import NonceView | ||||||
|  | from authentik.enterprise.providers.apple_psso.views.register import ( | ||||||
|  |     RegisterDeviceView, | ||||||
|  |     RegisterUserView, | ||||||
|  | ) | ||||||
|  | from authentik.enterprise.providers.apple_psso.views.token import TokenView | ||||||
|  |  | ||||||
|  | urlpatterns = [ | ||||||
|  |     path("token/", TokenView.as_view(), name="token"), | ||||||
|  |     path("nonce/", NonceView.as_view(), name="nonce"), | ||||||
|  |     path("register/device/", RegisterDeviceView.as_view(), name="register-device"), | ||||||
|  |     path("register/user/", RegisterUserView.as_view(), name="register-user"), | ||||||
|  | ] | ||||||
							
								
								
									
										7
									
								
								authentik/enterprise/providers/apple_psso/urls_root.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								authentik/enterprise/providers/apple_psso/urls_root.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | from django.urls import path | ||||||
|  |  | ||||||
|  | from authentik.enterprise.providers.apple_psso.views.site_association import AppleAppSiteAssociation | ||||||
|  |  | ||||||
|  | urlpatterns = [ | ||||||
|  |     path(".well-known/apple-app-site-association", AppleAppSiteAssociation.as_view(), name="asa"), | ||||||
|  | ] | ||||||
							
								
								
									
										25
									
								
								authentik/enterprise/providers/apple_psso/views/nonce.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								authentik/enterprise/providers/apple_psso/views/nonce.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | from base64 import b64encode | ||||||
|  | from datetime import timedelta | ||||||
|  | from secrets import token_bytes | ||||||
|  |  | ||||||
|  | from django.http import HttpRequest, JsonResponse | ||||||
|  | from django.utils.decorators import method_decorator | ||||||
|  | from django.utils.timezone import now | ||||||
|  | from django.views import View | ||||||
|  | from django.views.decorators.csrf import csrf_exempt | ||||||
|  |  | ||||||
|  | from authentik.enterprise.providers.apple_psso.models import AppleNonce | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @method_decorator(csrf_exempt, name="dispatch") | ||||||
|  | class NonceView(View): | ||||||
|  |  | ||||||
|  |     def post(self, request: HttpRequest, *args, **kwargs): | ||||||
|  |         nonce = AppleNonce.objects.create( | ||||||
|  |             nonce=b64encode(token_bytes(32)).decode(), expires=now() + timedelta(minutes=5) | ||||||
|  |         ) | ||||||
|  |         return JsonResponse( | ||||||
|  |             { | ||||||
|  |                 "Nonce": nonce.nonce, | ||||||
|  |             } | ||||||
|  |         ) | ||||||
							
								
								
									
										92
									
								
								authentik/enterprise/providers/apple_psso/views/register.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								authentik/enterprise/providers/apple_psso/views/register.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | |||||||
|  | from django.shortcuts import get_object_or_404 | ||||||
|  | from rest_framework.authentication import BaseAuthentication | ||||||
|  | from rest_framework.fields import CharField | ||||||
|  | from rest_framework.request import Request | ||||||
|  | from rest_framework.response import Response | ||||||
|  | from rest_framework.views import APIView | ||||||
|  |  | ||||||
|  | from authentik.api.authentication import TokenAuthentication | ||||||
|  | from authentik.core.api.utils import PassiveSerializer | ||||||
|  | from authentik.core.models import User | ||||||
|  | from authentik.enterprise.providers.apple_psso.models import ( | ||||||
|  |     AppleDevice, | ||||||
|  |     AppleDeviceUser, | ||||||
|  |     ApplePlatformSSOProvider, | ||||||
|  | ) | ||||||
|  | from authentik.lib.generators import generate_key | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DeviceRegisterAuth(BaseAuthentication): | ||||||
|  |     def authenticate(self, request): | ||||||
|  |         # very temporary, lol | ||||||
|  |         return (User(), None) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RegisterDeviceView(APIView): | ||||||
|  |  | ||||||
|  |     class DeviceRegistration(PassiveSerializer): | ||||||
|  |  | ||||||
|  |         device_uuid = CharField() | ||||||
|  |         client_id = CharField() | ||||||
|  |         device_signing_key = CharField() | ||||||
|  |         device_encryption_key = CharField() | ||||||
|  |         sign_key_id = CharField() | ||||||
|  |         enc_key_id = CharField() | ||||||
|  |  | ||||||
|  |     permission_classes = [] | ||||||
|  |     pagination_class = None | ||||||
|  |     filter_backends = [] | ||||||
|  |     serializer_class = DeviceRegistration | ||||||
|  |     authentication_classes = [DeviceRegisterAuth, TokenAuthentication] | ||||||
|  |  | ||||||
|  |     def post(self, request: Request) -> Response: | ||||||
|  |         data = self.DeviceRegistration(data=request.data) | ||||||
|  |         data.is_valid(raise_exception=True) | ||||||
|  |         provider = get_object_or_404( | ||||||
|  |             ApplePlatformSSOProvider, client_id=data.validated_data["client_id"] | ||||||
|  |         ) | ||||||
|  |         AppleDevice.objects.update_or_create( | ||||||
|  |             endpoint_uuid=data.validated_data["device_uuid"], | ||||||
|  |             defaults={ | ||||||
|  |                 "signing_key": data.validated_data["device_signing_key"], | ||||||
|  |                 "encryption_key": data.validated_data["device_encryption_key"], | ||||||
|  |                 "sign_key_id": data.validated_data["sign_key_id"], | ||||||
|  |                 "enc_key_id": data.validated_data["enc_key_id"], | ||||||
|  |                 "key_exchange_key": generate_key(), | ||||||
|  |                 "provider": provider, | ||||||
|  |             }, | ||||||
|  |         ) | ||||||
|  |         return Response() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class RegisterUserView(APIView): | ||||||
|  |  | ||||||
|  |     class UserRegistration(PassiveSerializer): | ||||||
|  |  | ||||||
|  |         device_uuid = CharField() | ||||||
|  |         user_secure_enclave_key = CharField() | ||||||
|  |         enclave_key_id = CharField() | ||||||
|  |  | ||||||
|  |     permission_classes = [] | ||||||
|  |     pagination_class = None | ||||||
|  |     filter_backends = [] | ||||||
|  |     serializer_class = UserRegistration | ||||||
|  |     authentication_classes = [TokenAuthentication] | ||||||
|  |  | ||||||
|  |     def post(self, request: Request) -> Response: | ||||||
|  |         data = self.UserRegistration(data=request.data) | ||||||
|  |         data.is_valid(raise_exception=True) | ||||||
|  |         device = get_object_or_404(AppleDevice, endpoint_uuid=data.validated_data["device_uuid"]) | ||||||
|  |         AppleDeviceUser.objects.update_or_create( | ||||||
|  |             device=device, | ||||||
|  |             user=request.user, | ||||||
|  |             defaults={ | ||||||
|  |                 "secure_enclave_key": data.validated_data["user_secure_enclave_key"], | ||||||
|  |                 "enclave_key_id": data.validated_data["enclave_key_id"], | ||||||
|  |             }, | ||||||
|  |         ) | ||||||
|  |         return Response( | ||||||
|  |             { | ||||||
|  |                 "username": request.user.username, | ||||||
|  |             } | ||||||
|  |         ) | ||||||
| @ -0,0 +1,16 @@ | |||||||
|  | from django.http import HttpRequest, HttpResponse, JsonResponse | ||||||
|  | from django.views import View | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AppleAppSiteAssociation(View): | ||||||
|  |     def get(self, request: HttpRequest) -> HttpResponse: | ||||||
|  |         return JsonResponse( | ||||||
|  |             { | ||||||
|  |                 "authsrv": { | ||||||
|  |                     "apps": [ | ||||||
|  |                         "232G855Y8N.io.goauthentik.endpoint", | ||||||
|  |                         "232G855Y8N.io.goauthentik.endpoint.psso", | ||||||
|  |                     ] | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         ) | ||||||
							
								
								
									
										140
									
								
								authentik/enterprise/providers/apple_psso/views/token.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								authentik/enterprise/providers/apple_psso/views/token.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,140 @@ | |||||||
|  | from datetime import timedelta | ||||||
|  |  | ||||||
|  | from django.http import Http404, HttpRequest, HttpResponse | ||||||
|  | from django.utils.decorators import method_decorator | ||||||
|  | from django.utils.timezone import now | ||||||
|  | from django.views import View | ||||||
|  | from django.views.decorators.csrf import csrf_exempt | ||||||
|  | from jwt import PyJWT, decode | ||||||
|  | from rest_framework.exceptions import ValidationError | ||||||
|  | from structlog.stdlib import get_logger | ||||||
|  |  | ||||||
|  | from authentik.core.models import AuthenticatedSession, Session, User | ||||||
|  | from authentik.core.sessions import SessionStore | ||||||
|  | from authentik.enterprise.providers.apple_psso.http import JWEResponse | ||||||
|  | from authentik.enterprise.providers.apple_psso.models import ( | ||||||
|  |     AppleDevice, | ||||||
|  |     AppleDeviceUser, | ||||||
|  |     AppleNonce, | ||||||
|  |     ApplePlatformSSOProvider, | ||||||
|  | ) | ||||||
|  | from authentik.events.models import Event, EventAction | ||||||
|  | from authentik.events.signals import SESSION_LOGIN_EVENT | ||||||
|  | from authentik.providers.oauth2.constants import TOKEN_TYPE | ||||||
|  | from authentik.providers.oauth2.id_token import IDToken | ||||||
|  | from authentik.providers.oauth2.models import RefreshToken | ||||||
|  | from authentik.root.middleware import SessionMiddleware | ||||||
|  |  | ||||||
|  | LOGGER = get_logger() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @method_decorator(csrf_exempt, name="dispatch") | ||||||
|  | class TokenView(View): | ||||||
|  |  | ||||||
|  |     device: AppleDevice | ||||||
|  |     provider: ApplePlatformSSOProvider | ||||||
|  |  | ||||||
|  |     def post(self, request: HttpRequest) -> HttpResponse: | ||||||
|  |         version = request.POST.get("platform_sso_version") | ||||||
|  |         assertion = request.POST.get("assertion", request.POST.get("request")) | ||||||
|  |         if not assertion: | ||||||
|  |             return HttpResponse(status=400) | ||||||
|  |  | ||||||
|  |         decode_unvalidated = PyJWT().decode_complete(assertion, options={"verify_signature": False}) | ||||||
|  |         LOGGER.debug(decode_unvalidated["header"]) | ||||||
|  |         expected_kid = decode_unvalidated["header"]["kid"] | ||||||
|  |  | ||||||
|  |         self.device = AppleDevice.objects.filter(sign_key_id=expected_kid).first() | ||||||
|  |         if not self.device: | ||||||
|  |             raise Http404 | ||||||
|  |         self.provider = self.device.provider | ||||||
|  |  | ||||||
|  |         # Properly decode the JWT with the key from the device | ||||||
|  |         decoded = decode( | ||||||
|  |             assertion, self.device.signing_key, algorithms=["ES256"], options={"verify_aud": False} | ||||||
|  |         ) | ||||||
|  |         LOGGER.debug(decoded) | ||||||
|  |  | ||||||
|  |         LOGGER.debug("got device", device=self.device) | ||||||
|  |  | ||||||
|  |         # Check that the nonce hasn't been used before | ||||||
|  |         nonce = AppleNonce.objects.filter(nonce=decoded["request_nonce"]).first() | ||||||
|  |         if not nonce: | ||||||
|  |             return HttpResponse(status=400) | ||||||
|  |         nonce.delete() | ||||||
|  |  | ||||||
|  |         handler_func = ( | ||||||
|  |             f"handle_v{version}_{decode_unvalidated["header"]["typ"]}".replace("-", "_") | ||||||
|  |             .replace("+", "_") | ||||||
|  |             .replace(".", "_") | ||||||
|  |         ) | ||||||
|  |         handler = getattr(self, handler_func, None) | ||||||
|  |         if not handler: | ||||||
|  |             LOGGER.debug("Handler not found", handler=handler_func) | ||||||
|  |             return HttpResponse(status=400) | ||||||
|  |         LOGGER.debug("sending to handler", handler=handler_func) | ||||||
|  |         return handler(decoded) | ||||||
|  |  | ||||||
|  |     def validate_device_user_response(self, assertion: str) -> tuple[AppleDeviceUser, dict] | None: | ||||||
|  |         """Decode an embedded assertion and validate it by looking up the matching device user""" | ||||||
|  |         decode_unvalidated = PyJWT().decode_complete(assertion, options={"verify_signature": False}) | ||||||
|  |         expected_kid = decode_unvalidated["header"]["kid"] | ||||||
|  |  | ||||||
|  |         device_user = AppleDeviceUser.objects.filter( | ||||||
|  |             device=self.device, enclave_key_id=expected_kid | ||||||
|  |         ).first() | ||||||
|  |         if not device_user: | ||||||
|  |             return None | ||||||
|  |         return device_user, decode( | ||||||
|  |             assertion, | ||||||
|  |             device_user.secure_enclave_key, | ||||||
|  |             audience="apple-platform-sso", | ||||||
|  |             algorithms=["ES256"], | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def create_auth_session(self, user: User): | ||||||
|  |         event = Event.new(EventAction.LOGIN).from_http(self.request, user=user) | ||||||
|  |         store = SessionStore() | ||||||
|  |         store[SESSION_LOGIN_EVENT] = event | ||||||
|  |         store.save() | ||||||
|  |         session = Session.objects.filter(session_key=store.session_key).first() | ||||||
|  |         AuthenticatedSession.objects.create(session=session, user=user) | ||||||
|  |         session = SessionMiddleware.encode_session(store.session_key, user) | ||||||
|  |         return session | ||||||
|  |  | ||||||
|  |     def handle_v1_0_platformsso_login_request_jwt(self, decoded: dict): | ||||||
|  |         user = None | ||||||
|  |         if decoded["grant_type"] == "urn:ietf:params:oauth:grant-type:jwt-bearer": | ||||||
|  |             # Decode and validate inner assertion | ||||||
|  |             user, inner = self.validate_device_user_response(decoded["assertion"]) | ||||||
|  |             if inner["nonce"] != decoded["nonce"]: | ||||||
|  |                 LOGGER.warning("Mis-matched nonce to outer assertion") | ||||||
|  |                 raise ValidationError("Invalid request") | ||||||
|  |  | ||||||
|  |         refresh_token = RefreshToken( | ||||||
|  |             user=user.user, | ||||||
|  |             scope=decoded["scope"], | ||||||
|  |             expires=now() + timedelta(hours=8), | ||||||
|  |             provider=self.provider, | ||||||
|  |             auth_time=now(), | ||||||
|  |             session=None, | ||||||
|  |         ) | ||||||
|  |         id_token = IDToken.new( | ||||||
|  |             self.provider, | ||||||
|  |             refresh_token, | ||||||
|  |             self.request, | ||||||
|  |         ) | ||||||
|  |         id_token.nonce = decoded["nonce"] | ||||||
|  |         refresh_token.id_token = id_token | ||||||
|  |         refresh_token.save() | ||||||
|  |         return JWEResponse( | ||||||
|  |             { | ||||||
|  |                 "refresh_token": refresh_token.token, | ||||||
|  |                 "refresh_token_expires_in": int((refresh_token.expires - now()).total_seconds()), | ||||||
|  |                 "id_token": refresh_token.id_token.to_jwt(self.provider), | ||||||
|  |                 "token_type": TOKEN_TYPE, | ||||||
|  |                 "session_key": self.create_auth_session(user.user), | ||||||
|  |             }, | ||||||
|  |             device=self.device, | ||||||
|  |             apv=decoded["jwe_crypto"]["apv"], | ||||||
|  |         ) | ||||||
| @ -15,6 +15,7 @@ CELERY_BEAT_SCHEDULE = { | |||||||
| TENANT_APPS = [ | TENANT_APPS = [ | ||||||
|     "authentik.enterprise.audit", |     "authentik.enterprise.audit", | ||||||
|     "authentik.enterprise.policies.unique_password", |     "authentik.enterprise.policies.unique_password", | ||||||
|  |     "authentik.enterprise.providers.apple_psso", | ||||||
|     "authentik.enterprise.providers.google_workspace", |     "authentik.enterprise.providers.google_workspace", | ||||||
|     "authentik.enterprise.providers.microsoft_entra", |     "authentik.enterprise.providers.microsoft_entra", | ||||||
|     "authentik.enterprise.providers.ssf", |     "authentik.enterprise.providers.ssf", | ||||||
|  | |||||||
| @ -555,6 +555,8 @@ class TokenView(View): | |||||||
|  |  | ||||||
|     provider: OAuth2Provider | None = None |     provider: OAuth2Provider | None = None | ||||||
|     params: TokenParams | None = None |     params: TokenParams | None = None | ||||||
|  |     params_class = TokenParams | ||||||
|  |     provider_class = OAuth2Provider | ||||||
|  |  | ||||||
|     def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: |     def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: | ||||||
|         response = super().dispatch(request, *args, **kwargs) |         response = super().dispatch(request, *args, **kwargs) | ||||||
| @ -574,12 +576,14 @@ class TokenView(View): | |||||||
|                 op="authentik.providers.oauth2.post.parse", |                 op="authentik.providers.oauth2.post.parse", | ||||||
|             ): |             ): | ||||||
|                 client_id, client_secret = extract_client_auth(request) |                 client_id, client_secret = extract_client_auth(request) | ||||||
|                 self.provider = OAuth2Provider.objects.filter(client_id=client_id).first() |                 self.provider = self.provider_class.objects.filter(client_id=client_id).first() | ||||||
|                 if not self.provider: |                 if not self.provider: | ||||||
|                     LOGGER.warning("OAuth2Provider does not exist", client_id=client_id) |                     LOGGER.warning("OAuth2Provider does not exist", client_id=client_id) | ||||||
|                     raise TokenError("invalid_client") |                     raise TokenError("invalid_client") | ||||||
|                 CTX_AUTH_VIA.set("oauth_client_secret") |                 CTX_AUTH_VIA.set("oauth_client_secret") | ||||||
|                 self.params = TokenParams.parse(request, self.provider, client_id, client_secret) |                 self.params = self.params_class.parse( | ||||||
|  |                     request, self.provider, client_id, client_secret | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|             with start_span( |             with start_span( | ||||||
|                 op="authentik.providers.oauth2.post.response", |                 op="authentik.providers.oauth2.post.response", | ||||||
|  | |||||||
| @ -66,7 +66,10 @@ class RACClientConsumer(AsyncWebsocketConsumer): | |||||||
|     def init_outpost_connection(self): |     def init_outpost_connection(self): | ||||||
|         """Initialize guac connection settings""" |         """Initialize guac connection settings""" | ||||||
|         self.token = ( |         self.token = ( | ||||||
|             ConnectionToken.filter_not_expired(token=self.scope["url_route"]["kwargs"]["token"]) |             ConnectionToken.filter_not_expired( | ||||||
|  |                 token=self.scope["url_route"]["kwargs"]["token"], | ||||||
|  |                 session__session__session_key=self.scope["session"].session_key, | ||||||
|  |             ) | ||||||
|             .select_related("endpoint", "provider", "session", "session__user") |             .select_related("endpoint", "provider", "session", "session__user") | ||||||
|             .first() |             .first() | ||||||
|         ) |         ) | ||||||
|  | |||||||
| @ -87,3 +87,22 @@ class TestRACViews(APITestCase): | |||||||
|         ) |         ) | ||||||
|         body = loads(flow_response.content) |         body = loads(flow_response.content) | ||||||
|         self.assertEqual(body["component"], "ak-stage-access-denied") |         self.assertEqual(body["component"], "ak-stage-access-denied") | ||||||
|  |  | ||||||
|  |     def test_different_session(self): | ||||||
|  |         """Test request""" | ||||||
|  |         self.client.force_login(self.user) | ||||||
|  |         response = self.client.get( | ||||||
|  |             reverse( | ||||||
|  |                 "authentik_providers_rac:start", | ||||||
|  |                 kwargs={"app": self.app.slug, "endpoint": str(self.endpoint.pk)}, | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(response.status_code, 302) | ||||||
|  |         flow_response = self.client.get( | ||||||
|  |             reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) | ||||||
|  |         ) | ||||||
|  |         body = loads(flow_response.content) | ||||||
|  |         next_url = body["to"] | ||||||
|  |         self.client.logout() | ||||||
|  |         final_response = self.client.get(next_url) | ||||||
|  |         self.assertEqual(final_response.url, reverse("authentik_core:if-user")) | ||||||
|  | |||||||
| @ -68,7 +68,10 @@ class RACInterface(InterfaceView): | |||||||
|  |  | ||||||
|     def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: |     def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: | ||||||
|         # Early sanity check to ensure token still exists |         # Early sanity check to ensure token still exists | ||||||
|         token = ConnectionToken.filter_not_expired(token=self.kwargs["token"]).first() |         token = ConnectionToken.filter_not_expired( | ||||||
|  |             token=self.kwargs["token"], | ||||||
|  |             session__session__session_key=request.session.session_key, | ||||||
|  |         ).first() | ||||||
|         if not token: |         if not token: | ||||||
|             return redirect("authentik_core:if-user") |             return redirect("authentik_core:if-user") | ||||||
|         self.token = token |         self.token = token | ||||||
|  | |||||||
| @ -61,6 +61,22 @@ class SessionMiddleware(UpstreamSessionMiddleware): | |||||||
|             pass |             pass | ||||||
|         return session_key |         return session_key | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def encode_session(session_key: str, user: User): | ||||||
|  |         payload = { | ||||||
|  |             "sid": session_key, | ||||||
|  |             "iss": "authentik", | ||||||
|  |             "sub": "anonymous", | ||||||
|  |             "authenticated": user.is_authenticated, | ||||||
|  |             "acr": ACR_AUTHENTIK_SESSION, | ||||||
|  |         } | ||||||
|  |         if user.is_authenticated: | ||||||
|  |             payload["sub"] = user.uid | ||||||
|  |         value = encode(payload=payload, key=SIGNING_HASH) | ||||||
|  |         if settings.TEST: | ||||||
|  |             value = session_key | ||||||
|  |         return value | ||||||
|  |  | ||||||
|     def process_request(self, request: HttpRequest): |     def process_request(self, request: HttpRequest): | ||||||
|         raw_session = request.COOKIES.get(settings.SESSION_COOKIE_NAME) |         raw_session = request.COOKIES.get(settings.SESSION_COOKIE_NAME) | ||||||
|         session_key = SessionMiddleware.decode_session_key(raw_session) |         session_key = SessionMiddleware.decode_session_key(raw_session) | ||||||
| @ -117,21 +133,9 @@ class SessionMiddleware(UpstreamSessionMiddleware): | |||||||
|                             "request completed. The user may have logged " |                             "request completed. The user may have logged " | ||||||
|                             "out in a concurrent request, for example." |                             "out in a concurrent request, for example." | ||||||
|                         ) from None |                         ) from None | ||||||
|                     payload = { |  | ||||||
|                         "sid": request.session.session_key, |  | ||||||
|                         "iss": "authentik", |  | ||||||
|                         "sub": "anonymous", |  | ||||||
|                         "authenticated": request.user.is_authenticated, |  | ||||||
|                         "acr": ACR_AUTHENTIK_SESSION, |  | ||||||
|                     } |  | ||||||
|                     if request.user.is_authenticated: |  | ||||||
|                         payload["sub"] = request.user.uid |  | ||||||
|                     value = encode(payload=payload, key=SIGNING_HASH) |  | ||||||
|                     if settings.TEST: |  | ||||||
|                         value = request.session.session_key |  | ||||||
|                     response.set_cookie( |                     response.set_cookie( | ||||||
|                         settings.SESSION_COOKIE_NAME, |                         settings.SESSION_COOKIE_NAME, | ||||||
|                         value, |                         SessionMiddleware.encode_session(request.session.session_key, request.user), | ||||||
|                         max_age=max_age, |                         max_age=max_age, | ||||||
|                         expires=expires, |                         expires=expires, | ||||||
|                         domain=settings.SESSION_COOKIE_DOMAIN, |                         domain=settings.SESSION_COOKIE_DOMAIN, | ||||||
|  | |||||||
| @ -27,7 +27,6 @@ | |||||||
|     </table> |     </table> | ||||||
|   </td> |   </td> | ||||||
| </tr> | </tr> | ||||||
| <td> |  | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  |  | ||||||
| {% block sub_content %} | {% block sub_content %} | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
|     "$schema": "http://json-schema.org/draft-07/schema", |     "$schema": "http://json-schema.org/draft-07/schema", | ||||||
|     "$id": "https://goauthentik.io/blueprints/schema.json", |     "$id": "https://goauthentik.io/blueprints/schema.json", | ||||||
|     "type": "object", |     "type": "object", | ||||||
|     "title": "authentik 2025.6.2 Blueprint schema", |     "title": "authentik 2025.6.3 Blueprint schema", | ||||||
|     "required": [ |     "required": [ | ||||||
|         "version", |         "version", | ||||||
|         "entries" |         "entries" | ||||||
| @ -496,6 +496,46 @@ | |||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 }, |                 }, | ||||||
|  |                 { | ||||||
|  |                     "type": "object", | ||||||
|  |                     "required": [ | ||||||
|  |                         "model", | ||||||
|  |                         "identifiers" | ||||||
|  |                     ], | ||||||
|  |                     "properties": { | ||||||
|  |                         "model": { | ||||||
|  |                             "const": "authentik_providers_apple_psso.appleplatformssoprovider" | ||||||
|  |                         }, | ||||||
|  |                         "id": { | ||||||
|  |                             "type": "string" | ||||||
|  |                         }, | ||||||
|  |                         "state": { | ||||||
|  |                             "type": "string", | ||||||
|  |                             "enum": [ | ||||||
|  |                                 "absent", | ||||||
|  |                                 "created", | ||||||
|  |                                 "must_created", | ||||||
|  |                                 "present" | ||||||
|  |                             ], | ||||||
|  |                             "default": "present" | ||||||
|  |                         }, | ||||||
|  |                         "conditions": { | ||||||
|  |                             "type": "array", | ||||||
|  |                             "items": { | ||||||
|  |                                 "type": "boolean" | ||||||
|  |                             } | ||||||
|  |                         }, | ||||||
|  |                         "permissions": { | ||||||
|  |                             "$ref": "#/$defs/model_authentik_providers_apple_psso.appleplatformssoprovider_permissions" | ||||||
|  |                         }, | ||||||
|  |                         "attrs": { | ||||||
|  |                             "$ref": "#/$defs/model_authentik_providers_apple_psso.appleplatformssoprovider" | ||||||
|  |                         }, | ||||||
|  |                         "identifiers": { | ||||||
|  |                             "$ref": "#/$defs/model_authentik_providers_apple_psso.appleplatformssoprovider" | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|                 { |                 { | ||||||
|                     "type": "object", |                     "type": "object", | ||||||
|                     "required": [ |                     "required": [ | ||||||
| @ -5028,6 +5068,22 @@ | |||||||
|                             "authentik_policies_unique_password.delete_userpasswordhistory", |                             "authentik_policies_unique_password.delete_userpasswordhistory", | ||||||
|                             "authentik_policies_unique_password.view_uniquepasswordpolicy", |                             "authentik_policies_unique_password.view_uniquepasswordpolicy", | ||||||
|                             "authentik_policies_unique_password.view_userpasswordhistory", |                             "authentik_policies_unique_password.view_userpasswordhistory", | ||||||
|  |                             "authentik_providers_apple_psso.add_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.add_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.add_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.add_appleplatformssoprovider", | ||||||
|  |                             "authentik_providers_apple_psso.change_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.change_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.change_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.change_appleplatformssoprovider", | ||||||
|  |                             "authentik_providers_apple_psso.delete_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.delete_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.delete_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.delete_appleplatformssoprovider", | ||||||
|  |                             "authentik_providers_apple_psso.view_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.view_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.view_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.view_appleplatformssoprovider", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovider", |                             "authentik_providers_google_workspace.add_googleworkspaceprovider", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", | ||||||
| @ -5599,6 +5655,43 @@ | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  |         "model_authentik_providers_apple_psso.appleplatformssoprovider": { | ||||||
|  |             "type": "object", | ||||||
|  |             "properties": { | ||||||
|  |                 "name": { | ||||||
|  |                     "type": "string", | ||||||
|  |                     "minLength": 1, | ||||||
|  |                     "title": "Name" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "required": [] | ||||||
|  |         }, | ||||||
|  |         "model_authentik_providers_apple_psso.appleplatformssoprovider_permissions": { | ||||||
|  |             "type": "array", | ||||||
|  |             "items": { | ||||||
|  |                 "type": "object", | ||||||
|  |                 "required": [ | ||||||
|  |                     "permission" | ||||||
|  |                 ], | ||||||
|  |                 "properties": { | ||||||
|  |                     "permission": { | ||||||
|  |                         "type": "string", | ||||||
|  |                         "enum": [ | ||||||
|  |                             "add_appleplatformssoprovider", | ||||||
|  |                             "change_appleplatformssoprovider", | ||||||
|  |                             "delete_appleplatformssoprovider", | ||||||
|  |                             "view_appleplatformssoprovider" | ||||||
|  |                         ] | ||||||
|  |                     }, | ||||||
|  |                     "user": { | ||||||
|  |                         "type": "integer" | ||||||
|  |                     }, | ||||||
|  |                     "role": { | ||||||
|  |                         "type": "string" | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|         "model_authentik_providers_google_workspace.googleworkspaceprovider": { |         "model_authentik_providers_google_workspace.googleworkspaceprovider": { | ||||||
|             "type": "object", |             "type": "object", | ||||||
|             "properties": { |             "properties": { | ||||||
| @ -7342,6 +7435,7 @@ | |||||||
|                         "authentik.enterprise", |                         "authentik.enterprise", | ||||||
|                         "authentik.enterprise.audit", |                         "authentik.enterprise.audit", | ||||||
|                         "authentik.enterprise.policies.unique_password", |                         "authentik.enterprise.policies.unique_password", | ||||||
|  |                         "authentik.enterprise.providers.apple_psso", | ||||||
|                         "authentik.enterprise.providers.google_workspace", |                         "authentik.enterprise.providers.google_workspace", | ||||||
|                         "authentik.enterprise.providers.microsoft_entra", |                         "authentik.enterprise.providers.microsoft_entra", | ||||||
|                         "authentik.enterprise.providers.ssf", |                         "authentik.enterprise.providers.ssf", | ||||||
| @ -7452,6 +7546,7 @@ | |||||||
|                         "authentik_core.token", |                         "authentik_core.token", | ||||||
|                         "authentik_enterprise.license", |                         "authentik_enterprise.license", | ||||||
|                         "authentik_policies_unique_password.uniquepasswordpolicy", |                         "authentik_policies_unique_password.uniquepasswordpolicy", | ||||||
|  |                         "authentik_providers_apple_psso.appleplatformssoprovider", | ||||||
|                         "authentik_providers_google_workspace.googleworkspaceprovider", |                         "authentik_providers_google_workspace.googleworkspaceprovider", | ||||||
|                         "authentik_providers_google_workspace.googleworkspaceprovidermapping", |                         "authentik_providers_google_workspace.googleworkspaceprovidermapping", | ||||||
|                         "authentik_providers_microsoft_entra.microsoftentraprovider", |                         "authentik_providers_microsoft_entra.microsoftentraprovider", | ||||||
| @ -9674,6 +9769,22 @@ | |||||||
|                             "authentik_policies_unique_password.delete_userpasswordhistory", |                             "authentik_policies_unique_password.delete_userpasswordhistory", | ||||||
|                             "authentik_policies_unique_password.view_uniquepasswordpolicy", |                             "authentik_policies_unique_password.view_uniquepasswordpolicy", | ||||||
|                             "authentik_policies_unique_password.view_userpasswordhistory", |                             "authentik_policies_unique_password.view_userpasswordhistory", | ||||||
|  |                             "authentik_providers_apple_psso.add_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.add_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.add_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.add_appleplatformssoprovider", | ||||||
|  |                             "authentik_providers_apple_psso.change_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.change_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.change_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.change_appleplatformssoprovider", | ||||||
|  |                             "authentik_providers_apple_psso.delete_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.delete_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.delete_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.delete_appleplatformssoprovider", | ||||||
|  |                             "authentik_providers_apple_psso.view_appledevice", | ||||||
|  |                             "authentik_providers_apple_psso.view_appledeviceuser", | ||||||
|  |                             "authentik_providers_apple_psso.view_applenonce", | ||||||
|  |                             "authentik_providers_apple_psso.view_appleplatformssoprovider", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovider", |                             "authentik_providers_google_workspace.add_googleworkspaceprovider", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ services: | |||||||
|     volumes: |     volumes: | ||||||
|       - redis:/data |       - redis:/data | ||||||
|   server: |   server: | ||||||
|     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.3} | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     command: server |     command: server | ||||||
|     environment: |     environment: | ||||||
| @ -55,7 +55,7 @@ services: | |||||||
|       redis: |       redis: | ||||||
|         condition: service_healthy |         condition: service_healthy | ||||||
|   worker: |   worker: | ||||||
|     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.2} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.3} | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     command: worker |     command: worker | ||||||
|     environment: |     environment: | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @ -29,7 +29,7 @@ require ( | |||||||
| 	github.com/spf13/cobra v1.9.1 | 	github.com/spf13/cobra v1.9.1 | ||||||
| 	github.com/stretchr/testify v1.10.0 | 	github.com/stretchr/testify v1.10.0 | ||||||
| 	github.com/wwt/guac v1.3.2 | 	github.com/wwt/guac v1.3.2 | ||||||
| 	goauthentik.io/api/v3 v3.2025062.5 | 	goauthentik.io/api/v3 v3.2025063.1 | ||||||
| 	golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab | 	golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab | ||||||
| 	golang.org/x/oauth2 v0.30.0 | 	golang.org/x/oauth2 v0.30.0 | ||||||
| 	golang.org/x/sync v0.15.0 | 	golang.org/x/sync v0.15.0 | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @ -298,8 +298,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.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 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= | ||||||
| go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= | ||||||
| goauthentik.io/api/v3 v3.2025062.5 h1:+eQe3S+9WxrO0QczbSQUhtfnCB1w2rse5wmgMkcRUio= | goauthentik.io/api/v3 v3.2025063.1 h1:zvKhZTESgMY/SNiLuTs7G0YleBnev1v7+S9Xd6PZ9bc= | ||||||
| goauthentik.io/api/v3 v3.2025062.5/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= | goauthentik.io/api/v3 v3.2025063.1/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-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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||||
| golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||||
|  | |||||||
| @ -33,4 +33,4 @@ func UserAgent() string { | |||||||
| 	return fmt.Sprintf("authentik@%s", FullVersion()) | 	return fmt.Sprintf("authentik@%s", FullVersion()) | ||||||
| } | } | ||||||
|  |  | ||||||
| const VERSION = "2025.6.2" | const VERSION = "2025.6.3" | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								lifecycle/aws/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								lifecycle/aws/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -9,7 +9,7 @@ | |||||||
|             "version": "0.0.0", |             "version": "0.0.0", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "devDependencies": { |             "devDependencies": { | ||||||
|                 "aws-cdk": "^2.1019.1", |                 "aws-cdk": "^2.1019.2", | ||||||
|                 "cross-env": "^7.0.3" |                 "cross-env": "^7.0.3" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
| @ -17,9 +17,9 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/aws-cdk": { |         "node_modules/aws-cdk": { | ||||||
|             "version": "2.1019.1", |             "version": "2.1019.2", | ||||||
|             "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1019.1.tgz", |             "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1019.2.tgz", | ||||||
|             "integrity": "sha512-G2jxKuTsYTrYZX80CDApCrKcZ+AuFxxd+b0dkb0KEkfUsela7RqrDGLm5wOzSCIc3iH6GocR8JDVZuJ+0nNuKg==", |             "integrity": "sha512-LkWZ3IKBkfCPTCu60t4Wb9JMSkb+0Uzk+HIxZeW5sFohq8bxDGV0OP1hcqEC2+KbVYRn7q+YhMeSJ/FOQcgpiw==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "Apache-2.0", |             "license": "Apache-2.0", | ||||||
|             "bin": { |             "bin": { | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ | |||||||
|         "node": ">=20" |         "node": ">=20" | ||||||
|     }, |     }, | ||||||
|     "devDependencies": { |     "devDependencies": { | ||||||
|         "aws-cdk": "^2.1019.1", |         "aws-cdk": "^2.1019.2", | ||||||
|         "cross-env": "^7.0.3" |         "cross-env": "^7.0.3" | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -26,7 +26,7 @@ Parameters: | |||||||
|     Description: authentik Docker image |     Description: authentik Docker image | ||||||
|   AuthentikVersion: |   AuthentikVersion: | ||||||
|     Type: String |     Type: String | ||||||
|     Default: 2025.6.2 |     Default: 2025.6.3 | ||||||
|     Description: authentik Docker image tag |     Description: authentik Docker image tag | ||||||
|   AuthentikServerCPU: |   AuthentikServerCPU: | ||||||
|     Type: Number |     Type: Number | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -11,18 +11,18 @@ | |||||||
| # Nicola Mersi, 2024 | # Nicola Mersi, 2024 | ||||||
| # tmassimi, 2024 | # tmassimi, 2024 | ||||||
| # Marc Schmitt, 2024 | # Marc Schmitt, 2024 | ||||||
| # albanobattistella <albanobattistella@gmail.com>, 2024 |  | ||||||
| # Matteo Piccina <altermatte@gmail.com>, 2025 | # Matteo Piccina <altermatte@gmail.com>, 2025 | ||||||
| # Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025 | # Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025 | ||||||
|  | # albanobattistella <albanobattistella@gmail.com>, 2025 | ||||||
| #  | #  | ||||||
| #, fuzzy | #, fuzzy | ||||||
| msgid "" | msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2025-05-28 11:25+0000\n" | "POT-Creation-Date: 2025-06-25 00:10+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n" | "Last-Translator: albanobattistella <albanobattistella@gmail.com>, 2025\n" | ||||||
| "Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n" | "Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n" | ||||||
| "MIME-Version: 1.0\n" | "MIME-Version: 1.0\n" | ||||||
| "Content-Type: text/plain; charset=UTF-8\n" | "Content-Type: text/plain; charset=UTF-8\n" | ||||||
| @ -116,7 +116,7 @@ msgstr "Certificato Web utilizzato dal server Web authentik Core." | |||||||
|  |  | ||||||
| #: authentik/brands/models.py | #: authentik/brands/models.py | ||||||
| msgid "Certificates used for client authentication." | msgid "Certificates used for client authentication." | ||||||
| msgstr "" | msgstr "Certificati utilizzati per l'autenticazione del client." | ||||||
|  |  | ||||||
| #: authentik/brands/models.py | #: authentik/brands/models.py | ||||||
| msgid "Brand" | msgid "Brand" | ||||||
| @ -130,10 +130,6 @@ msgstr "Brands" | |||||||
| msgid "User does not have access to application." | msgid "User does not have access to application." | ||||||
| msgstr "L'utente non ha accesso all'applicazione." | msgstr "L'utente non ha accesso all'applicazione." | ||||||
|  |  | ||||||
| #: authentik/core/api/devices.py |  | ||||||
| msgid "Extra description not available" |  | ||||||
| msgstr "Descrizione extra non disponibile" |  | ||||||
|  |  | ||||||
| #: authentik/core/api/groups.py | #: authentik/core/api/groups.py | ||||||
| msgid "Cannot set group as parent of itself." | msgid "Cannot set group as parent of itself." | ||||||
| msgstr "Impossibile impostare il gruppo come padre di se stesso." | msgstr "Impossibile impostare il gruppo come padre di se stesso." | ||||||
| @ -294,15 +290,15 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Collegamento a un utente con indirizzo email identico. Può avere " | "Collegamento a un utente con indirizzo email identico. Può avere " | ||||||
| "implicazioni sulla sicurezza quando una fonte non convalida gli indirizzi " | "implicazioni sulla sicurezza quando una fonte non convalida gli indirizzi " | ||||||
| "e-mail." | "email." | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "" | msgid "" | ||||||
| "Use the user's email address, but deny enrollment when the email address " | "Use the user's email address, but deny enrollment when the email address " | ||||||
| "already exists." | "already exists." | ||||||
| msgstr "" | msgstr "" | ||||||
| "Usa l'indirizzo e-mail dell'utente, ma nega l'iscrizione quando l'indirizzo " | "Usa l'indirizzo email dell'utente, ma nega l'iscrizione quando l'indirizzo " | ||||||
| "e-mail esiste già." | "email esiste già." | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "" | msgid "" | ||||||
| @ -682,26 +678,29 @@ msgid "" | |||||||
| "option has a higher priority than the `client_certificate` option on " | "option has a higher priority than the `client_certificate` option on " | ||||||
| "`Brand`." | "`Brand`." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | "Configura le autorità di certificazione per convalidare il certificato. " | ||||||
|  | "Questa opzione ha una priorità maggiore rispetto all'opzione " | ||||||
|  | "`client_certificate` su `Brand`." | ||||||
|  |  | ||||||
| #: authentik/enterprise/stages/mtls/models.py | #: authentik/enterprise/stages/mtls/models.py | ||||||
| msgid "Mutual TLS Stage" | msgid "Mutual TLS Stage" | ||||||
| msgstr "" | msgstr "Fase di TLS reciproca" | ||||||
|  |  | ||||||
| #: authentik/enterprise/stages/mtls/models.py | #: authentik/enterprise/stages/mtls/models.py | ||||||
| msgid "Mutual TLS Stages" | msgid "Mutual TLS Stages" | ||||||
| msgstr "" | msgstr "Fasi di TLS reciproche" | ||||||
|  |  | ||||||
| #: authentik/enterprise/stages/mtls/models.py | #: authentik/enterprise/stages/mtls/models.py | ||||||
| msgid "Permissions to pass Certificates for outposts." | msgid "Permissions to pass Certificates for outposts." | ||||||
| msgstr "" | msgstr " Permessi di trasmissione dei Certificati per gli avamposti." | ||||||
|  |  | ||||||
| #: authentik/enterprise/stages/mtls/stage.py | #: authentik/enterprise/stages/mtls/stage.py | ||||||
| msgid "Certificate required but no certificate was given." | msgid "Certificate required but no certificate was given." | ||||||
| msgstr "" | msgstr " Il certificato è stato richiesto ma non è stato consegnato." | ||||||
|  |  | ||||||
| #: authentik/enterprise/stages/mtls/stage.py | #: authentik/enterprise/stages/mtls/stage.py | ||||||
| msgid "No user found for certificate." | msgid "No user found for certificate." | ||||||
| msgstr "" | msgstr "Nessun utente trovato per il certificato." | ||||||
|  |  | ||||||
| #: authentik/enterprise/stages/source/models.py | #: authentik/enterprise/stages/source/models.py | ||||||
| msgid "" | msgid "" | ||||||
| @ -834,6 +833,14 @@ msgstr "" | |||||||
| "Definisci a quale gruppo di utenti deve essere inviata e mostrata questa " | "Definisci a quale gruppo di utenti deve essere inviata e mostrata questa " | ||||||
| "notifica. Se lasciato vuoto, la notifica non verrà inviata." | "notifica. Se lasciato vuoto, la notifica non verrà inviata." | ||||||
|  |  | ||||||
|  | #: authentik/events/models.py | ||||||
|  | msgid "" | ||||||
|  | "When enabled, notification will be sent to user the user that triggered the " | ||||||
|  | "event.When destination_group is configured, notification is sent to both." | ||||||
|  | msgstr "" | ||||||
|  | "Se abilitata, la notifica verrà inviata all'utente che ha attivato l'evento." | ||||||
|  | " Se destination_group è configurato, la notifica verrà inviata a entrambi." | ||||||
|  |  | ||||||
| #: authentik/events/models.py | #: authentik/events/models.py | ||||||
| msgid "Notification Rule" | msgid "Notification Rule" | ||||||
| msgstr "Regola di notifica" | msgstr "Regola di notifica" | ||||||
| @ -1050,16 +1057,16 @@ msgstr "Avvio della sincronizzazione completa del provider" | |||||||
|  |  | ||||||
| #: authentik/lib/sync/outgoing/tasks.py | #: authentik/lib/sync/outgoing/tasks.py | ||||||
| msgid "Syncing users" | msgid "Syncing users" | ||||||
| msgstr "" | msgstr "Sincronizzazione degli utenti" | ||||||
|  |  | ||||||
| #: authentik/lib/sync/outgoing/tasks.py | #: authentik/lib/sync/outgoing/tasks.py | ||||||
| msgid "Syncing groups" | msgid "Syncing groups" | ||||||
| msgstr "" | msgstr "Sincronizzazione dei gruppi" | ||||||
|  |  | ||||||
| #: authentik/lib/sync/outgoing/tasks.py | #: authentik/lib/sync/outgoing/tasks.py | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Syncing page {page} of groups" | msgid "Syncing page {page} of {object_type}" | ||||||
| msgstr "Sincronizzando pagina {page} dei gruppi" | msgstr "Sincronizzazione della pagina {page} di {object_type}" | ||||||
|  |  | ||||||
| #: authentik/lib/sync/outgoing/tasks.py | #: authentik/lib/sync/outgoing/tasks.py | ||||||
| msgid "Dropping mutating request due to dry run" | msgid "Dropping mutating request due to dry run" | ||||||
| @ -2461,6 +2468,10 @@ msgstr "Gruppo di aggiunta DN" | |||||||
| msgid "Consider Objects matching this filter to be Users." | msgid "Consider Objects matching this filter to be Users." | ||||||
| msgstr "Considerare gli oggetti corrispondenti a questo filtro come Utenti." | msgstr "Considerare gli oggetti corrispondenti a questo filtro come Utenti." | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Attribute which matches the value of `group_membership_field`." | ||||||
|  | msgstr "Attributo che corrisponde al valore di `group_membership_field`." | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/models.py | #: authentik/sources/ldap/models.py | ||||||
| msgid "Field which contains members of a group." | msgid "Field which contains members of a group." | ||||||
| msgstr "Campo che contiene i membri di un gruppo." | msgstr "Campo che contiene i membri di un gruppo." | ||||||
| @ -2502,6 +2513,8 @@ msgid "" | |||||||
| "Delete authentik users and groups which were previously supplied by this " | "Delete authentik users and groups which were previously supplied by this " | ||||||
| "source, but are now missing from it." | "source, but are now missing from it." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | "Elimina gli utenti e i gruppi authentik precedentemente forniti da questa " | ||||||
|  | "fonte, ma che ora mancano." | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/models.py | #: authentik/sources/ldap/models.py | ||||||
| msgid "LDAP Source" | msgid "LDAP Source" | ||||||
| @ -2523,6 +2536,8 @@ msgstr "Mappature delle proprietà della sorgente LDAP" | |||||||
| msgid "" | msgid "" | ||||||
| "Unique ID used while checking if this object still exists in the directory." | "Unique ID used while checking if this object still exists in the directory." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | "ID univoco utilizzato per verificare se questo oggetto esiste ancora nella " | ||||||
|  | "directory." | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/models.py | #: authentik/sources/ldap/models.py | ||||||
| msgid "User LDAP Source Connection" | msgid "User LDAP Source Connection" | ||||||
| @ -2920,7 +2935,7 @@ msgstr "Connessioni sorgente SAML di gruppo" | |||||||
| #: authentik/sources/saml/views.py | #: authentik/sources/saml/views.py | ||||||
| #, python-brace-format | #, python-brace-format | ||||||
| msgid "Continue to {source_name}" | msgid "Continue to {source_name}" | ||||||
| msgstr "" | msgstr "Continua su {source_name}" | ||||||
|  |  | ||||||
| #: authentik/sources/scim/models.py | #: authentik/sources/scim/models.py | ||||||
| msgid "SCIM Source" | msgid "SCIM Source" | ||||||
| @ -2988,8 +3003,8 @@ msgstr "Fasi di configurazione dell'autenticatore email" | |||||||
| #: authentik/stages/email/stage.py | #: authentik/stages/email/stage.py | ||||||
| msgid "Exception occurred while rendering E-mail template" | msgid "Exception occurred while rendering E-mail template" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Eccezione verificatasi durante la visualizzazione del modello di posta " | "Si è verificata un'eccezione durante la visualizzazione del modello di posta" | ||||||
| "elettronica" | " elettronica" | ||||||
|  |  | ||||||
| #: authentik/stages/authenticator_email/models.py | #: authentik/stages/authenticator_email/models.py | ||||||
| msgid "Email Device" | msgid "Email Device" | ||||||
| @ -3028,7 +3043,7 @@ msgid "" | |||||||
| "          " | "          " | ||||||
| msgstr "" | msgstr "" | ||||||
| "\n" | "\n" | ||||||
| "          Codice MFA via e-mail.\n" | "          Codice MFA via email.\n" | ||||||
| "          " | "          " | ||||||
|  |  | ||||||
| #: authentik/stages/authenticator_email/templates/email/email_otp.html | #: authentik/stages/authenticator_email/templates/email/email_otp.html | ||||||
| @ -3054,7 +3069,7 @@ msgid "" | |||||||
| "Email MFA code\n" | "Email MFA code\n" | ||||||
| msgstr "" | msgstr "" | ||||||
| "\n" | "\n" | ||||||
| "Codice e-mail MFA\n" | "Codice email MFA\n" | ||||||
|  |  | ||||||
| #: authentik/stages/authenticator_email/templates/email/email_otp.txt | #: authentik/stages/authenticator_email/templates/email/email_otp.txt | ||||||
| #, python-format | #, python-format | ||||||
| @ -3321,7 +3336,7 @@ msgstr "Consensi utente" | |||||||
|  |  | ||||||
| #: authentik/stages/consent/stage.py | #: authentik/stages/consent/stage.py | ||||||
| msgid "Invalid consent token, re-showing prompt" | msgid "Invalid consent token, re-showing prompt" | ||||||
| msgstr "" | msgstr "Token di consenso non valido, viene nuovamente visualizzato il prompt" | ||||||
|  |  | ||||||
| #: authentik/stages/deny/models.py | #: authentik/stages/deny/models.py | ||||||
| msgid "Deny Stage" | msgid "Deny Stage" | ||||||
| @ -3341,11 +3356,11 @@ msgstr "Fasi fittizie" | |||||||
|  |  | ||||||
| #: authentik/stages/email/flow.py | #: authentik/stages/email/flow.py | ||||||
| msgid "Continue to confirm this email address." | msgid "Continue to confirm this email address." | ||||||
| msgstr "" | msgstr "Continua per confermare questo indirizzo email." | ||||||
|  |  | ||||||
| #: authentik/stages/email/flow.py | #: authentik/stages/email/flow.py | ||||||
| msgid "Link was already used, please request a new link." | msgid "Link was already used, please request a new link." | ||||||
| msgstr "" | msgstr "Il collegamento è già stato utilizzato. Richiedine uno nuovo." | ||||||
|  |  | ||||||
| #: authentik/stages/email/models.py | #: authentik/stages/email/models.py | ||||||
| msgid "Password Reset" | msgid "Password Reset" | ||||||
| @ -3365,7 +3380,7 @@ msgstr "Fase email" | |||||||
|  |  | ||||||
| #: authentik/stages/email/models.py | #: authentik/stages/email/models.py | ||||||
| msgid "Email Stages" | msgid "Email Stages" | ||||||
| msgstr "Fasi Email" | msgstr "Fasi email" | ||||||
|  |  | ||||||
| #: authentik/stages/email/stage.py | #: authentik/stages/email/stage.py | ||||||
| msgid "Successfully verified Email." | msgid "Successfully verified Email." | ||||||
| @ -3467,7 +3482,7 @@ msgid "" | |||||||
| "    " | "    " | ||||||
| msgstr "" | msgstr "" | ||||||
| "\n" | "\n" | ||||||
| "   Se non hai richiesto una modifica della password, ignora questa e-mail. Il link sopra è valido per %(expires)s.\n" | "   Se non hai richiesto una modifica della password, ignora questa email. Il link sopra è valido per %(expires)s.\n" | ||||||
| "    " | "    " | ||||||
|  |  | ||||||
| #: authentik/stages/email/templates/email/password_reset.txt | #: authentik/stages/email/templates/email/password_reset.txt | ||||||
| @ -3485,11 +3500,11 @@ msgid "" | |||||||
| "If you did not request a password change, please ignore this email. The link above is valid for %(expires)s.\n" | "If you did not request a password change, please ignore this email. The link above is valid for %(expires)s.\n" | ||||||
| msgstr "" | msgstr "" | ||||||
| "\n" | "\n" | ||||||
| "Se non hai richiesto una modifica della password, ignora questa e-mail. Il link sopra è valido per %(expires)s.\n" | "Se non hai richiesto una modifica della password, ignora questa email. Il link sopra è valido per %(expires)s.\n" | ||||||
|  |  | ||||||
| #: authentik/stages/email/templates/email/setup.html | #: authentik/stages/email/templates/email/setup.html | ||||||
| msgid "authentik Test-Email" | msgid "authentik Test-Email" | ||||||
| msgstr "e-mail di prova di authentik" | msgstr "email di prova di authentik" | ||||||
|  |  | ||||||
| #: authentik/stages/email/templates/email/setup.html | #: authentik/stages/email/templates/email/setup.html | ||||||
| msgid "" | msgid "" | ||||||
| @ -3498,7 +3513,7 @@ msgid "" | |||||||
| "                    " | "                    " | ||||||
| msgstr "" | msgstr "" | ||||||
| "\n" | "\n" | ||||||
| "                    Questa è un'e-mail di prova per informarti che hai configurato correttamente le e-mail di authentik.\n" | "                    Questa è un'email di prova per informarti che hai configurato correttamente le email di authentik.\n" | ||||||
| "                    " | "                    " | ||||||
|  |  | ||||||
| #: authentik/stages/email/templates/email/setup.txt | #: authentik/stages/email/templates/email/setup.txt | ||||||
| @ -3507,7 +3522,7 @@ msgid "" | |||||||
| "This is a test email to inform you, that you've successfully configured authentik emails.\n" | "This is a test email to inform you, that you've successfully configured authentik emails.\n" | ||||||
| msgstr "" | msgstr "" | ||||||
| "\n" | "\n" | ||||||
| "Questa è un'e-mail di prova per informarti che hai configurato correttamente le e-mail di authentik.\n" | "Questa è un'email di prova per informarti che hai configurato correttamente le email di authentik.\n" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/api.py | #: authentik/stages/identification/api.py | ||||||
| msgid "When no user fields are selected, at least one source must be selected" | msgid "When no user fields are selected, at least one source must be selected" | ||||||
| @ -3710,7 +3725,7 @@ msgstr "" | |||||||
|  |  | ||||||
| #: authentik/stages/prompt/models.py | #: authentik/stages/prompt/models.py | ||||||
| msgid "Email: Text field with Email type." | msgid "Email: Text field with Email type." | ||||||
| msgstr "E-mail: Campo di testo con il tipo di e-mail." | msgstr "Email: Campo di testo con il tipo di email." | ||||||
|  |  | ||||||
| #: authentik/stages/prompt/models.py | #: authentik/stages/prompt/models.py | ||||||
| msgid "" | msgid "" | ||||||
| @ -3865,10 +3880,6 @@ msgstr "Fasi di accesso utente" | |||||||
| msgid "No Pending user to login." | msgid "No Pending user to login." | ||||||
| msgstr "Nessun utente in attesa di accesso." | msgstr "Nessun utente in attesa di accesso." | ||||||
|  |  | ||||||
| #: authentik/stages/user_login/stage.py |  | ||||||
| msgid "Successfully logged in!" |  | ||||||
| msgstr "Accesso effettuato!" |  | ||||||
|  |  | ||||||
| #: authentik/stages/user_logout/models.py | #: authentik/stages/user_logout/models.py | ||||||
| msgid "User Logout Stage" | msgid "User Logout Stage" | ||||||
| msgstr "Fase di disconnessione dell'utente" | msgstr "Fase di disconnessione dell'utente" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -15,7 +15,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2025-06-04 00:12+0000\n" | "POT-Creation-Date: 2025-06-25 00:10+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: deluxghost, 2025\n" | "Last-Translator: deluxghost, 2025\n" | ||||||
| "Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n" | "Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n" | ||||||
| @ -118,10 +118,6 @@ msgstr "品牌" | |||||||
| msgid "User does not have access to application." | msgid "User does not have access to application." | ||||||
| msgstr "用户没有访问此应用程序的权限。" | msgstr "用户没有访问此应用程序的权限。" | ||||||
|  |  | ||||||
| #: authentik/core/api/devices.py |  | ||||||
| msgid "Extra description not available" |  | ||||||
| msgstr "额外描述不可用" |  | ||||||
|  |  | ||||||
| #: authentik/core/api/groups.py | #: authentik/core/api/groups.py | ||||||
| msgid "Cannot set group as parent of itself." | msgid "Cannot set group as parent of itself." | ||||||
| msgstr "无法设置组自身为父级。" | msgstr "无法设置组自身为父级。" | ||||||
| @ -775,6 +771,12 @@ msgid "" | |||||||
| "If left empty, Notification won't ben sent." | "If left empty, Notification won't ben sent." | ||||||
| msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。" | msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。" | ||||||
|  |  | ||||||
|  | #: authentik/events/models.py | ||||||
|  | msgid "" | ||||||
|  | "When enabled, notification will be sent to user the user that triggered the " | ||||||
|  | "event.When destination_group is configured, notification is sent to both." | ||||||
|  | msgstr "启用时,通知会被发送到触发事件的用户。当配置了 destination_group 时,通知也会同时发送到对应组。" | ||||||
|  |  | ||||||
| #: authentik/events/models.py | #: authentik/events/models.py | ||||||
| msgid "Notification Rule" | msgid "Notification Rule" | ||||||
| msgstr "通知规则" | msgstr "通知规则" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -14,7 +14,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2025-06-04 00:12+0000\n" | "POT-Creation-Date: 2025-06-25 00:10+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: deluxghost, 2025\n" | "Last-Translator: deluxghost, 2025\n" | ||||||
| "Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n" | "Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n" | ||||||
| @ -117,10 +117,6 @@ msgstr "品牌" | |||||||
| msgid "User does not have access to application." | msgid "User does not have access to application." | ||||||
| msgstr "用户没有访问此应用程序的权限。" | msgstr "用户没有访问此应用程序的权限。" | ||||||
|  |  | ||||||
| #: authentik/core/api/devices.py |  | ||||||
| msgid "Extra description not available" |  | ||||||
| msgstr "额外描述不可用" |  | ||||||
|  |  | ||||||
| #: authentik/core/api/groups.py | #: authentik/core/api/groups.py | ||||||
| msgid "Cannot set group as parent of itself." | msgid "Cannot set group as parent of itself." | ||||||
| msgstr "无法设置组自身为父级。" | msgstr "无法设置组自身为父级。" | ||||||
| @ -774,6 +770,12 @@ msgid "" | |||||||
| "If left empty, Notification won't ben sent." | "If left empty, Notification won't ben sent." | ||||||
| msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。" | msgstr "定义此通知应该发送到哪些用户组。如果留空,则不会发送通知。" | ||||||
|  |  | ||||||
|  | #: authentik/events/models.py | ||||||
|  | msgid "" | ||||||
|  | "When enabled, notification will be sent to user the user that triggered the " | ||||||
|  | "event.When destination_group is configured, notification is sent to both." | ||||||
|  | msgstr "启用时,通知会被发送到触发事件的用户。当配置了 destination_group 时,通知也会同时发送到对应组。" | ||||||
|  |  | ||||||
| #: authentik/events/models.py | #: authentik/events/models.py | ||||||
| msgid "Notification Rule" | msgid "Notification Rule" | ||||||
| msgstr "通知规则" | msgstr "通知规则" | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/authentik", |     "name": "@goauthentik/authentik", | ||||||
|     "version": "2025.6.2", |     "version": "2025.6.3", | ||||||
|     "lockfileVersion": 3, |     "lockfileVersion": 3, | ||||||
|     "requires": true, |     "requires": true, | ||||||
|     "packages": { |     "packages": { | ||||||
|         "": { |         "": { | ||||||
|             "name": "@goauthentik/authentik", |             "name": "@goauthentik/authentik", | ||||||
|             "version": "2025.6.2", |             "version": "2025.6.3", | ||||||
|             "devDependencies": { |             "devDependencies": { | ||||||
|                 "@trivago/prettier-plugin-sort-imports": "^5.2.2", |                 "@trivago/prettier-plugin-sort-imports": "^5.2.2", | ||||||
|                 "prettier": "^3.3.3", |                 "prettier": "^3.3.3", | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/authentik", |     "name": "@goauthentik/authentik", | ||||||
|     "version": "2025.6.2", |     "version": "2025.6.3", | ||||||
|     "private": true, |     "private": true, | ||||||
|     "type": "module", |     "type": "module", | ||||||
|     "devDependencies": { |     "devDependencies": { | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
| README.md | README.md | ||||||
| node_modules | node_modules | ||||||
| _media | _media | ||||||
|  | !.github/README.md | ||||||
| @ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/esbuild-plugin-live-reload", |     "name": "@goauthentik/esbuild-plugin-live-reload", | ||||||
|     "version": "1.0.5", |     "version": "1.0.6", | ||||||
|     "lockfileVersion": 3, |     "lockfileVersion": 3, | ||||||
|     "requires": true, |     "requires": true, | ||||||
|     "packages": { |     "packages": { | ||||||
|         "": { |         "": { | ||||||
|             "name": "@goauthentik/esbuild-plugin-live-reload", |             "name": "@goauthentik/esbuild-plugin-live-reload", | ||||||
|             "version": "1.0.5", |             "version": "1.0.6", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "find-free-ports": "^3.1.1" |                 "find-free-ports": "^3.1.1" | ||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/esbuild-plugin-live-reload", |     "name": "@goauthentik/esbuild-plugin-live-reload", | ||||||
|     "version": "1.0.5", |     "version": "1.0.6", | ||||||
|     "description": "ESBuild + browser refresh. Build completes, page reloads.", |     "description": "ESBuild + browser refresh. Build completes, page reloads.", | ||||||
|     "license": "MIT", |     "license": "MIT", | ||||||
|     "scripts": { |     "scripts": { | ||||||
| @ -1,6 +1,6 @@ | |||||||
| [project] | [project] | ||||||
| name = "authentik" | name = "authentik" | ||||||
| version = "2025.6.2" | version = "2025.6.3" | ||||||
| description = "" | description = "" | ||||||
| authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }] | authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }] | ||||||
| requires-python = "==3.13.*" | requires-python = "==3.13.*" | ||||||
| @ -17,10 +17,10 @@ dependencies = [ | |||||||
|     "django-countries==7.6.1", |     "django-countries==7.6.1", | ||||||
|     "django-cte==2.0.0", |     "django-cte==2.0.0", | ||||||
|     "django-filter==25.1", |     "django-filter==25.1", | ||||||
|     "django-guardian==3.0.0", |     "django-guardian==3.0.3", | ||||||
|     "django-model-utils==5.0.0", |     "django-model-utils==5.0.0", | ||||||
|     "django-pglock==1.7.2", |     "django-pglock==1.7.2", | ||||||
|     "django-prometheus==2.4.0", |     "django-prometheus==2.4.1", | ||||||
|     "django-redis==6.0.0", |     "django-redis==6.0.0", | ||||||
|     "django-storages[s3]==1.14.6", |     "django-storages[s3]==1.14.6", | ||||||
|     "django-tenants==3.8.0", |     "django-tenants==3.8.0", | ||||||
| @ -36,7 +36,7 @@ dependencies = [ | |||||||
|     "flower==2.0.1", |     "flower==2.0.1", | ||||||
|     "geoip2==5.1.0", |     "geoip2==5.1.0", | ||||||
|     "geopy==2.4.1", |     "geopy==2.4.1", | ||||||
|     "google-api-python-client==2.173.0", |     "google-api-python-client==2.174.0", | ||||||
|     "gssapi==1.9.0", |     "gssapi==1.9.0", | ||||||
|     "gunicorn==23.0.0", |     "gunicorn==23.0.0", | ||||||
|     "jsonpatch==1.33", |     "jsonpatch==1.33", | ||||||
| @ -44,7 +44,7 @@ dependencies = [ | |||||||
|     "kubernetes==33.1.0", |     "kubernetes==33.1.0", | ||||||
|     "ldap3==2.9.1", |     "ldap3==2.9.1", | ||||||
|     "lxml==5.4.0", |     "lxml==5.4.0", | ||||||
|     "msgraph-sdk==1.34.0", |     "msgraph-sdk==1.35.0", | ||||||
|     "opencontainers==0.0.14", |     "opencontainers==0.0.14", | ||||||
|     "packaging==25.0", |     "packaging==25.0", | ||||||
|     "paramiko==3.5.1", |     "paramiko==3.5.1", | ||||||
| @ -57,7 +57,7 @@ dependencies = [ | |||||||
|     "pyyaml==6.0.2", |     "pyyaml==6.0.2", | ||||||
|     "requests-oauthlib==2.0.0", |     "requests-oauthlib==2.0.0", | ||||||
|     "scim2-filter-parser==0.7.0", |     "scim2-filter-parser==0.7.0", | ||||||
|     "sentry-sdk==2.31.0", |     "sentry-sdk==2.32.0", | ||||||
|     "service-identity==24.2.0", |     "service-identity==24.2.0", | ||||||
|     "setproctitle==1.3.6", |     "setproctitle==1.3.6", | ||||||
|     "structlog==25.4.0", |     "structlog==25.4.0", | ||||||
| @ -67,7 +67,7 @@ dependencies = [ | |||||||
|     "ua-parser==1.0.1", |     "ua-parser==1.0.1", | ||||||
|     "unidecode==1.4.0", |     "unidecode==1.4.0", | ||||||
|     "urllib3<3", |     "urllib3<3", | ||||||
|     "uvicorn[standard]==0.34.3", |     "uvicorn[standard]==0.35.0", | ||||||
|     "watchdog==6.0.0", |     "watchdog==6.0.0", | ||||||
|     "webauthn==2.6.0", |     "webauthn==2.6.0", | ||||||
|     "wsproto==1.2.0", |     "wsproto==1.2.0", | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								schema.yml
									
									
									
									
									
								
							| @ -1,7 +1,7 @@ | |||||||
| openapi: 3.0.3 | openapi: 3.0.3 | ||||||
| info: | info: | ||||||
|   title: authentik |   title: authentik | ||||||
|   version: 2025.6.2 |   version: 2025.6.3 | ||||||
|   description: Making authentication simple. |   description: Making authentication simple. | ||||||
|   contact: |   contact: | ||||||
|     email: hello@goauthentik.io |     email: hello@goauthentik.io | ||||||
| @ -24864,6 +24864,7 @@ paths: | |||||||
|           - authentik_policies_password.passwordpolicy |           - authentik_policies_password.passwordpolicy | ||||||
|           - authentik_policies_reputation.reputationpolicy |           - authentik_policies_reputation.reputationpolicy | ||||||
|           - authentik_policies_unique_password.uniquepasswordpolicy |           - authentik_policies_unique_password.uniquepasswordpolicy | ||||||
|  |           - authentik_providers_apple_psso.appleplatformssoprovider | ||||||
|           - authentik_providers_google_workspace.googleworkspaceprovider |           - authentik_providers_google_workspace.googleworkspaceprovider | ||||||
|           - authentik_providers_google_workspace.googleworkspaceprovidermapping |           - authentik_providers_google_workspace.googleworkspaceprovidermapping | ||||||
|           - authentik_providers_ldap.ldapprovider |           - authentik_providers_ldap.ldapprovider | ||||||
| @ -25113,6 +25114,7 @@ paths: | |||||||
|           - authentik_policies_password.passwordpolicy |           - authentik_policies_password.passwordpolicy | ||||||
|           - authentik_policies_reputation.reputationpolicy |           - authentik_policies_reputation.reputationpolicy | ||||||
|           - authentik_policies_unique_password.uniquepasswordpolicy |           - authentik_policies_unique_password.uniquepasswordpolicy | ||||||
|  |           - authentik_providers_apple_psso.appleplatformssoprovider | ||||||
|           - authentik_providers_google_workspace.googleworkspaceprovider |           - authentik_providers_google_workspace.googleworkspaceprovider | ||||||
|           - authentik_providers_google_workspace.googleworkspaceprovidermapping |           - authentik_providers_google_workspace.googleworkspaceprovidermapping | ||||||
|           - authentik_providers_ldap.ldapprovider |           - authentik_providers_ldap.ldapprovider | ||||||
| @ -41212,6 +41214,7 @@ components: | |||||||
|       - authentik.enterprise |       - authentik.enterprise | ||||||
|       - authentik.enterprise.audit |       - authentik.enterprise.audit | ||||||
|       - authentik.enterprise.policies.unique_password |       - authentik.enterprise.policies.unique_password | ||||||
|  |       - authentik.enterprise.providers.apple_psso | ||||||
|       - authentik.enterprise.providers.google_workspace |       - authentik.enterprise.providers.google_workspace | ||||||
|       - authentik.enterprise.providers.microsoft_entra |       - authentik.enterprise.providers.microsoft_entra | ||||||
|       - authentik.enterprise.providers.ssf |       - authentik.enterprise.providers.ssf | ||||||
| @ -41258,6 +41261,15 @@ components: | |||||||
|       - redirect_uri |       - redirect_uri | ||||||
|       - scope |       - scope | ||||||
|       - state |       - state | ||||||
|  |     ApplePlatformSSOProviderRequest: | ||||||
|  |       type: object | ||||||
|  |       description: ApplePlatformSSOProvider Serializer | ||||||
|  |       properties: | ||||||
|  |         name: | ||||||
|  |           type: string | ||||||
|  |           minLength: 1 | ||||||
|  |       required: | ||||||
|  |       - name | ||||||
|     Application: |     Application: | ||||||
|       type: object |       type: object | ||||||
|       description: Application Serializer |       description: Application Serializer | ||||||
| @ -48714,6 +48726,7 @@ components: | |||||||
|       - authentik_core.token |       - authentik_core.token | ||||||
|       - authentik_enterprise.license |       - authentik_enterprise.license | ||||||
|       - authentik_policies_unique_password.uniquepasswordpolicy |       - authentik_policies_unique_password.uniquepasswordpolicy | ||||||
|  |       - authentik_providers_apple_psso.appleplatformssoprovider | ||||||
|       - authentik_providers_google_workspace.googleworkspaceprovider |       - authentik_providers_google_workspace.googleworkspaceprovider | ||||||
|       - authentik_providers_google_workspace.googleworkspaceprovidermapping |       - authentik_providers_google_workspace.googleworkspaceprovidermapping | ||||||
|       - authentik_providers_microsoft_entra.microsoftentraprovider |       - authentik_providers_microsoft_entra.microsoftentraprovider | ||||||
| @ -56659,6 +56672,7 @@ components: | |||||||
|       type: string |       type: string | ||||||
|     ProviderModelEnum: |     ProviderModelEnum: | ||||||
|       enum: |       enum: | ||||||
|  |       - authentik_providers_apple_psso.appleplatformssoprovider | ||||||
|       - authentik_providers_google_workspace.googleworkspaceprovider |       - authentik_providers_google_workspace.googleworkspaceprovider | ||||||
|       - authentik_providers_ldap.ldapprovider |       - authentik_providers_ldap.ldapprovider | ||||||
|       - authentik_providers_microsoft_entra.microsoftentraprovider |       - authentik_providers_microsoft_entra.microsoftentraprovider | ||||||
| @ -61871,6 +61885,7 @@ components: | |||||||
|       - worker_id |       - worker_id | ||||||
|     modelRequest: |     modelRequest: | ||||||
|       oneOf: |       oneOf: | ||||||
|  |       - $ref: '#/components/schemas/ApplePlatformSSOProviderRequest' | ||||||
|       - $ref: '#/components/schemas/GoogleWorkspaceProviderRequest' |       - $ref: '#/components/schemas/GoogleWorkspaceProviderRequest' | ||||||
|       - $ref: '#/components/schemas/LDAPProviderRequest' |       - $ref: '#/components/schemas/LDAPProviderRequest' | ||||||
|       - $ref: '#/components/schemas/MicrosoftEntraProviderRequest' |       - $ref: '#/components/schemas/MicrosoftEntraProviderRequest' | ||||||
| @ -61884,6 +61899,7 @@ components: | |||||||
|       discriminator: |       discriminator: | ||||||
|         propertyName: provider_model |         propertyName: provider_model | ||||||
|         mapping: |         mapping: | ||||||
|  |           authentik_providers_apple_psso.appleplatformssoprovider: '#/components/schemas/ApplePlatformSSOProviderRequest' | ||||||
|           authentik_providers_google_workspace.googleworkspaceprovider: '#/components/schemas/GoogleWorkspaceProviderRequest' |           authentik_providers_google_workspace.googleworkspaceprovider: '#/components/schemas/GoogleWorkspaceProviderRequest' | ||||||
|           authentik_providers_ldap.ldapprovider: '#/components/schemas/LDAPProviderRequest' |           authentik_providers_ldap.ldapprovider: '#/components/schemas/LDAPProviderRequest' | ||||||
|           authentik_providers_microsoft_entra.microsoftentraprovider: '#/components/schemas/MicrosoftEntraProviderRequest' |           authentik_providers_microsoft_entra.microsoftentraprovider: '#/components/schemas/MicrosoftEntraProviderRequest' | ||||||
|  | |||||||
| @ -9,8 +9,8 @@ | |||||||
|         "strict": true, |         "strict": true, | ||||||
|         "newLine": "lf", |         "newLine": "lf", | ||||||
|         "target": "ESNext", |         "target": "ESNext", | ||||||
|         "module": "ESNext", |         "module": "NodeNext", | ||||||
|         "moduleResolution": "bundler", |         "moduleResolution": "NodeNext", | ||||||
|         "outDir": "dist", |         "outDir": "dist", | ||||||
|         "skipDefaultLibCheck": true, |         "skipDefaultLibCheck": true, | ||||||
|         "skipLibCheck": true, |         "skipLibCheck": true, | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ services: | |||||||
|     network_mode: host |     network_mode: host | ||||||
|     restart: always |     restart: always | ||||||
|   mailpit: |   mailpit: | ||||||
|     image: docker.io/axllent/mailpit:v1.26.2 |     image: docker.io/axllent/mailpit:v1.27.0 | ||||||
|     ports: |     ports: | ||||||
|       - 1025:1025 |       - 1025:1025 | ||||||
|       - 8025:8025 |       - 8025:8025 | ||||||
|  | |||||||
							
								
								
									
										51
									
								
								uv.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										51
									
								
								uv.lock
									
									
									
										generated
									
									
									
								
							| @ -165,7 +165,7 @@ wheels = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "authentik" | name = "authentik" | ||||||
| version = "2025.6.2" | version = "2025.6.3" | ||||||
| source = { editable = "." } | source = { editable = "." } | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     { name = "argon2-cffi" }, |     { name = "argon2-cffi" }, | ||||||
| @ -279,10 +279,10 @@ requires-dist = [ | |||||||
|     { name = "django-countries", specifier = "==7.6.1" }, |     { name = "django-countries", specifier = "==7.6.1" }, | ||||||
|     { name = "django-cte", specifier = "==2.0.0" }, |     { name = "django-cte", specifier = "==2.0.0" }, | ||||||
|     { name = "django-filter", specifier = "==25.1" }, |     { name = "django-filter", specifier = "==25.1" }, | ||||||
|     { name = "django-guardian", specifier = "==3.0.0" }, |     { name = "django-guardian", specifier = "==3.0.3" }, | ||||||
|     { name = "django-model-utils", specifier = "==5.0.0" }, |     { name = "django-model-utils", specifier = "==5.0.0" }, | ||||||
|     { name = "django-pglock", specifier = "==1.7.2" }, |     { name = "django-pglock", specifier = "==1.7.2" }, | ||||||
|     { name = "django-prometheus", specifier = "==2.4.0" }, |     { name = "django-prometheus", specifier = "==2.4.1" }, | ||||||
|     { name = "django-redis", specifier = "==6.0.0" }, |     { name = "django-redis", specifier = "==6.0.0" }, | ||||||
|     { name = "django-storages", extras = ["s3"], specifier = "==1.14.6" }, |     { name = "django-storages", extras = ["s3"], specifier = "==1.14.6" }, | ||||||
|     { name = "django-tenants", specifier = "==3.8.0" }, |     { name = "django-tenants", specifier = "==3.8.0" }, | ||||||
| @ -298,7 +298,7 @@ requires-dist = [ | |||||||
|     { name = "flower", specifier = "==2.0.1" }, |     { name = "flower", specifier = "==2.0.1" }, | ||||||
|     { name = "geoip2", specifier = "==5.1.0" }, |     { name = "geoip2", specifier = "==5.1.0" }, | ||||||
|     { name = "geopy", specifier = "==2.4.1" }, |     { name = "geopy", specifier = "==2.4.1" }, | ||||||
|     { name = "google-api-python-client", specifier = "==2.173.0" }, |     { name = "google-api-python-client", specifier = "==2.174.0" }, | ||||||
|     { name = "gssapi", specifier = "==1.9.0" }, |     { name = "gssapi", specifier = "==1.9.0" }, | ||||||
|     { name = "gunicorn", specifier = "==23.0.0" }, |     { name = "gunicorn", specifier = "==23.0.0" }, | ||||||
|     { name = "jsonpatch", specifier = "==1.33" }, |     { name = "jsonpatch", specifier = "==1.33" }, | ||||||
| @ -306,7 +306,7 @@ requires-dist = [ | |||||||
|     { name = "kubernetes", specifier = "==33.1.0" }, |     { name = "kubernetes", specifier = "==33.1.0" }, | ||||||
|     { name = "ldap3", specifier = "==2.9.1" }, |     { name = "ldap3", specifier = "==2.9.1" }, | ||||||
|     { name = "lxml", specifier = "==5.4.0" }, |     { name = "lxml", specifier = "==5.4.0" }, | ||||||
|     { name = "msgraph-sdk", specifier = "==1.34.0" }, |     { name = "msgraph-sdk", specifier = "==1.35.0" }, | ||||||
|     { name = "opencontainers", git = "https://github.com/vsoch/oci-python?rev=ceb4fcc090851717a3069d78e85ceb1e86c2740c" }, |     { name = "opencontainers", git = "https://github.com/vsoch/oci-python?rev=ceb4fcc090851717a3069d78e85ceb1e86c2740c" }, | ||||||
|     { name = "packaging", specifier = "==25.0" }, |     { name = "packaging", specifier = "==25.0" }, | ||||||
|     { name = "paramiko", specifier = "==3.5.1" }, |     { name = "paramiko", specifier = "==3.5.1" }, | ||||||
| @ -319,7 +319,7 @@ requires-dist = [ | |||||||
|     { name = "pyyaml", specifier = "==6.0.2" }, |     { name = "pyyaml", specifier = "==6.0.2" }, | ||||||
|     { name = "requests-oauthlib", specifier = "==2.0.0" }, |     { name = "requests-oauthlib", specifier = "==2.0.0" }, | ||||||
|     { name = "scim2-filter-parser", specifier = "==0.7.0" }, |     { name = "scim2-filter-parser", specifier = "==0.7.0" }, | ||||||
|     { name = "sentry-sdk", specifier = "==2.31.0" }, |     { name = "sentry-sdk", specifier = "==2.32.0" }, | ||||||
|     { name = "service-identity", specifier = "==24.2.0" }, |     { name = "service-identity", specifier = "==24.2.0" }, | ||||||
|     { name = "setproctitle", specifier = "==1.3.6" }, |     { name = "setproctitle", specifier = "==1.3.6" }, | ||||||
|     { name = "structlog", specifier = "==25.4.0" }, |     { name = "structlog", specifier = "==25.4.0" }, | ||||||
| @ -329,7 +329,7 @@ requires-dist = [ | |||||||
|     { name = "ua-parser", specifier = "==1.0.1" }, |     { name = "ua-parser", specifier = "==1.0.1" }, | ||||||
|     { name = "unidecode", specifier = "==1.4.0" }, |     { name = "unidecode", specifier = "==1.4.0" }, | ||||||
|     { name = "urllib3", specifier = "<3" }, |     { name = "urllib3", specifier = "<3" }, | ||||||
|     { name = "uvicorn", extras = ["standard"], specifier = "==0.34.3" }, |     { name = "uvicorn", extras = ["standard"], specifier = "==0.35.0" }, | ||||||
|     { name = "watchdog", specifier = "==6.0.0" }, |     { name = "watchdog", specifier = "==6.0.0" }, | ||||||
|     { name = "webauthn", specifier = "==2.6.0" }, |     { name = "webauthn", specifier = "==2.6.0" }, | ||||||
|     { name = "wsproto", specifier = "==1.2.0" }, |     { name = "wsproto", specifier = "==1.2.0" }, | ||||||
| @ -1021,14 +1021,14 @@ wheels = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "django-guardian" | name = "django-guardian" | ||||||
| version = "3.0.0" | version = "3.0.3" | ||||||
| source = { registry = "https://pypi.org/simple" } | source = { registry = "https://pypi.org/simple" } | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     { name = "django" }, |     { name = "django" }, | ||||||
| ] | ] | ||||||
| sdist = { url = "https://files.pythonhosted.org/packages/30/82/2c76cdf77eae3cb0c3df394686daf8f84bcd604c0da7a26fa19f5fe74ed4/django_guardian-3.0.0.tar.gz", hash = "sha256:0c79d55c4af2cfc14fbd19539846a1ebfed2a38198b7697e0f5177b7f654e1cd", size = 79895, upload-time = "2025-05-07T19:33:23.328Z" } | sdist = { url = "https://files.pythonhosted.org/packages/30/c2/3ed43813dd7313f729dbaa829b4f9ed4a647530151f672cfb5f843c12edf/django_guardian-3.0.3.tar.gz", hash = "sha256:4e59eab4d836da5a027cf0c176d14bc2a4e22cbbdf753159a03946c08c8a196d", size = 85410, upload-time = "2025-06-25T20:42:17.475Z" } | ||||||
| wheels = [ | wheels = [ | ||||||
|     { url = "https://files.pythonhosted.org/packages/a5/81/a2f3d3245d1f4cf446d78863526fba0b1b140d60784095a5cc2d4e8ac709/django_guardian-3.0.0-py3-none-any.whl", hash = "sha256:f3ebe3cc7f486e267041b780c3429ad5db72c909df40c2f74adb1b059582a3cd", size = 112672, upload-time = "2025-05-07T19:33:21.719Z" }, |     { url = "https://files.pythonhosted.org/packages/8b/13/e6f629a978ef5fab8b8d2760cacc3e451016cef952cf4c049d672c5c6b07/django_guardian-3.0.3-py3-none-any.whl", hash = "sha256:d2164cea9f03c369d7ade21802710f3ab23ca6734bcc7dfcfb385906783916c7", size = 118198, upload-time = "2025-06-25T20:42:15.377Z" }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| @ -1070,14 +1070,15 @@ wheels = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "django-prometheus" | name = "django-prometheus" | ||||||
| version = "2.4.0" | version = "2.4.1" | ||||||
| source = { registry = "https://pypi.org/simple" } | source = { registry = "https://pypi.org/simple" } | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  |     { name = "django" }, | ||||||
|     { name = "prometheus-client" }, |     { name = "prometheus-client" }, | ||||||
| ] | ] | ||||||
| sdist = { url = "https://files.pythonhosted.org/packages/e8/b9/c758675671d71a1800feaad5c5fbcdecbd8d34296b63f9dc5662db39abda/django_prometheus-2.4.0.tar.gz", hash = "sha256:67da5c73d8e859aa73f6e11f52341c482691b17f8bd9844157cff6cdf51ce9bc", size = 24393, upload-time = "2025-06-18T18:06:28.673Z" } | sdist = { url = "https://files.pythonhosted.org/packages/98/f4/cb39ddd2a41e07a274c4e162c076e906ae232d63b66bbabdea0300878877/django_prometheus-2.4.1.tar.gz", hash = "sha256:073628243d2a6de6a8a8c20e5b512872dfb85d66e1b60b28bcf1eca0155dad95", size = 24464, upload-time = "2025-06-25T15:45:37.149Z" } | ||||||
| wheels = [ | wheels = [ | ||||||
|     { url = "https://files.pythonhosted.org/packages/38/05/d980950fb8c3f6f96c644599b1a025fb50e827477b1acf36daef72aa7e76/django_prometheus-2.4.0-py2.py3-none-any.whl", hash = "sha256:5b46b5f07b02ba8dd7abdb03a3c39073e8fd9120e2293a1ecb949bbb865378ac", size = 29528, upload-time = "2025-06-18T18:06:27.079Z" }, |     { url = "https://files.pythonhosted.org/packages/01/50/9c5e022fa92574e5d20606687f15a2aa255e10512a17d11a8216fa117f72/django_prometheus-2.4.1-py2.py3-none-any.whl", hash = "sha256:7fe5af7f7c9ad9cd8a429fe0f3f1bf651f0e244f77162147869eab7ec09cc5e7", size = 29541, upload-time = "2025-06-25T15:45:35.433Z" }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| @ -1402,7 +1403,7 @@ wheels = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "google-api-python-client" | name = "google-api-python-client" | ||||||
| version = "2.173.0" | version = "2.174.0" | ||||||
| source = { registry = "https://pypi.org/simple" } | source = { registry = "https://pypi.org/simple" } | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     { name = "google-api-core" }, |     { name = "google-api-core" }, | ||||||
| @ -1411,9 +1412,9 @@ dependencies = [ | |||||||
|     { name = "httplib2" }, |     { name = "httplib2" }, | ||||||
|     { name = "uritemplate" }, |     { name = "uritemplate" }, | ||||||
| ] | ] | ||||||
| sdist = { url = "https://files.pythonhosted.org/packages/8f/7e/7c6e43e54f611f0f97f1678ea567fe06fecd545bd574db05e204e5b136fe/google_api_python_client-2.173.0.tar.gz", hash = "sha256:b537bc689758f4be3e6f40d59a6c0cd305abafdea91af4bc66ec31d40c08c804", size = 13091318, upload-time = "2025-06-19T19:39:05.881Z" } | sdist = { url = "https://files.pythonhosted.org/packages/1a/fd/860fef0cf3edbad828e2ab4d2ddee5dfe8e595b6da748ac6c77e95bc7bef/google_api_python_client-2.174.0.tar.gz", hash = "sha256:9eb7616a820b38a9c12c5486f9b9055385c7feb18b20cbafc5c5a688b14f3515", size = 13127872, upload-time = "2025-06-25T19:27:12.977Z" } | ||||||
| wheels = [ | wheels = [ | ||||||
|     { url = "https://files.pythonhosted.org/packages/e6/c9/dc9ca0537ee2ddac0f0b1e458903afe3f490a0f90dfd4b1b16eb339cdfbb/google_api_python_client-2.173.0-py3-none-any.whl", hash = "sha256:16a8e81c772dd116f5c4ee47d83643149e1367dc8fb4f47cb471fbcb5c7d7ac7", size = 13612778, upload-time = "2025-06-19T19:39:03.283Z" }, |     { url = "https://files.pythonhosted.org/packages/16/2d/4250b81e8f5309b58650660f403584db6f64067acac74475893a8f33348d/google_api_python_client-2.174.0-py3-none-any.whl", hash = "sha256:f695205ceec97bfaa1590a14282559c4109326c473b07352233a3584cdbf4b89", size = 13650466, upload-time = "2025-06-25T19:27:10.426Z" }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| @ -2071,7 +2072,7 @@ wheels = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "msgraph-sdk" | name = "msgraph-sdk" | ||||||
| version = "1.34.0" | version = "1.35.0" | ||||||
| source = { registry = "https://pypi.org/simple" } | source = { registry = "https://pypi.org/simple" } | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     { name = "azure-identity" }, |     { name = "azure-identity" }, | ||||||
| @ -2081,9 +2082,9 @@ dependencies = [ | |||||||
|     { name = "microsoft-kiota-serialization-text" }, |     { name = "microsoft-kiota-serialization-text" }, | ||||||
|     { name = "msgraph-core" }, |     { name = "msgraph-core" }, | ||||||
| ] | ] | ||||||
| sdist = { url = "https://files.pythonhosted.org/packages/92/7a/c69b4fc4b9c02a6d14eddc96b91319dd7e91f0987245d4243a74b9c17fcf/msgraph_sdk-1.34.0.tar.gz", hash = "sha256:f71a81d3291f49d3610220de47bbbb6321aa62f7129d17a958f301b9acadfe99", size = 5968516, upload-time = "2025-06-18T11:43:33.287Z" } | sdist = { url = "https://files.pythonhosted.org/packages/33/49/25df000defb136542400bbe3096b3e1dab384e5b02fec4c6c4cb4a433296/msgraph_sdk-1.35.0.tar.gz", hash = "sha256:513f77d3332618af35d2f456ff26e2050f136abc8856858a69d63e811480eddd", size = 5967030, upload-time = "2025-06-25T10:28:30.599Z" } | ||||||
| wheels = [ | wheels = [ | ||||||
|     { url = "https://files.pythonhosted.org/packages/f2/0c/75f8066eca60fe9b2d5e1dd868b592533671b7b5cc711e655afd5c44d259/msgraph_sdk-1.34.0-py3-none-any.whl", hash = "sha256:d6daea012b78a7a4dd07fabb782ae00e4a9fe4f8d6016e8037769962533aa8ae", size = 24491410, upload-time = "2025-06-18T11:43:30.824Z" }, |     { url = "https://files.pythonhosted.org/packages/72/ae/a0ea8742af0c99c9f53d82bca19f027f10d747874f725fa2f8d165eb60b3/msgraph_sdk-1.35.0-py3-none-any.whl", hash = "sha256:0e2305a0d6d8343f3a29aa227183c6acc6191f4dfda8522ea41d97e7fe25a0d1", size = 24490922, upload-time = "2025-06-25T10:28:28.127Z" }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| @ -2960,15 +2961,15 @@ wheels = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "sentry-sdk" | name = "sentry-sdk" | ||||||
| version = "2.31.0" | version = "2.32.0" | ||||||
| source = { registry = "https://pypi.org/simple" } | source = { registry = "https://pypi.org/simple" } | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     { name = "certifi" }, |     { name = "certifi" }, | ||||||
|     { name = "urllib3" }, |     { name = "urllib3" }, | ||||||
| ] | ] | ||||||
| sdist = { url = "https://files.pythonhosted.org/packages/d0/45/c7ef7e12d8434fda8b61cdab432d8af64fb832480c93cdaf4bdcab7f5597/sentry_sdk-2.31.0.tar.gz", hash = "sha256:fed6d847f15105849cdf5dfdc64dcec356f936d41abb8c9d66adae45e60959ec", size = 334167, upload-time = "2025-06-24T16:36:26.066Z" } | sdist = { url = "https://files.pythonhosted.org/packages/10/59/eb90c45cb836cf8bec973bba10230ddad1c55e2b2e9ffa9d7d7368948358/sentry_sdk-2.32.0.tar.gz", hash = "sha256:9016c75d9316b0f6921ac14c8cd4fb938f26002430ac5be9945ab280f78bec6b", size = 334932, upload-time = "2025-06-27T08:10:02.89Z" } | ||||||
| wheels = [ | wheels = [ | ||||||
|     { url = "https://files.pythonhosted.org/packages/7d/a2/9b6d8cc59f03251c583b3fec9d2f075dc09c0f6e030e0e0a3b223c6e64b2/sentry_sdk-2.31.0-py2.py3-none-any.whl", hash = "sha256:e953f5ab083e6599bab255b75d6829b33b3ddf9931a27ca00b4ab0081287e84f", size = 355638, upload-time = "2025-06-24T16:36:24.306Z" }, |     { url = "https://files.pythonhosted.org/packages/01/a1/fc4856bd02d2097324fb7ce05b3021fb850f864b83ca765f6e37e92ff8ca/sentry_sdk-2.32.0-py2.py3-none-any.whl", hash = "sha256:6cf51521b099562d7ce3606da928c473643abe99b00ce4cb5626ea735f4ec345", size = 356122, upload-time = "2025-06-27T08:10:01.424Z" }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| @ -3321,15 +3322,15 @@ socks = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "uvicorn" | name = "uvicorn" | ||||||
| version = "0.34.3" | version = "0.35.0" | ||||||
| source = { registry = "https://pypi.org/simple" } | source = { registry = "https://pypi.org/simple" } | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     { name = "click" }, |     { name = "click" }, | ||||||
|     { name = "h11" }, |     { name = "h11" }, | ||||||
| ] | ] | ||||||
| sdist = { url = "https://files.pythonhosted.org/packages/de/ad/713be230bcda622eaa35c28f0d328c3675c371238470abdea52417f17a8e/uvicorn-0.34.3.tar.gz", hash = "sha256:35919a9a979d7a59334b6b10e05d77c1d0d574c50e0fc98b8b1a0f165708b55a", size = 76631, upload-time = "2025-06-01T07:48:17.531Z" } | sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } | ||||||
| wheels = [ | wheels = [ | ||||||
|     { url = "https://files.pythonhosted.org/packages/6d/0d/8adfeaa62945f90d19ddc461c55f4a50c258af7662d34b6a3d5d1f8646f6/uvicorn-0.34.3-py3-none-any.whl", hash = "sha256:16246631db62bdfbf069b0645177d6e8a77ba950cfedbfd093acef9444e4d885", size = 62431, upload-time = "2025-06-01T07:48:15.664Z" }, |     { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [package.optional-dependencies] | [package.optional-dependencies] | ||||||
|  | |||||||
							
								
								
									
										260
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										260
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -34,7 +34,7 @@ | |||||||
|                 "@openlayers-elements/maps": "^0.4.0", |                 "@openlayers-elements/maps": "^0.4.0", | ||||||
|                 "@patternfly/elements": "^4.1.0", |                 "@patternfly/elements": "^4.1.0", | ||||||
|                 "@patternfly/patternfly": "^4.224.2", |                 "@patternfly/patternfly": "^4.224.2", | ||||||
|                 "@sentry/browser": "^9.31.0", |                 "@sentry/browser": "^9.32.0", | ||||||
|                 "@spotlightjs/spotlight": "^3.0.1", |                 "@spotlightjs/spotlight": "^3.0.1", | ||||||
|                 "@webcomponents/webcomponentsjs": "^2.8.0", |                 "@webcomponents/webcomponentsjs": "^2.8.0", | ||||||
|                 "base64-js": "^1.5.1", |                 "base64-js": "^1.5.1", | ||||||
| @ -75,7 +75,7 @@ | |||||||
|             "devDependencies": { |             "devDependencies": { | ||||||
|                 "@eslint/js": "^9.27.0", |                 "@eslint/js": "^9.27.0", | ||||||
|                 "@goauthentik/core": "^1.0.0", |                 "@goauthentik/core": "^1.0.0", | ||||||
|                 "@goauthentik/esbuild-plugin-live-reload": "^1.0.4", |                 "@goauthentik/esbuild-plugin-live-reload": "^1.0.5", | ||||||
|                 "@goauthentik/eslint-config": "^1.0.5", |                 "@goauthentik/eslint-config": "^1.0.5", | ||||||
|                 "@goauthentik/prettier-config": "^1.0.5", |                 "@goauthentik/prettier-config": "^1.0.5", | ||||||
|                 "@goauthentik/tsconfig": "^1.0.4", |                 "@goauthentik/tsconfig": "^1.0.4", | ||||||
| @ -1716,20 +1716,6 @@ | |||||||
|                 "node": ">=6" |                 "node": ">=6" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@gerrit0/mini-shiki": { |  | ||||||
|             "version": "3.4.2", |  | ||||||
|             "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.4.2.tgz", |  | ||||||
|             "integrity": "sha512-3jXo5bNjvvimvdbIhKGfFxSnKCX+MA8wzHv55ptzk/cx8wOzT+BRcYgj8aFN3yTiTs+zvQQiaZFr7Jce1ZG3fw==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "@shikijs/engine-oniguruma": "^3.4.2", |  | ||||||
|                 "@shikijs/langs": "^3.4.2", |  | ||||||
|                 "@shikijs/themes": "^3.4.2", |  | ||||||
|                 "@shikijs/types": "^3.4.2", |  | ||||||
|                 "@shikijs/vscode-textmate": "^10.0.2" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/@goauthentik/api": { |         "node_modules/@goauthentik/api": { | ||||||
|             "version": "2025.6.2-1750856752", |             "version": "2025.6.2-1750856752", | ||||||
|             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.6.2-1750856752.tgz", |             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.6.2-1750856752.tgz", | ||||||
| @ -1740,8 +1726,20 @@ | |||||||
|             "link": true |             "link": true | ||||||
|         }, |         }, | ||||||
|         "node_modules/@goauthentik/esbuild-plugin-live-reload": { |         "node_modules/@goauthentik/esbuild-plugin-live-reload": { | ||||||
|             "resolved": "packages/esbuild-plugin-live-reload", |             "version": "1.0.5", | ||||||
|             "link": true |             "resolved": "https://registry.npmjs.org/@goauthentik/esbuild-plugin-live-reload/-/esbuild-plugin-live-reload-1.0.5.tgz", | ||||||
|  |             "integrity": "sha512-MZ/najY+Xn62ijzj7JDS1sVupWI3BNRwJc4kykB/iP9CdLJw+xO71qPTjfCEEOVYMZrOTftD4KOLhRYx3GTqkA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "find-free-ports": "^3.1.1" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=22" | ||||||
|  |             }, | ||||||
|  |             "peerDependencies": { | ||||||
|  |                 "esbuild": "^0.25.4" | ||||||
|  |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@goauthentik/eslint-config": { |         "node_modules/@goauthentik/eslint-config": { | ||||||
|             "version": "1.0.5", |             "version": "1.0.5", | ||||||
| @ -4058,6 +4056,7 @@ | |||||||
|             "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", |             "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": "^12.20.0 || ^14.18.0 || >=16.0.0" |                 "node": "^12.20.0 || ^14.18.0 || >=16.0.0" | ||||||
|             }, |             }, | ||||||
| @ -4561,75 +4560,75 @@ | |||||||
|             "dev": true |             "dev": true | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry-internal/browser-utils": { |         "node_modules/@sentry-internal/browser-utils": { | ||||||
|             "version": "9.31.0", |             "version": "9.32.0", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.31.0.tgz", |             "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.32.0.tgz", | ||||||
|             "integrity": "sha512-rviu/jUmeQbY4rSO8l4pubOtRIhFtH5Gu/ryRNMTlpJRdomp4uxddqthHUDH5g6xCXZsMTyJEIdx0aTqbgr/GQ==", |             "integrity": "sha512-mVWdruSWXF+2WgS24jwLhWFyC/nDQbKXseLR8paU9LGSnVtlBlQseIx1GrANbJrhBxiEWSft4WiuxU34wPsbXg==", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/core": "9.31.0" |                 "@sentry/core": "9.32.0" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=18" |                 "node": ">=18" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry-internal/feedback": { |         "node_modules/@sentry-internal/feedback": { | ||||||
|             "version": "9.31.0", |             "version": "9.32.0", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.31.0.tgz", |             "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.32.0.tgz", | ||||||
|             "integrity": "sha512-Ygi/8UZ7p2B4DhXQjZDtOc45vNUHkfk2XETBTBGkByEQkE8vygzSiKhgRcnVpzwq+8xKFMRy+PxvpcCo+PNQew==", |             "integrity": "sha512-OaXaovXqlhN1sG2wtJMhxMEjyeuK7RwY57o96LgKE0bWM//Fs9WWCOkGa+7l8TOf0+0ib7gfhJZlpN0hlqOgRw==", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry/core": "9.31.0" |                 "@sentry/core": "9.32.0" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=18" |                 "node": ">=18" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry-internal/replay": { |         "node_modules/@sentry-internal/replay": { | ||||||
|             "version": "9.31.0", |             "version": "9.32.0", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.31.0.tgz", |             "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.32.0.tgz", | ||||||
|             "integrity": "sha512-V5rvcO/xSj8JMw4ZnZT2cBYC+UOuIiZ2Flj4EoIurxMrTgowE1uMXUBA32EBfuB5/vQSJXB6W5uAudhk7LjBPQ==", |             "integrity": "sha512-mOHUKjUtHbEwshikrCQPM1ZqWAMUEcpEGashnXQp3KQivvbTxrExiNnt6XK5TjJyGvsI3A907Bp/HvEzgneYgQ==", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry-internal/browser-utils": "9.31.0", |                 "@sentry-internal/browser-utils": "9.32.0", | ||||||
|                 "@sentry/core": "9.31.0" |                 "@sentry/core": "9.32.0" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=18" |                 "node": ">=18" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry-internal/replay-canvas": { |         "node_modules/@sentry-internal/replay-canvas": { | ||||||
|             "version": "9.31.0", |             "version": "9.32.0", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.31.0.tgz", |             "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.32.0.tgz", | ||||||
|             "integrity": "sha512-VGqfvQCIuXQZeecrBf8bd4sj8lYGzUA/2CffTAkad1nB1Onyz0Kzo54qLWemivCxA3ufHf6DCpNA3Loa/0ywFQ==", |             "integrity": "sha512-tu+coeTRpJxknmWPMJC2jqmIM5IsVoRn9gEDdkSrcPbgx/GwgE03fSJVBJL1tOEA8yRNIhZPMR86ORE7/7n2ow==", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry-internal/replay": "9.31.0", |                 "@sentry-internal/replay": "9.32.0", | ||||||
|                 "@sentry/core": "9.31.0" |                 "@sentry/core": "9.32.0" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=18" |                 "node": ">=18" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/browser": { |         "node_modules/@sentry/browser": { | ||||||
|             "version": "9.31.0", |             "version": "9.32.0", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.31.0.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.32.0.tgz", | ||||||
|             "integrity": "sha512-DzG72JJTqHzE0Qo2fHeHm3xgFs97InaSQStmTMxOA59yPqvAXbweNPcsgCNu1q76+jZyaJcoy1qOwahnLuEVDg==", |             "integrity": "sha512-BzPogpH87n+sC9VPfXaXkiKJtagLpIB87LGg1hSBURpwGx6Rt2ORmaVYgwwuuFZX8Hia727IIM7pbcbNfrXGRQ==", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@sentry-internal/browser-utils": "9.31.0", |                 "@sentry-internal/browser-utils": "9.32.0", | ||||||
|                 "@sentry-internal/feedback": "9.31.0", |                 "@sentry-internal/feedback": "9.32.0", | ||||||
|                 "@sentry-internal/replay": "9.31.0", |                 "@sentry-internal/replay": "9.32.0", | ||||||
|                 "@sentry-internal/replay-canvas": "9.31.0", |                 "@sentry-internal/replay-canvas": "9.32.0", | ||||||
|                 "@sentry/core": "9.31.0" |                 "@sentry/core": "9.32.0" | ||||||
|             }, |             }, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=18" |                 "node": ">=18" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@sentry/core": { |         "node_modules/@sentry/core": { | ||||||
|             "version": "9.31.0", |             "version": "9.32.0", | ||||||
|             "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.31.0.tgz", |             "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.32.0.tgz", | ||||||
|             "integrity": "sha512-6JeoPGvBgT9m2YFIf2CrW+KrrOYzUqb9+Xwr/Dw25kPjVKy+WJjWqK8DKCNLgkBA22OCmSOmHuRwFR0YxGVdZQ==", |             "integrity": "sha512-1wAXMMmeY4Ny2MJBCuri3b4LMVPjqXdgbVgTxxipGW+gzPsjv+8+LCSnJAR/cRBr8JoXV+qGC2tE06rI1XDj3A==", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=18" |                 "node": ">=18" | ||||||
| @ -4719,55 +4718,6 @@ | |||||||
|                 "node": ">=14.18" |                 "node": ">=14.18" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/@shikijs/engine-oniguruma": { |  | ||||||
|             "version": "3.4.2", |  | ||||||
|             "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.4.2.tgz", |  | ||||||
|             "integrity": "sha512-zcZKMnNndgRa3ORja6Iemsr3DrLtkX3cAF7lTJkdMB6v9alhlBsX9uNiCpqofNrXOvpA3h6lHcLJxgCIhVOU5Q==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "@shikijs/types": "3.4.2", |  | ||||||
|                 "@shikijs/vscode-textmate": "^10.0.2" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/@shikijs/langs": { |  | ||||||
|             "version": "3.4.2", |  | ||||||
|             "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.4.2.tgz", |  | ||||||
|             "integrity": "sha512-H6azIAM+OXD98yztIfs/KH5H4PU39t+SREhmM8LaNXyUrqj2mx+zVkr8MWYqjceSjDw9I1jawm1WdFqU806rMA==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "@shikijs/types": "3.4.2" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/@shikijs/themes": { |  | ||||||
|             "version": "3.4.2", |  | ||||||
|             "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.4.2.tgz", |  | ||||||
|             "integrity": "sha512-qAEuAQh+brd8Jyej2UDDf+b4V2g1Rm8aBIdvt32XhDPrHvDkEnpb7Kzc9hSuHUxz0Iuflmq7elaDuQAP9bHIhg==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "@shikijs/types": "3.4.2" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/@shikijs/types": { |  | ||||||
|             "version": "3.4.2", |  | ||||||
|             "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.4.2.tgz", |  | ||||||
|             "integrity": "sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "@shikijs/vscode-textmate": "^10.0.2", |  | ||||||
|                 "@types/hast": "^3.0.4" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/@shikijs/vscode-textmate": { |  | ||||||
|             "version": "10.0.2", |  | ||||||
|             "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", |  | ||||||
|             "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT" |  | ||||||
|         }, |  | ||||||
|         "node_modules/@sinclair/typebox": { |         "node_modules/@sinclair/typebox": { | ||||||
|             "version": "0.27.8", |             "version": "0.27.8", | ||||||
|             "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", |             "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", | ||||||
| @ -13238,6 +13188,7 @@ | |||||||
|             "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", |             "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": ">=12.20" |                 "node": ">=12.20" | ||||||
|             } |             } | ||||||
| @ -13248,6 +13199,7 @@ | |||||||
|             "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", |             "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "engines": { |             "engines": { | ||||||
|                 "node": "^12.20.0 || ^14.13.1 || >=16.0.0" |                 "node": "^12.20.0 || ^14.13.1 || >=16.0.0" | ||||||
|             }, |             }, | ||||||
| @ -15698,6 +15650,7 @@ | |||||||
|             "version": "3.1.1", |             "version": "3.1.1", | ||||||
|             "resolved": "https://registry.npmjs.org/find-free-ports/-/find-free-ports-3.1.1.tgz", |             "resolved": "https://registry.npmjs.org/find-free-ports/-/find-free-ports-3.1.1.tgz", | ||||||
|             "integrity": "sha512-hQebewth9i5qkf0a0u06iFaxQssk5ZnPBBggsa1vk8zCYaZoz9IZXpoRLTbEOrYdqfrjvcxU00gYoCPgmXugKA==", |             "integrity": "sha512-hQebewth9i5qkf0a0u06iFaxQssk5ZnPBBggsa1vk8zCYaZoz9IZXpoRLTbEOrYdqfrjvcxU00gYoCPgmXugKA==", | ||||||
|  |             "dev": true, | ||||||
|             "license": "MIT" |             "license": "MIT" | ||||||
|         }, |         }, | ||||||
|         "node_modules/find-replace": { |         "node_modules/find-replace": { | ||||||
| @ -16242,6 +16195,7 @@ | |||||||
|             "integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==", |             "integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "funding": { |             "funding": { | ||||||
|                 "url": "https://github.com/fisker/git-hooks-list?sponsor=1" |                 "url": "https://github.com/fisker/git-hooks-list?sponsor=1" | ||||||
|             } |             } | ||||||
| @ -19172,16 +19126,6 @@ | |||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT" |             "license": "MIT" | ||||||
|         }, |         }, | ||||||
|         "node_modules/linkify-it": { |  | ||||||
|             "version": "5.0.0", |  | ||||||
|             "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", |  | ||||||
|             "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "uc.micro": "^2.0.0" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/lit": { |         "node_modules/lit": { | ||||||
|             "version": "3.3.0", |             "version": "3.3.0", | ||||||
|             "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz", |             "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz", | ||||||
| @ -19586,13 +19530,6 @@ | |||||||
|                 "node": ">=16.14" |                 "node": ">=16.14" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/lunr": { |  | ||||||
|             "version": "2.3.9", |  | ||||||
|             "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", |  | ||||||
|             "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT" |  | ||||||
|         }, |  | ||||||
|         "node_modules/lz-string": { |         "node_modules/lz-string": { | ||||||
|             "version": "1.5.0", |             "version": "1.5.0", | ||||||
|             "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", |             "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", | ||||||
| @ -19654,24 +19591,6 @@ | |||||||
|                 "url": "https://github.com/sponsors/sindresorhus" |                 "url": "https://github.com/sponsors/sindresorhus" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/markdown-it": { |  | ||||||
|             "version": "14.1.0", |  | ||||||
|             "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", |  | ||||||
|             "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "argparse": "^2.0.1", |  | ||||||
|                 "entities": "^4.4.0", |  | ||||||
|                 "linkify-it": "^5.0.0", |  | ||||||
|                 "mdurl": "^2.0.0", |  | ||||||
|                 "punycode.js": "^2.3.1", |  | ||||||
|                 "uc.micro": "^2.1.0" |  | ||||||
|             }, |  | ||||||
|             "bin": { |  | ||||||
|                 "markdown-it": "bin/markdown-it.mjs" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/markdown-table": { |         "node_modules/markdown-table": { | ||||||
|             "version": "3.0.4", |             "version": "3.0.4", | ||||||
|             "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", |             "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", | ||||||
| @ -20069,13 +19988,6 @@ | |||||||
|                 "url": "https://opencollective.com/unified" |                 "url": "https://opencollective.com/unified" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/mdurl": { |  | ||||||
|             "version": "2.0.0", |  | ||||||
|             "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", |  | ||||||
|             "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT" |  | ||||||
|         }, |  | ||||||
|         "node_modules/media-typer": { |         "node_modules/media-typer": { | ||||||
|             "version": "0.3.0", |             "version": "0.3.0", | ||||||
|             "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", |             "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | ||||||
| @ -23018,6 +22930,7 @@ | |||||||
|             "integrity": "sha512-h+3tSpr2nVpp+YOK1MDIYtYhHVXr8/0V59UUbJpIJFaqi3w4fvUokJo6eV8W+vELrUXIZzJ+DKm5G7lYzrMcKQ==", |             "integrity": "sha512-h+3tSpr2nVpp+YOK1MDIYtYhHVXr8/0V59UUbJpIJFaqi3w4fvUokJo6eV8W+vELrUXIZzJ+DKm5G7lYzrMcKQ==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "sort-package-json": "3.2.1", |                 "sort-package-json": "3.2.1", | ||||||
|                 "synckit": "0.11.6" |                 "synckit": "0.11.6" | ||||||
| @ -23265,16 +23178,6 @@ | |||||||
|                 "node": ">=6" |                 "node": ">=6" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/punycode.js": { |  | ||||||
|             "version": "2.3.1", |  | ||||||
|             "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", |  | ||||||
|             "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "engines": { |  | ||||||
|                 "node": ">=6" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/puppeteer-core": { |         "node_modules/puppeteer-core": { | ||||||
|             "version": "22.15.0", |             "version": "22.15.0", | ||||||
|             "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz", |             "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz", | ||||||
| @ -25377,7 +25280,8 @@ | |||||||
|             "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", |             "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", | ||||||
|             "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", |             "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT" |             "license": "MIT", | ||||||
|  |             "peer": true | ||||||
|         }, |         }, | ||||||
|         "node_modules/sort-package-json": { |         "node_modules/sort-package-json": { | ||||||
|             "version": "3.2.1", |             "version": "3.2.1", | ||||||
| @ -25385,6 +25289,7 @@ | |||||||
|             "integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==", |             "integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "detect-indent": "^7.0.1", |                 "detect-indent": "^7.0.1", | ||||||
|                 "detect-newline": "^4.0.1", |                 "detect-newline": "^4.0.1", | ||||||
| @ -26077,6 +25982,7 @@ | |||||||
|             "integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==", |             "integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "@pkgr/core": "^0.2.4" |                 "@pkgr/core": "^0.2.4" | ||||||
|             }, |             }, | ||||||
| @ -26287,6 +26193,7 @@ | |||||||
|             "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", |             "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", | ||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|  |             "peer": true, | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "fdir": "^6.4.4", |                 "fdir": "^6.4.4", | ||||||
|                 "picomatch": "^4.0.2" |                 "picomatch": "^4.0.2" | ||||||
| @ -27156,43 +27063,6 @@ | |||||||
|             "dev": true, |             "dev": true, | ||||||
|             "license": "MIT" |             "license": "MIT" | ||||||
|         }, |         }, | ||||||
|         "node_modules/typedoc": { |  | ||||||
|             "version": "0.28.5", |  | ||||||
|             "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.5.tgz", |  | ||||||
|             "integrity": "sha512-5PzUddaA9FbaarUzIsEc4wNXCiO4Ot3bJNeMF2qKpYlTmM9TTaSHQ7162w756ERCkXER/+o2purRG6YOAv6EMA==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "Apache-2.0", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "@gerrit0/mini-shiki": "^3.2.2", |  | ||||||
|                 "lunr": "^2.3.9", |  | ||||||
|                 "markdown-it": "^14.1.0", |  | ||||||
|                 "minimatch": "^9.0.5", |  | ||||||
|                 "yaml": "^2.7.1" |  | ||||||
|             }, |  | ||||||
|             "bin": { |  | ||||||
|                 "typedoc": "bin/typedoc" |  | ||||||
|             }, |  | ||||||
|             "engines": { |  | ||||||
|                 "node": ">= 18", |  | ||||||
|                 "pnpm": ">= 10" |  | ||||||
|             }, |  | ||||||
|             "peerDependencies": { |  | ||||||
|                 "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/typedoc-plugin-markdown": { |  | ||||||
|             "version": "4.6.3", |  | ||||||
|             "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.6.3.tgz", |  | ||||||
|             "integrity": "sha512-86oODyM2zajXwLs4Wok2mwVEfCwCnp756QyhLGX2IfsdRYr1DXLCgJgnLndaMUjJD7FBhnLk2okbNE9PdLxYRw==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "engines": { |  | ||||||
|                 "node": ">= 18" |  | ||||||
|             }, |  | ||||||
|             "peerDependencies": { |  | ||||||
|                 "typedoc": "0.28.x" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "node_modules/types-ramda": { |         "node_modules/types-ramda": { | ||||||
|             "version": "0.30.1", |             "version": "0.30.1", | ||||||
|             "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.30.1.tgz", |             "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.30.1.tgz", | ||||||
| @ -27249,13 +27119,6 @@ | |||||||
|                 "node": ">=8" |                 "node": ">=8" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "node_modules/uc.micro": { |  | ||||||
|             "version": "2.1.0", |  | ||||||
|             "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", |  | ||||||
|             "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT" |  | ||||||
|         }, |  | ||||||
|         "node_modules/ufo": { |         "node_modules/ufo": { | ||||||
|             "version": "1.5.4", |             "version": "1.5.4", | ||||||
|             "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", |             "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", | ||||||
| @ -29467,6 +29330,7 @@ | |||||||
|         "packages/esbuild-plugin-live-reload": { |         "packages/esbuild-plugin-live-reload": { | ||||||
|             "name": "@goauthentik/esbuild-plugin-live-reload", |             "name": "@goauthentik/esbuild-plugin-live-reload", | ||||||
|             "version": "1.0.5", |             "version": "1.0.5", | ||||||
|  |             "extraneous": true, | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "find-free-ports": "^3.1.1" |                 "find-free-ports": "^3.1.1" | ||||||
| @ -29490,16 +29354,6 @@ | |||||||
|                 "esbuild": "^0.25.5" |                 "esbuild": "^0.25.5" | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "packages/esbuild-plugin-live-reload/node_modules/@types/node": { |  | ||||||
|             "version": "22.15.19", |  | ||||||
|             "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.19.tgz", |  | ||||||
|             "integrity": "sha512-3vMNr4TzNQyjHcRZadojpRaD9Ofr6LsonZAoQ+HMUa/9ORTPoxVIw0e0mpqWpdjj8xybyCM+oKOUH2vwFu/oEw==", |  | ||||||
|             "dev": true, |  | ||||||
|             "license": "MIT", |  | ||||||
|             "dependencies": { |  | ||||||
|                 "undici-types": "~6.21.0" |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "packages/monorepo": { |         "packages/monorepo": { | ||||||
|             "name": "@goauthentik/monorepo", |             "name": "@goauthentik/monorepo", | ||||||
|             "version": "1.0.0", |             "version": "1.0.0", | ||||||
|  | |||||||
| @ -105,7 +105,7 @@ | |||||||
|         "@openlayers-elements/maps": "^0.4.0", |         "@openlayers-elements/maps": "^0.4.0", | ||||||
|         "@patternfly/elements": "^4.1.0", |         "@patternfly/elements": "^4.1.0", | ||||||
|         "@patternfly/patternfly": "^4.224.2", |         "@patternfly/patternfly": "^4.224.2", | ||||||
|         "@sentry/browser": "^9.31.0", |         "@sentry/browser": "^9.32.0", | ||||||
|         "@spotlightjs/spotlight": "^3.0.1", |         "@spotlightjs/spotlight": "^3.0.1", | ||||||
|         "@webcomponents/webcomponentsjs": "^2.8.0", |         "@webcomponents/webcomponentsjs": "^2.8.0", | ||||||
|         "base64-js": "^1.5.1", |         "base64-js": "^1.5.1", | ||||||
| @ -146,7 +146,7 @@ | |||||||
|     "devDependencies": { |     "devDependencies": { | ||||||
|         "@eslint/js": "^9.27.0", |         "@eslint/js": "^9.27.0", | ||||||
|         "@goauthentik/core": "^1.0.0", |         "@goauthentik/core": "^1.0.0", | ||||||
|         "@goauthentik/esbuild-plugin-live-reload": "^1.0.4", |         "@goauthentik/esbuild-plugin-live-reload": "^1.0.5", | ||||||
|         "@goauthentik/eslint-config": "^1.0.5", |         "@goauthentik/eslint-config": "^1.0.5", | ||||||
|         "@goauthentik/prettier-config": "^1.0.5", |         "@goauthentik/prettier-config": "^1.0.5", | ||||||
|         "@goauthentik/tsconfig": "^1.0.4", |         "@goauthentik/tsconfig": "^1.0.4", | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>Im Namen von |         <target>Im Namen von | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9256,6 +9256,9 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -363,7 +363,7 @@ | |||||||
|         <target>Recent events</target> |         <target>Recent events</target> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>On behalf of |         <target>On behalf of | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
| @ -7766,6 +7766,9 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>En nombre de |         <target>En nombre de | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9317,6 +9317,9 @@ Las vinculaciones a grupos o usuarios se comparan con el usuario del evento.</ta | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>Au nom de |         <target>Au nom de | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9884,6 +9884,9 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>Per conto di |         <target>Per conto di | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9904,6 +9904,11 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  |   <target>Questa applicazione al momento non ha eventuali diritti applicativi definiti.</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
|  |   <target>Autenticato come <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -445,7 +445,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="saf63a04c86018698"> |       <trans-unit id="saf63a04c86018698"> | ||||||
| @ -9224,6 +9224,9 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -447,7 +447,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>Namens |         <target>Namens | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9128,6 +9128,9 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>W imieniu |         <target>W imieniu | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9551,6 +9551,9 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -448,7 +448,7 @@ | |||||||
|  |  | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|   <target>Ōń ƀēĥàĺƒ ōƒ <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |   <target>Ōń ƀēĥàĺƒ ōƒ <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|  |  | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
| @ -9560,4 +9560,7 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
|  | </trans-unit> | ||||||
| </body></file></xliff> | </body></file></xliff> | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>От имени |         <target>От имени | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9643,6 +9643,9 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -447,7 +447,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target><x id="0" equiv-text="${event.user.on_behalf_of.username}"/> adına</target> |         <target><x id="0" equiv-text="${event.user.on_behalf_of.username}"/> adına</target> | ||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
| @ -9615,6 +9615,9 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -294,7 +294,7 @@ | |||||||
|   <source>Recent events</source> |   <source>Recent events</source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sc35581d9c1cd67ff"> | <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|   <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |   <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="saf63a04c86018698"> | <trans-unit id="saf63a04c86018698"> | ||||||
|   <source>-</source> |   <source>-</source> | ||||||
| @ -6383,6 +6383,9 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
|  | </trans-unit> | ||||||
| </body> | </body> | ||||||
| </file> | </file> | ||||||
| </xliff> | </xliff> | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>代表 |         <target>代表 | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -9876,27 +9876,39 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="s0433d667ea6eec1a"> | <trans-unit id="s0433d667ea6eec1a"> | ||||||
|   <source>The name of an invitation must be a slug: only lower case letters, numbers, and the hyphen are permitted here.</source> |   <source>The name of an invitation must be a slug: only lower case letters, numbers, and the hyphen are permitted here.</source> | ||||||
|  |   <target>邀请名称必须是一个 Slug:仅允许小写字母、数字和连字符。</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="s2e9d5ea88f02ae68"> | <trans-unit id="s2e9d5ea88f02ae68"> | ||||||
|   <source>Select the group of users which the alerts are sent to. </source> |   <source>Select the group of users which the alerts are sent to. </source> | ||||||
|  |   <target>选择一组用于发送警告的用户。</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="se630f2ccd39bf9e6"> | <trans-unit id="se630f2ccd39bf9e6"> | ||||||
|   <source>If no group is selected and 'Send notification to event user' is disabled the rule is disabled. </source> |   <source>If no group is selected and 'Send notification to event user' is disabled the rule is disabled. </source> | ||||||
|  |   <target>如果未选择组,并且“发送通知给事件用户”被禁用,则此规则被禁用。</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="s47966b2a708694e2"> | <trans-unit id="s47966b2a708694e2"> | ||||||
|   <source>Send notification to event user</source> |   <source>Send notification to event user</source> | ||||||
|  |   <target>发送通知给事件用户</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sd30f00ff2135589c"> | <trans-unit id="sd30f00ff2135589c"> | ||||||
|   <source>When enabled, notification will be sent to the user that triggered the event in addition to any users in the group above. The event user will always be the first user, to send a notification only to the event user enabled 'Send once' in the notification transport.</source> |   <source>When enabled, notification will be sent to the user that triggered the event in addition to any users in the group above. The event user will always be the first user, to send a notification only to the event user enabled 'Send once' in the notification transport.</source> | ||||||
|  |   <target>启用时,通知不仅会发送给触发事件的用户,还会发送到组中的任何用户。事件用户将总是第一个用户,要只向事件用户发送通知,则需要在通知传输中启用“发送一次”。</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sbd65aeeb8a3b9bbc"> | <trans-unit id="sbd65aeeb8a3b9bbc"> | ||||||
|   <source>Maximum registration attempts</source> |   <source>Maximum registration attempts</source> | ||||||
|  |   <target>最大注册尝试次数</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="s8495753cb15e8d8e"> | <trans-unit id="s8495753cb15e8d8e"> | ||||||
|   <source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source> |   <source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source> | ||||||
|  |   <target>允许的最大注册尝试次数。设置为 0 则不限制次数。</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  |   <target>此应用程序目前没有定义任何应用程序授权。</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
|  |   <target>以 <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/> 身份通过验证</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -359,7 +359,7 @@ | |||||||
|         <source>Recent events</source> |         <source>Recent events</source> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>代表 |         <target>代表 | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
| @ -7467,6 +7467,9 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|         <target>代表 |         <target>代表 | ||||||
|         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> |         <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target> | ||||||
|          |          | ||||||
| @ -5702,11 +5702,6 @@ doesn't pass when either or both of the selected options are equal or above the | |||||||
|         <source>Successfully created rule.</source> |         <source>Successfully created rule.</source> | ||||||
|         <target>已成功创建规则。</target> |         <target>已成功创建规则。</target> | ||||||
|          |          | ||||||
|       </trans-unit> |  | ||||||
|       <trans-unit id="sa55ee64c5c51df0f"> |  | ||||||
|         <source>Select the group of users which the alerts are sent to. If no group is selected the rule is disabled.</source> |  | ||||||
|         <target>选择一组用于发送警告的用户。如果未选择组,则此规则被禁用。</target> |  | ||||||
|          |  | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sffa171e11d4ae513"> |       <trans-unit id="sffa171e11d4ae513"> | ||||||
|         <source>Transports</source> |         <source>Transports</source> | ||||||
| @ -5742,11 +5737,6 @@ doesn't pass when either or both of the selected options are equal or above the | |||||||
|         <source>Notification rule(s)</source> |         <source>Notification rule(s)</source> | ||||||
|         <target>通知规则</target> |         <target>通知规则</target> | ||||||
|          |          | ||||||
|       </trans-unit> |  | ||||||
|       <trans-unit id="s5140d157642d7362"> |  | ||||||
|         <source>None (rule disabled)</source> |  | ||||||
|         <target>无(规则已禁用)</target> |  | ||||||
|          |  | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sd1146418b344f81f"> |       <trans-unit id="sd1146418b344f81f"> | ||||||
|         <source>Update Notification Rule</source> |         <source>Update Notification Rule</source> | ||||||
| @ -9242,10 +9232,6 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
|   <source>No app entitlements created.</source> |   <source>No app entitlements created.</source> | ||||||
|   <target>未创建应用程序授权。</target> |   <target>未创建应用程序授权。</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sdc8a8f29af6aa411"> |  | ||||||
|   <source>This application does currently not have any application entitlement defined.</source> |  | ||||||
|   <target>此应用程序目前没有定义任何应用程序授权。</target> |  | ||||||
| </trans-unit> |  | ||||||
| <trans-unit id="sf0bd204ce3fea1de"> | <trans-unit id="sf0bd204ce3fea1de"> | ||||||
|   <source>Create Entitlement</source> |   <source>Create Entitlement</source> | ||||||
|   <target>创建授权</target> |   <target>创建授权</target> | ||||||
| @ -9887,6 +9873,42 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| <trans-unit id="s4f820625804ed29b"> | <trans-unit id="s4f820625804ed29b"> | ||||||
|   <source>Re-authenticate with Plex</source> |   <source>Re-authenticate with Plex</source> | ||||||
|   <target>使用 Plex 重新验证身份</target> |   <target>使用 Plex 重新验证身份</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s0433d667ea6eec1a"> | ||||||
|  |   <source>The name of an invitation must be a slug: only lower case letters, numbers, and the hyphen are permitted here.</source> | ||||||
|  |   <target>邀请名称必须是一个 Slug:仅允许小写字母、数字和连字符。</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s2e9d5ea88f02ae68"> | ||||||
|  |   <source>Select the group of users which the alerts are sent to. </source> | ||||||
|  |   <target>选择一组用于发送警告的用户。</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="se630f2ccd39bf9e6"> | ||||||
|  |   <source>If no group is selected and 'Send notification to event user' is disabled the rule is disabled. </source> | ||||||
|  |   <target>如果未选择组,并且“发送通知给事件用户”被禁用,则此规则被禁用。</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s47966b2a708694e2"> | ||||||
|  |   <source>Send notification to event user</source> | ||||||
|  |   <target>发送通知给事件用户</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="sd30f00ff2135589c"> | ||||||
|  |   <source>When enabled, notification will be sent to the user that triggered the event in addition to any users in the group above. The event user will always be the first user, to send a notification only to the event user enabled 'Send once' in the notification transport.</source> | ||||||
|  |   <target>启用时,通知不仅会发送给触发事件的用户,还会发送到组中的任何用户。事件用户将总是第一个用户,要只向事件用户发送通知,则需要在通知传输中启用“发送一次”。</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="sbd65aeeb8a3b9bbc"> | ||||||
|  |   <source>Maximum registration attempts</source> | ||||||
|  |   <target>最大注册尝试次数</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s8495753cb15e8d8e"> | ||||||
|  |   <source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source> | ||||||
|  |   <target>允许的最大注册尝试次数。设置为 0 则不限制次数。</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|  |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  |   <target>此应用程序目前没有定义任何应用程序授权。</target> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
|  |   <target>以 <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/> 身份通过验证</target> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -445,7 +445,7 @@ | |||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="sc35581d9c1cd67ff"> |       <trans-unit id="sc35581d9c1cd67ff"> | ||||||
|         <source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source> |         <source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source> | ||||||
|          |          | ||||||
|       </trans-unit> |       </trans-unit> | ||||||
|       <trans-unit id="saf63a04c86018698"> |       <trans-unit id="saf63a04c86018698"> | ||||||
| @ -9203,6 +9203,9 @@ Bindings to groups/users are checked against the user of the event.</source> | |||||||
| </trans-unit> | </trans-unit> | ||||||
| <trans-unit id="sab4db6a3bd6abc1e"> | <trans-unit id="sab4db6a3bd6abc1e"> | ||||||
|   <source>This application does currently not have any application entitlements defined.</source> |   <source>This application does currently not have any application entitlements defined.</source> | ||||||
|  | </trans-unit> | ||||||
|  | <trans-unit id="s7225aacf0eee94d2"> | ||||||
|  |   <source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source> | ||||||
| </trans-unit> | </trans-unit> | ||||||
|     </body> |     </body> | ||||||
|   </file> |   </file> | ||||||
|  | |||||||
| @ -10,6 +10,10 @@ However, any flow can be executed via an API from anywhere, in fact that is what | |||||||
| Because the flow executor stores its state in the HTTP Session, so you need to ensure that cookies between flow executor requests are persisted. | Because the flow executor stores its state in the HTTP Session, so you need to ensure that cookies between flow executor requests are persisted. | ||||||
| ::: | ::: | ||||||
|  |  | ||||||
|  | :::info | ||||||
|  | Note that the HTTP session must be obtained as a cookie before `GET /api/v3/flows/executor/:slug` can be called. If you are using a JWT for authentication, you first have to obtain a session cookie via `GET /api/v3/flows/instances/:slug/execute/` before requesting `GET /api/v3/flows/executor/:slug`. | ||||||
|  | ::: | ||||||
|  |  | ||||||
| The main endpoint for flow execution is `/api/v3/flows/executor/:slug`. | The main endpoint for flow execution is `/api/v3/flows/executor/:slug`. | ||||||
|  |  | ||||||
| This endpoint accepts a query parameter called `query`, in which the flow executor sends the full query-string. | This endpoint accepts a query parameter called `query`, in which the flow executor sends the full query-string. | ||||||
|  | |||||||
| @ -110,6 +110,10 @@ If you have any questions or comments about this advisory: | |||||||
|  |  | ||||||
|     Include the new file in the `/website/sidebars.js` |     Include the new file in the `/website/sidebars.js` | ||||||
|  |  | ||||||
|  |     Push the branch to https://github.com/goauthentik/authentik-internal for CI to run and for reviews | ||||||
|  |  | ||||||
|  |     An image with the fix is built under `ghcr.io/goauthentik/internal-server` which can be made accessible to the reporter for testing | ||||||
|  |  | ||||||
| - Check with the original reporter that the fix works as intended | - Check with the original reporter that the fix works as intended | ||||||
| - Wait for GitHub to assign a CVE | - Wait for GitHub to assign a CVE | ||||||
| - Announce the release of the vulnerability via Mailing list and discord | - Announce the release of the vulnerability via Mailing list and discord | ||||||
| @ -136,7 +140,18 @@ We'll be publishing a security Issue (CVE-2022-xxxxx) and accompanying fix on _d | |||||||
|  |  | ||||||
| ### Creating a security release | ### Creating a security release | ||||||
|  |  | ||||||
| - On the date specified in the announcement, push the local `security/CVE-2022-xxxxx` branch into a PR, and squash merge it if the pipeline passes | - On the date specified in the announcement, retag the image from `authentik-internal` to the main image: | ||||||
|  |  | ||||||
|  |     ``` | ||||||
|  |     docker buildx imagetools create -t ghcr.io/goauthentik/server:xxxx.x ghcr.io/goauthentik/internal-server:gh-cve-2022-xxx | ||||||
|  |     docker buildx imagetools create -t ghcr.io/goauthentik/server:xxxx.x.x ghcr.io/goauthentik/internal-server:gh-cve-2022-xxx | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  |     Where xxxx.x is the version family and xxxx.x.x is the full version. | ||||||
|  |  | ||||||
|  |     This will make the fixed container image available instantly, while the full release is running on the main repository. | ||||||
|  |  | ||||||
|  | - Push the local `security/CVE-2022-xxxxx` branch into a PR, and squash merge it if the pipeline passes | ||||||
| - If the fix made any changes to the API schema, merge the PR to update the web API client | - If the fix made any changes to the API schema, merge the PR to update the web API client | ||||||
| - Cherry-pick the merge commit onto the version branch | - Cherry-pick the merge commit onto the version branch | ||||||
| - If the fix made any changes to the API schema, manually install the latest version of the API client in `/web` | - If the fix made any changes to the API schema, manually install the latest version of the API client in `/web` | ||||||
|  | |||||||
| @ -291,6 +291,10 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2025.4 | |||||||
| - lifecycle: fix arguments not being passed to worker command (cherry-pick #14574) (#14620) | - lifecycle: fix arguments not being passed to worker command (cherry-pick #14574) (#14620) | ||||||
| - sources/scim: fix all users being added to group when no members are given (cherry-pick #14645) (#14666) | - sources/scim: fix all users being added to group when no members are given (cherry-pick #14645) (#14666) | ||||||
|  |  | ||||||
|  | ## Fixed in 2025.4.3 | ||||||
|  |  | ||||||
|  | - security: fix CVE-2025-52553 (#15289) | ||||||
|  |  | ||||||
| ## API Changes | ## API Changes | ||||||
|  |  | ||||||
| #### What's New | #### What's New | ||||||
|  | |||||||
| @ -152,6 +152,22 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2025.6 | |||||||
| - web/elements: fix dual select without sortBy (cherry-pick #14977) (#14979) | - web/elements: fix dual select without sortBy (cherry-pick #14977) (#14979) | ||||||
| - web/elements: fix typo in localeComparator (cherry-pick #15054) (#15055) | - web/elements: fix typo in localeComparator (cherry-pick #15054) (#15055) | ||||||
|  |  | ||||||
|  | ## Fixed in 2025.6.3 | ||||||
|  |  | ||||||
|  | - ci: fix CodeQL failing on cherry-pick PRs (cherry-pick #15205) (#15206) | ||||||
|  | - ci: fix post-release e2e builds failing (cherry-pick #15082) (#15092) | ||||||
|  | - core: bump goauthentik/fips-python from 3.13.3-slim-bookworm-fips to 3.13.5-slim-bookworm-fips in 2025.6 (#15274) | ||||||
|  | - core: bump protobuf from 6.30.2 to v6.31.1 (cherry-pick #14894) (#15173) | ||||||
|  | - core: bump requests from 2.32.3 to v2.32.4 (cherry-pick #15129) (#15135) | ||||||
|  | - core: bump tornado from 6.4.2 to v6.5.1 (cherry-pick #15100) (#15116) | ||||||
|  | - core: bump urllib3 from 2.4.0 to v2.5.0 (cherry-pick #15131) (#15174) | ||||||
|  | - security: fix CVE-2025-52553 (cherry-pick #15289) (#15290) | ||||||
|  | - sources/ldap: fix sync on empty groups (cherry-pick #15158) (#15171) | ||||||
|  | - stages/user_login: fix session binding logging (#15175) | ||||||
|  | - web/elements: Add light mode custom css handling (cherry-pick #14944) (#15096) | ||||||
|  | - web/elements: typing error when variables are not converted to string (cherry-pick #15169) (#15222) | ||||||
|  | - web/user: fix infinite loop when no user settings flow is set (cherry-pick #15188) (#15192) | ||||||
|  |  | ||||||
| ## API Changes | ## API Changes | ||||||
|  |  | ||||||
| #### What's New | #### What's New | ||||||
|  | |||||||
							
								
								
									
										27
									
								
								website/docs/security/cves/CVE-2025-52553.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								website/docs/security/cves/CVE-2025-52553.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | # CVE-2025-52553 | ||||||
|  |  | ||||||
|  | _Reported by [SPIEGEL-Verlag](https://gruppe.spiegel.de)_ | ||||||
|  |  | ||||||
|  | ## Insufficient Session verification for Remote Access Control endpoint access | ||||||
|  |  | ||||||
|  | ### Summary | ||||||
|  |  | ||||||
|  | After authorizing access to a RAC endpoint, authentik creates a token which is used for a single connection and is sent to the client in the URL. This token is intended to only be valid for the session of the user who authorized the connection, however this check is currently missing. | ||||||
|  |  | ||||||
|  | ### Patches | ||||||
|  |  | ||||||
|  | authentik 2025.4.3 and 2025.6.3 fix this issue. | ||||||
|  |  | ||||||
|  | ### Impact | ||||||
|  |  | ||||||
|  | When for example using RAC during a screenshare, a malicious user could access the same session by copying the URL from the shown browser. | ||||||
|  |  | ||||||
|  | ### Workarounds | ||||||
|  |  | ||||||
|  | As a workaround it is recommended to decrease the duration a token is valid for (in the RAC Provider settings, set **Connection expiry** to `minutes=5` for example). We also recommend enabling the option **Delete authorization on disconnect**. | ||||||
|  |  | ||||||
|  | ### For more information | ||||||
|  |  | ||||||
|  | If you have any questions or comments about this advisory: | ||||||
|  |  | ||||||
|  | - Email us at [security@goauthentik.io](mailto:security@goauthentik.io). | ||||||
| @ -81,7 +81,7 @@ You can configure Actual Budget to authenticate users with OpenID Connect by mod | |||||||
|  |  | ||||||
| Alternatively, it is possible to configure OpenID Connect via the UI. | Alternatively, it is possible to configure OpenID Connect via the UI. | ||||||
|  |  | ||||||
|       1. Sign in to Actual Budget and select your budget by clicing its name. |       1. Sign in to Actual Budget and select your budget by clicking its name. | ||||||
|       2. In the top-left corner, click your budget name to open the dropdown and choose **Settings**. |       2. In the top-left corner, click your budget name to open the dropdown and choose **Settings**. | ||||||
|       3. Scroll down and select **Show advanced settings**, then enable **I understand the risks, show experimental features**. |       3. Scroll down and select **Show advanced settings**, then enable **I understand the risks, show experimental features**. | ||||||
|       4. Enable **OpenID authentication method**. |       4. Enable **OpenID authentication method**. | ||||||
|  | |||||||
| @ -48,7 +48,7 @@ To support the integration of BookStack with authentik, you need to create an ap | |||||||
|     - **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type. |     - **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type. | ||||||
|     - **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations. |     - **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations. | ||||||
|         - Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later. |         - Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later. | ||||||
|         - Set a `Strict` redirect URI to `https://bookstack.company/oidc/callback/`. |         - Set a `Strict` redirect URI to `https://bookstack.company/oidc/callback`. | ||||||
|         - Select any available signing key. |         - Select any available signing key. | ||||||
|     - **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/flows-stages/bindings/) (policy, group, or user) to manage the listing and access to applications on a user's **My applications** page. |     - **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/flows-stages/bindings/) (policy, group, or user) to manage the listing and access to applications on a user's **My applications** page. | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										164
									
								
								website/integrations/services/omada-controller/index.mdx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								website/integrations/services/omada-controller/index.mdx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,164 @@ | |||||||
|  | --- | ||||||
|  | title: Integrate with Omada Controller | ||||||
|  | sidebar_label: Omada Controller | ||||||
|  | support_level: community | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ## What is Omada Controller | ||||||
|  |  | ||||||
|  | > Omada Controller is a software platform used to centrally manage and monitor Omada networking devices like access points, switches, and routers. It provides a single interface for configuring, managing, and monitoring these devices, offering centralized control over your entire Omada network. | ||||||
|  | > | ||||||
|  | > -- https://www.omadanetworks.com/ | ||||||
|  |  | ||||||
|  | ## Preparation | ||||||
|  |  | ||||||
|  | The following placeholders are used in this guide: | ||||||
|  |  | ||||||
|  | - `authentik.company` is the FQDN of the authentik installation. | ||||||
|  |  | ||||||
|  | :::note | ||||||
|  | This documentation lists only the settings that you need to change from their default values. Be aware that any changes other than those explicitly mentioned in this guide could cause issues accessing your application. | ||||||
|  | ::: | ||||||
|  |  | ||||||
|  | ## authentik configuration | ||||||
|  |  | ||||||
|  | To support the integration of Omada Controller with authentik, you need to create property mappings, a group, and an application/provider pair in authentik. | ||||||
|  |  | ||||||
|  | ### Create property mappings in authentik | ||||||
|  |  | ||||||
|  | 1. Log in to authentik as an administrator, and open the authentik Admin interface. | ||||||
|  | 2. Navigate to **Customization** > **Property Mappings**, click **Create**, select **SAML Provider Property Mappings**, and click **Next**. | ||||||
|  | 3. Configure the first mapping for the user's _given name_ (first name): | ||||||
|  |     - **Name**: `givenname` | ||||||
|  |     - **SAML Attribute Name**: `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname` | ||||||
|  |     - **Friendly Name**: Leave blank | ||||||
|  |     - **Expression**: | ||||||
|  |  | ||||||
|  |     ```python | ||||||
|  |     return request.user.name.split(" ", 1)[0] | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  | 4. Click **Finish** to save. Then, repeat the process to create a mapping for the user's _surname_: | ||||||
|  |     - **Name**: `surname` | ||||||
|  |     - **SAML Attribute Name**: `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname` | ||||||
|  |     - **Friendly Name**: Leave blank | ||||||
|  |     - **Expression**: | ||||||
|  |  | ||||||
|  |     ```python | ||||||
|  |     return request.user.name.split(" ", 1)[-1] | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  | 5. Click **Finish** to save. Then, repeat the process to create a mapping for the user's _group memberships_: | ||||||
|  |     - **Name**: `usergroup_name` | ||||||
|  |     - **SAML Attribute Name**: `usergroup_name` | ||||||
|  |     - **Friendly Name**: Leave blank | ||||||
|  |     - **Expression**: | ||||||
|  |  | ||||||
|  |     ```python | ||||||
|  |     for group in user.ak_groups.all(): | ||||||
|  |         yield group.name | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  | 6. Click **Finish** to save. Finally, repeat the process to create a mapping for the user's _username_: | ||||||
|  |     - **Name**: `username` | ||||||
|  |     - **SAML Attribute Name**: `username` | ||||||
|  |     - **Friendly Name**: Leave blank | ||||||
|  |     - **Expression**: | ||||||
|  |  | ||||||
|  |     ```python | ||||||
|  |     return request.user.username | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  | 7. Click **Finish**. | ||||||
|  |  | ||||||
|  | ### Create a group in authentik | ||||||
|  |  | ||||||
|  | 1. Log in to authentik as an administrator and open the authentik Admin interface. | ||||||
|  | 2. Navigate to **Directory** > **Groups** and click **Create**. | ||||||
|  | 3. Set a name for the group (e.g. `Omada-admins`) and click **Create**. | ||||||
|  | 4. Click the name of the newly created group, then switch to the **Users** tab. | ||||||
|  | 5. Click **Add existing user**, select the user who needs Omada Controller administrator access, and click **Add**. | ||||||
|  |  | ||||||
|  | ### Create an application and provider in authentik | ||||||
|  |  | ||||||
|  | 1. Log in to authentik as an administrator, and open the authentik Admin interface. | ||||||
|  | 2. Navigate to **Applications** > **Applications** and click **Create with Provider** to create an application and provider pair. (Alternatively you can first create a provider separately, and then create the application and connect it with the provider.) | ||||||
|  |     - **Application**: provide a descriptive name, an optional group for the type of application, the policy engine mode, and optional UI settings. | ||||||
|  |         - Note the application slug, it will be required when filling out the **Identity provider SSO URL** later on. | ||||||
|  |     - **Choose a Provider type**: select **SAML Provider** as the provider type. | ||||||
|  |     - **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations. | ||||||
|  |         - **ACS URL**: | ||||||
|  |             - For Cloud Controllers: `https://aps1-omada-account.tplinkcloud.com/sso/saml/login/` | ||||||
|  |             - For Software/Hardware Controllers: `https://<controller_ip_address>:8043/sso/saml/login` | ||||||
|  |         - **Issuer**: | ||||||
|  |             - For Cloud Controllers: `https://omada.tplinkcloud.com/` | ||||||
|  |             - For Software and Hardware Controllers: `https://<controller_ip_address>:8043` | ||||||
|  |         - Set the **Service Provider Binding** to `Post`. | ||||||
|  |         - Under **Advanced protocol settings**: | ||||||
|  |             - Set an available signing certificate. | ||||||
|  |             - Set **NameID Property Mapping** to `authentik default SAML Mapping: UPN` | ||||||
|  |             - Under **Property mappings**: | ||||||
|  |                 - Select only the following **User Property Mappings**: | ||||||
|  |                     - `authentik default SAML Mapping: Email` | ||||||
|  |                     - `authentik default SAML Mapping: Name` | ||||||
|  |                     - `authentik default SAML Mapping: UPN` | ||||||
|  |                     - `givenname` | ||||||
|  |                     - `surname` | ||||||
|  |                     - `usergroup_name` | ||||||
|  |                     - `username` | ||||||
|  |     - **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/flows-stages/bindings/) (policy, group, or user) to manage the listing and access to applications on a user's **My applications** page. | ||||||
|  |  | ||||||
|  | 3. Click **Submit** to save the new application and provider. | ||||||
|  |  | ||||||
|  | ### Copy the metadata URL | ||||||
|  |  | ||||||
|  | 1. Log into authentik as an administrator, and open the authentik Admin interface. | ||||||
|  | 2. Navigate to **Applications** > **Providers** and click on the name of the newly created Omada Controller provider. | ||||||
|  | 3. Under **Metadata**, click the **Copy Download URL**. This metadata URL will be required in the next section. | ||||||
|  |  | ||||||
|  | ## Omada Controller configuration | ||||||
|  |  | ||||||
|  | 1. Log in to the Omada Controller. | ||||||
|  | 2. Navigate to **Global View** > **Settings** > **SAML SSO**, and then click **Add New SAML Connection**. | ||||||
|  | 3. Set **Identity Provider Name** to `authentik`. | ||||||
|  | 4. Select `Metadata URL` as the **Configuration Method**, and then paste the metadata URL that you copied from authentik. | ||||||
|  | 5. Click **Load Info**, and then click **Send**. | ||||||
|  | 6. In the **Actions** column, click on the **Details** button next to the newly created authentik SAML connection. | ||||||
|  | 7. Take note of the **Entity ID**, **Omada ID**, **Resource ID**, and then click **OK**. These values will be required in the next section. | ||||||
|  | 8. At the top right of the page, click **Go To SAML Role**, and then **Add New SAML Role**. | ||||||
|  | 9. Set the desired **SAML Role Name**, **Role**, **User Type**, and **Privileges** for the new SAML role. The **SAML Role Name** must match the name of the previously created authentik group. | ||||||
|  | 10. Click **Create**. | ||||||
|  |  | ||||||
|  | ## Encoding default relay state | ||||||
|  |  | ||||||
|  | The default relay state is generated by Base64-encoding a combination of the **Resource ID** and **Omada ID**, separated by an underscore (`_`). | ||||||
|  |  | ||||||
|  | You can generate the relay state value using one of the following methods: | ||||||
|  |  | ||||||
|  | ### Linux and macOS | ||||||
|  |  | ||||||
|  |     ```bash | ||||||
|  |     echo -n '<Resource_ID>_<Omada_ID>' | base64 --wrap=0 | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  | ### Windows (PowerShell): | ||||||
|  |  | ||||||
|  |     ```powershell | ||||||
|  |     [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('<Resource_ID>_<Omada_ID>')) | ||||||
|  |     ``` | ||||||
|  |  | ||||||
|  | ## Reconfigure authentik provider | ||||||
|  |  | ||||||
|  | 1. Log in to authentik as an administrator, and open the authentik Admin interface. | ||||||
|  | 2. Navigate to **Applications** > **Providers** and click the **Edit** icon next to the newly created Omada Controller provider. | ||||||
|  | 3. Set **Issuer** to the **Entity ID** value from Omada Controller. | ||||||
|  | 4. Under **Advanced protocol settings**, set **Default relay state** to the encoded value from the previous section. | ||||||
|  | 5. Click **Update** to save your changes. | ||||||
|  |  | ||||||
|  | ## Configuration verification | ||||||
|  |  | ||||||
|  | To verify that authentik is correctly integrated with Omada Controller, first log out of Omada Controller. Log in to authentik and click on the Omada Controller application in the application dashboard, and you should then be redirected to the Omada Controller dashboard. | ||||||
|  |  | ||||||
|  | ## Resources | ||||||
|  |  | ||||||
|  | - [Omada Networks Documentation - How to Configure SAML SSO on Omada Controller](https://www.omadanetworks.com/de/support/faq/4406/#_Toc193896083) | ||||||
| @ -34,7 +34,7 @@ To support the integration of Zulip with authentik, you need to create an applic | |||||||
| - **Choose a Provider type**: select **SAML Provider** as the provider type. | - **Choose a Provider type**: select **SAML Provider** as the provider type. | ||||||
| - **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations. | - **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations. | ||||||
|     - Set the **ACS URL** to `https://zulip.company/complete/saml/`. |     - Set the **ACS URL** to `https://zulip.company/complete/saml/`. | ||||||
|     - Set the **Issuer** to `https://zulip.company`. |     - Set the **Issuer** to `https://authentik.company`. | ||||||
|     - Set the **Service Provider Binding** to `Post`. |     - Set the **Service Provider Binding** to `Post`. | ||||||
|     - Under **Advanced protocol settings**, select an available signing certificate. |     - Under **Advanced protocol settings**, select an available signing certificate. | ||||||
| - **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/flows-stages/bindings/) (policy, group, or user) to manage the listing and access to applications on a user's **My applications** page. | - **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/flows-stages/bindings/) (policy, group, or user) to manage the listing and access to applications on a user's **My applications** page. | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	