Compare commits

..

172 Commits

Author SHA1 Message Date
a8134e26c8 website/docs: re-add gtag (cherry-pick #15334) (#15335)
website/docs: re-add gtag (#15334)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-07-01 19:33:23 +02:00
1c637bc0d1 web/elements: fix table search not resetting page when query changes (cherry-pick #15324) (#15326)
web/elements: fix table search not resetting page when query changes (#15324)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-07-01 17:18:43 +02:00
8af668a9d2 website: changelog for security releases (#15291)
* website: changelog for security releases

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

* format

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	website/docs/releases/2025/v2025.4.md
2025-06-27 15:43:14 +02:00
96266e2e2b release: 2025.6.3 2025-06-27 15:34:53 +02:00
65373ab217 security: fix CVE-2025-52553 (cherry-pick #15289) (#15290)
security: fix CVE-2025-52553 (#15289)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-27 15:30:42 +02:00
88590e1134 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 goauthentik/fips-python from 3.13.3-slim-bookworm-fips to 3.13.4-slim-bookworm-fips in 2025.6

Signed-off-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-06-27 00:43:45 +02:00
f6ff31e3de web/elements: typing error when variables are not converted to string (cherry-pick #15169) (#15222)
web/elements: typing error when variables are not converted to string (#15169)

fix: typing error when variables are not converted to string

Co-authored-by: Leandro4002 <leandro262009@gmail.com>
Co-authored-by: leandro.saraiva <leandro.saraiva@adonite.com>
2025-06-24 20:24:49 +02:00
cbc14524b3 website/docs: Add steps to troubleshoot /initial-setup/ (cherry-pick #15011) (#15210)
website/docs: Add steps to troubleshoot /initial-setup/ (#15011)

* Add steps to troubleshoot /initial-setup/

* fix linting

* Apply suggestions from code review




* Apply suggestions from code review




* add email part

* Apply suggestions from code review




* Apply suggestions from code review




* change wording

---------

Signed-off-by: Marcelo Elizeche Landó <marce@melizeche.com>
Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-06-24 00:43:56 +02:00
d807038d05 website/docs: fix note at end of rac credentials prompt (cherry-pick #14909) (#15208)
website/docs: fix note at end of rac credentials prompt (#14909)

* Fixes note section at end of document

* tweak to bump build

---------

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-23 22:17:59 +02:00
ba131a50ba website/docs: add credentials prompt for rac doc (cherry-pick #14840) (#15207)
website/docs: add credentials prompt for rac doc (#14840)

* Adds document

* Typo

* Clarified RAC endpoint sentence based on Tana's suggestion.

* Update website/docs/add-secure-apps/providers/rac/rac_credentials_prompt.md




* Small wording improvements

* Added connection security type information

* A word

* Added to sidebar

* Update website/docs/add-secure-apps/providers/rac/rac_credentials_prompt.md




* Applied suggestions from Tana

* Update website/docs/add-secure-apps/providers/rac/rac_credentials_prompt.md




---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-23 21:15:58 +02:00
0e37a66751 ci: fix CodeQL failing on cherry-pick PRs (cherry-pick #15205) (#15206)
* ci: fix CodeQL failing on cherry-pick PRs (#15205)

* fix build

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-23 20:41:33 +02:00
57c220dfc2 website: split integrations partially (#15076)
* config for split

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

* update alllll the links

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

* add redirect

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

* add separate job for integrations build

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

* Update website/netlify.toml

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jens L. <jens@beryju.org>

* Revert "update alllll the links"

This reverts commit 872c5870a8.

* absolute relative URLs only

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

* but use a plugin to rewrite them

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

* fix external URL regex

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

* make rewrite plugin more re-usable

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

* fix the reverse links

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

* lint

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

* fix root redirect

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

* fix rediret

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

* fix root redirect

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

* fix redirect

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	.github/workflows/ci-website.yml
#	website/docusaurus.config.esm.mjs
2025-06-23 15:53:08 +02:00
7339a22080 web/user: fix infinite loop when no user settings flow is set (cherry-pick #15188) (#15192)
web/user: fix infinite loop when no user settings flow is set (#15188)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-23 01:50:38 +02:00
8c2d72affe website/docs: fix egregious maintenance fail (cherry-pick #15176) (#15180)
website/docs: fix egregious maintenance fail (#15176)

fix egregious maintenance fail

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-22 00:58:35 +02:00
9c31e08bd9 website/docs: fixes misplaced sentence (cherry-pick #14998) (#15182)
website/docs: fixes misplaced sentence (#14998)

fixes misplaced sentence

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-22 00:58:16 +02:00
805b9afa80 stages/user_login: fix session binding logging (#15175)
* add tests

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

* fix logging

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

* update test db?

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

* ah there we go; fix mmdb not being reloaded with test settings

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
# Conflicts:
#	authentik/root/test_runner.py
2025-06-21 00:23:10 +02:00
bc809bae1e core: bump protobuf from 6.30.2 to v6.31.1 (cherry-pick #14894) (#15173)
Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-06-20 14:50:10 +02:00
66773b69ab core: bump urllib3 from 2.4.0 to v2.5.0 (cherry-pick #15131) (#15174)
Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-06-20 14:49:59 +02:00
c149701501 sources/ldap: fix sync on empty groups (cherry-pick #15158) (#15171)
Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
fix sync on empty groups (#15158)
2025-06-20 14:25:55 +02:00
b13b51b73a core: bump requests from 2.32.3 to v2.32.4 (cherry-pick #15129) (#15135)
core: bump requests from 2.32.3 to v2.32.4 (#15129)

Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-06-19 00:23:05 +02:00
ee30cc1ede core: bump tornado from 6.4.2 to v6.5.1 (cherry-pick #15100) (#15116)
core: bump tornado from 6.4.2 to v6.5.1 (#15100)

Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-06-18 18:48:02 +02:00
de095f4a10 web/elements: Add light mode custom css handling (cherry-pick #14944) (#15096)
web/elements: Add light mode custom css handling (#14944)

* fix(ui): Add light mode custom css handling



* Update Base.ts



---------

Signed-off-by: CodeMax IT Solutions Pvt. Ltd. <137166088+cdmx1@users.noreply.github.com>
Co-authored-by: CodeMax IT Solutions Pvt. Ltd. <137166088+cdmx1@users.noreply.github.com>
2025-06-17 20:31:08 +02:00
abf3aa3a7f ci: fix post-release e2e builds failing (cherry-pick #15082) (#15092)
ci: fix post-release e2e builds failing (#15082)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-17 09:37:26 +02:00
3ebae72a76 website/docs: add more to style guide (cherry-pick #14797) (#15077)
website/docs: add more to style guide (#14797)

* lists and variables

* lists and variables

* tweaks

* kens edit

---------

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-16 22:15:37 +02:00
b6b47b669e release: 2025.6.2 2025-06-16 18:20:22 +02:00
8422568c42 website/docs: release notes for 2025.6.2 (cherry-pick #15065) (#15069)
website/docs: release notes for `2025.6.2` (#15065)

* website/docs: release notes for `2025.6.2`

* fixup! website/docs: release notes for `2025.6.2`

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2025-06-16 18:19:24 +02:00
9973064f50 core: fix transaction test case (cherry-pick #15021) (#15070)
* core: fix transaction test case (#15021)

* move patched ct to root

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

* use our transaction test case as base

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

* fix...?

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

* well apparently that works

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

---------

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

* fixup! core: fix transaction test case (#15021)

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-16 17:55:12 +02:00
4fea65f5cc website/docs: remove commented out config options (cherry-pick #15064) (#15067)
website/docs: remove commented out config options (#15064)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-16 16:56:45 +02:00
784446a47d website/docs: correct minor version in release notes (cherry-pick #15012) (#15068)
website/docs: correct minor version in release notes (#15012)

Signed-off-by: Zeik0s <35345686+Zeik0s@users.noreply.github.com>
Co-authored-by: Zeik0s <35345686+Zeik0s@users.noreply.github.com>
2025-06-16 16:47:44 +02:00
516bc65fc4 web/elements: fix typo in localeComparator (cherry-pick #15054) (#15055)
web/elements: fix typo in localeComparator (#15054)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-16 01:57:26 +02:00
efb59adeff providers/rac: fixes prompt data not being merged with connection_settings (cherry-pick #15037) (#15038)
providers/rac: fixes prompt data not being merged with connection_settings (#15037)

* Fixes line that pulls in prompt data

* fallback to old settings



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-06-13 23:28:44 +02:00
43a2ad66f0 website/docs: also hide the postgres pool_options setting (cherry-pick #15023) (#15032)
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-06-13 15:40:49 +02:00
ec0c59f1fc core: bump django from 5.1.10 to 5.1.11 (cherry-pick #14997) (#15010)
core: bump django from 5.1.10 to 5.1.11 (#14997)

Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-06-11 18:25:26 +02:00
8f80072321 core: bump django from 5.1.9 to 5.1.10 (cherry-pick #14951) (#15008)
core: bump django from 5.1.9 to 5.1.10 (#14951)

bump django to 5.1.10

Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-06-11 18:09:04 +02:00
33f95c837b brands: fix custom_css being escaped (cherry-pick #14994) (#14996)
brands: fix custom_css being escaped (#14994)

* brands: fix custom_css being escaped



* escape adequately



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-10 17:21:22 +02:00
43637b8a75 internal/outpost: fix incorrect usage of golang SHA API (cherry-pick #14981) (#14982)
internal/outpost: fix incorrect usage of golang SHA API (#14981)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-10 00:28:20 +02:00
7a4518be26 web/elements: fix dual select without sortBy (cherry-pick #14977) (#14979)
web/elements: fix dual select without sortBy (#14977)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-09 19:48:19 +02:00
b94fb53821 stages/email: Only attach logo to email if used (cherry-pick #14835) (#14969)
stages/email: Only attach logo to email if used (#14835)

* Only attach logo to email if used

* Fix MIME logo attachment to adhere to standard

* format, fix web



* not tuple



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Christian Elsen <chriselsen@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-06-09 03:53:51 +02:00
2be5c9633b website/docs: add 2025.6.1 release notes (cherry-pick #14948) (#14949)
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-06-06 17:28:58 +02:00
e729e42595 release: 2025.6.1 2025-06-06 16:55:05 +02:00
01d591b84e root: fix bumpversion
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-06-06 16:53:26 +02:00
dd08e1bf66 providers/proxy: add option to override host header with property mappings (cherry-pick #14927) (#14945)
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-06 15:27:10 +02:00
150705f221 web/user: fix user settings flow not loading (cherry-pick #14911) (#14930)
web/user: fix user settings flow not loading (#14911)

* web/user: fix user settings flow not loading



* fix



* unrelated fix: fix select caret color in dark theme



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-06-05 23:36:40 +02:00
6b39f6495e tenants: fix tenant aware celery scheduler (cherry-pick #14921) 2025-06-05 15:15:34 +02:00
639c57245b website/docs: rotate supported versions: 2025.6 (cherry-pick #14856) (#14906)
website/docs: rotate supported versions: `2025.6` (#14856)

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2025-06-04 18:46:58 +02:00
730600aea4 website/integrations: tailscale (cherry-pick #14499) (#14908)
website/integrations: tailscale (#14499)

* init

* wording

* lint

* Update website/integrations/services/tailscale/index.md



* Dewi's suggestions

* still mention that its a placeholder

* fix



* Update website/integrations/services/tailscale/index.md




* mv to end



* indent

* Update website/integrations/services/tailscale/index.md




* Update website/integrations/services/tailscale/index.md



* tweak to bump build

* another tweak to bump build

---------

Signed-off-by: Dominic R <dominic@sdko.org>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-04 18:37:53 +02:00
e15ce5a3f0 website/release notes: add tailscale to new integrations (cherry-pick #14859) (#14877)
website/release notes: add tailscale to new integrations (#14859)

* website/release notes: add tailscale to new integrations

### What

Adds Tailscale to the list of new integrations this release as it was merged like 5 minutes ago and technically 2025.6 isn't released just yet



* tweaks to bump build

---------

Signed-off-by: Dominic R <dominic@sdko.org>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-04 17:06:01 +02:00
1fc91b004b website/releases: order new integrations alphabetically (cherry-pick #14850) (#14876)
website/releases: order new integrations alphabetically (#14850)

### What

Orders the 2025.6 release note's new integrations alphabetically. It just bothers me.

Signed-off-by: Dominic R <dominic@sdko.org>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-06-04 17:05:33 +02:00
644705e6fe release: 2025.6.0 2025-06-03 22:04:09 +02:00
ff8ef523db website/docs: finalize release notes for 2025.6 (cherry-pick #14854) (#14855)
website/docs: finalize release notes for `2025.6` (#14854)

* remove internal changes from release notes

* add late additions to release notes

* remove release candidate notice from `2025.6`

* rotate supported versions

* rotate releases in sidebar

* Revert "rotate supported versions"

This reverts commit eea9d03e1d.

I'd like to do the release tonight, but I can't merge this because it
needs a review from @teams/security. I'll open a separate PR for it.

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2025-06-03 22:01:40 +02:00
1051dd19ea providers/rac: apply ConnectionToken scoped-settings last (cherry-pick #14838) (#14853)
providers/rac: apply ConnectionToken scoped-settings last (#14838)

* providers/rac: apply ConnectionToken scoped-settings last



* fix tests



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-03 21:26:13 +02:00
04cb4fd267 lib/sync: fix static incorrect label of pages (cherry-pick #14851) (#14852)
lib/sync: fix static incorrect label of pages (#14851)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-03 21:26:09 +02:00
da9508f839 website/docs: add LDAP docs for forward deletion and memberUid (cherry-pick #14814) (#14848)
website/docs: add LDAP docs for forward deletion and `memberUid` (#14814)

* website/docs: add LDAP docs for forward deletion and `memberUid`

* reword LDAP docs



---------

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-06-03 19:31:04 +02:00
841a286a25 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (cherry-pick #14801) (#14847)
stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#14801)

* stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs



* replace removed device type in tests

Android Authenticator with SafetyNet Attestation was removed from
blob.jwt in the previous commit

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-06-03 19:30:56 +02:00
63c48d7b99 core: bump goauthentik.io/api/v3 from 3.2025041.2 to 3.2025041.4 (cherry-pick #14809) (#14846)
core: bump goauthentik.io/api/v3 from 3.2025041.2 to 3.2025041.4 (#14809)

Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025041.2 to 3.2025041.4.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Changelog](https://github.com/goauthentik/client-go/blob/main/model_version_history.go)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2025041.2...v3.2025041.4)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-version: 3.2025041.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-03 19:30:14 +02:00
5994fd2c61 core, web: update translations (cherry-pick #14800) (#14845)
core, web: update translations (#14800)

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-06-03 19:30:06 +02:00
5f745e682e website/integrations: Update Zammad SAML Instructions (cherry-pick #14774) (#14844)
website/integrations: Update Zammad SAML Instructions (#14774)

* Update Zammad SAML Instructions

I just configured Zammad 6.4.1 to work with Authentik 2025.4.1. There seem to have been some changes since these instructions were written. The Name ID Format cannot be left blank. The SSO URL and the logout URL were incorrect. I was getting an Error 422 from Zammad until I turned on signing assertions, so I conclude that is required and I wrote instructions for that. I saw some discussion online elsewhere that the `----BEGIN` and `---END` lines should be removed. I tested it both ways and it worked both ways. I wrote the instructions to keep those lines in because it seemed simplest and most intuitive.



* Incorporate separate instructions for certificate file




* Incorporate simplified copy/paste instructions




* Incoporate formatting change




* Incorporate formatting changes




* Removed reference to custom properties

* Capitalisation




* Formatting




* Formatting




* Updated language




* Update website/integrations/services/zammad/index.md




* Update website/integrations/services/zammad/index.md




* tweak to bump build

* bump build

* use bold font for UI labels

* my typo

* capitalization fix

---------

Signed-off-by: Paco Hope <pacohope@users.noreply.github.com>
Co-authored-by: Paco Hope <pacohope@users.noreply.github.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-06-03 19:29:59 +02:00
6f1b16e7f9 website/integrations: remove trailing slash from budibase redirect (cherry-pick #14823) (#14843)
website/integrations: remove trailing slash from budibase redirect (#14823)

Removes trailing slash from redirect

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-06-03 19:29:51 +02:00
57bce19e7a website/integrations: update cloudflare access callback url (cherry-pick #14807) (#14842)
website/integrations: update cloudflare access callback url (#14807)

Update CLoudflare Access index.md

The callback URL had a trailing / that breaks the callback URL being matched by a strict policy.

Signed-off-by: terafirmanz <53923271+terafirmanz@users.noreply.github.com>
Co-authored-by: terafirmanz <53923271+terafirmanz@users.noreply.github.com>
2025-06-03 19:29:40 +02:00
850c5d5a45 website/docs: remove fluff from release notes 2025.6 (cherry-pick #14819) (#14820)
remove fluff from release notes 2025.6 (#14819)

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-06-03 15:21:51 +02:00
8b7d11f94c web: minor design tweaks (cherry-pick #14803) (#14804)
web: minor design tweaks (#14803)

* fix spacing between header and page desc



* fix icon alignment



* fallback text when we dont have a user yet



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-06-01 23:15:08 +02:00
45737909f6 release: 2025.6.0-rc1 2025-05-31 00:44:04 +02:00
4c5fe84f92 website: release notes for 2025.6 (#14703)
* release notes for 2025.6: first pass

* release notes for 2025.6: second pass

* list new integration docs

* reword LDAP forward deletions

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

* fix typo

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

* add Komodo

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

* don't do sidebar stuff just yet

whoops

* generate boilerplate

* release notes for 2025.6: third pass

* add CloudFormation

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

---------

Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-31 00:12:12 +02:00
5faa224c81 docs/troubleshooting: cleanup upgrade instructions for postgres k8s (#14773)
* docs/troubleshooting: cleanup upgrade instructions for postgres k8s

* website/troubleshooting: upgrade pg on k8s: use lowercase for headers

* Update website/docs/troubleshooting/postgres/upgrade_kubernetes.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/troubleshooting/postgres/upgrade_kubernetes.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/troubleshooting/postgres/upgrade_kubernetes.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/troubleshooting/postgres/upgrade_kubernetes.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/troubleshooting/postgres/upgrade_kubernetes.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/troubleshooting/postgres/upgrade_kubernetes.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/troubleshooting/postgres/upgrade_kubernetes.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* bump build

* tweak

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-05-30 14:06:00 -05:00
736da3abef providers/scim: allow for specifying custom SCIM schemas for users and groups (#14794)
* providers/scim: allow for specifying custom SCIM schemas for users and groups

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

* fix lint

* fix broken tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-05-30 20:08:28 +02:00
52d90f8d3b website/docs: Change wording in the upgrade guidelines (#14793)
* Change wording in the upgrade guidelines

* Update website/docs/install-config/upgrade.mdx

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Marcelo Elizeche Landó <marce@melizeche.com>

* fix linting

---------

Signed-off-by: Marcelo Elizeche Landó <marce@melizeche.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-05-30 19:47:47 +02:00
7b812de977 web: bump API Client version (#14795)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-05-30 19:19:58 +02:00
a4bd2cc263 website/integrations: add komodo (#14790)
* Add doc and update sidebar

* WIP

* Finished Komodo configuration steps

* Applied suggestions from Dominic

* Missing indentation

* Update website/integrations/services/komodo/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Applied Tana's suggestions

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-05-30 17:10:03 +00:00
14038ba8d2 website/docs: configuration: remove deprecated key for session storage location (#14431)
* website/docs: configuration: remove deprecated key for session storage location

Signed-off-by: Dominic R <dominic@sdko.org>

* Update default.yml

Signed-off-by: Dominic R <dominic@sdko.org>

* cve fix

Signed-off-by: Dominic R <dominic@sdko.org>

* Update CVE-2025-29928.md

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dominic R <dominic@sdko.org>

* add

* Update website/docs/security/cves/CVE-2025-29928.md

Signed-off-by: Dominic R <dominic@sdko.org>

* Update website/docs/security/cves/CVE-2025-29928.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/install-config/configuration/configuration.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/install-config/configuration/configuration.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/security/cves/CVE-2025-29928.md

Signed-off-by: Dominic R <dominic@sdko.org>

* Update website/docs/security/cves/CVE-2025-29928.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/security/cves/CVE-2025-29928.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/security/cves/CVE-2025-29928.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* bump build

---------

Signed-off-by: Dominic R <dominic@sdko.org>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-05-30 12:05:04 -05:00
eaff59b6b0 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#14780)
Translate locale/en/LC_MESSAGES/django.po in zh_CN

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-30 18:43:10 +02:00
cb702ca07a translate: Updates for file web/xliff/en.xlf in zh_CN (#14781)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-30 18:42:49 +02:00
cb0bfb0dad translate: Updates for file web/xliff/en.xlf in zh-Hans (#14782)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-30 18:42:35 +02:00
bf46d5c916 stages/user_login: remove success message (#13775) 2025-05-30 16:38:44 +00:00
59e686c8b9 sources/ldap: add user_membership_attribute (#14784) 2025-05-30 18:34:13 +02:00
9e736f2838 website: use "administrator" instead of "admin" for Admin interface (#14771)
* website: use "administrator" instead of "admin" for Admin interface

* website: some manual touches

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-30 09:29:30 -05:00
c2dd3d9c1b website/docs: update user ref doc with parent group example (#14779)
* Adds example

* Update website/docs/users-sources/user/user_ref.mdx

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Small updates

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-30 08:45:33 -05:00
42302d3187 core: Migrate permissions before deleteing OldAuthenticatedSession (#14788)
* add migrate_permissions_before_delete to authentik_core 0047 migration

* fix linting

* new approach

* fixup! new approach

---------

Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-05-30 15:43:45 +02:00
20ccabf3ec web: Fix issue where dual select type is not specific. (#14783) 2025-05-30 11:30:47 +02:00
8f939fa577 website: fix incorrect usage of "login to" + "log into" vs "log in to" (#14772) 2025-05-29 09:23:19 -05:00
2519bcef89 website/integrations: move resource section to end of documents (#14668)
Moves the resource section to the end of each document

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
2025-05-29 12:42:48 +01:00
3e3615a859 website/docs: add docs for MTLS Stage (#14571)
* website/docs: add docs for MTLS Stage

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

* update

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

* update docs

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

* Apply suggestions from code review

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>

* Apply suggestions from code review

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Jens L. <jens@beryju.org>

* Apply suggestions from code review

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Jens L. <jens@beryju.org>

* update brand docs

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

* remove code changes

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

* fix build

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

* reword

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

* Update website/docs/add-secure-apps/flows-stages/stages/mtls/index.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/add-secure-apps/flows-stages/stages/mtls/index.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-28 19:34:58 +00:00
79e82c8dc9 website/integrations: add pangolin (#14614)
* Adds pangolin integration doc and updates the integrations sidebar.

* Added pangolin instructions

* Applied fixes based on review

* Fixed signing key line

* Added missing .

* Missing .

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/pangolin/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-28 14:01:53 -05:00
ccd4432e1f website/integrations: add filerise (#14610)
* Added filerise doc and updated integrations sidebar

* WIP

* Completed filerise instructions

* Minor wording fixes

* Applied suggestions from Dominic

* Clarified admin icon step.

* Update website/integrations/services/filerise/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/filerise/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Missing .

* Update website/integrations/services/filerise/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/filerise/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-28 14:00:03 -05:00
b3137f5307 website/docs: spell out administrator in service template (#14770)
* spell out administrator

* tweak to bump build checks

---------

Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-05-28 13:26:41 -05:00
2591ed9840 web/flows: update default flow background (#14769)
* web/flows: update default flow background

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

* Optimised images with calibre/image-actions

* update image

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

* Optimised images with calibre/image-actions

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-05-28 19:05:36 +02:00
b3e89ef570 website/integrations: add stripe (#14618)
* Adds almost completed Stripe integration doc and updated integration sidebar

* Minor update to Stripe config section

* Added stripe instructions

* Typo

* Typo

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/stripe/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/stripe/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/stripe/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/stripe/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-28 11:29:25 -05:00
45b48c5cd6 core, web: update translations (#14766)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-05-28 13:57:15 +00:00
1eefd834fc web: fix lock file once again yay JS (#14765) 2025-05-28 15:22:52 +02:00
4cc6ed97c5 translate: Updates for file web/xliff/en.xlf in tr [Manual Sync] (#14745)
Translate web/xliff/en.xlf in tr [Manual Sync]

89% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'tr'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 15:22:14 +02:00
bb55d9b3de translate: Updates for file locale/en/LC_MESSAGES/django.po in pt_PT [Manual Sync] (#14764)
Translate django.po in pt_PT [Manual Sync]

60% of minimum 60% translated source file: 'django.po'
on 'pt_PT'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 13:16:20 +00:00
3972afb865 translate: Updates for file locale/en/LC_MESSAGES/django.po in es [Manual Sync] (#14748)
Translate django.po in es [Manual Sync]

92% of minimum 60% translated source file: 'django.po'
on 'es'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 13:15:13 +00:00
04a013cc1b translate: Updates for file locale/en/LC_MESSAGES/django.po in pt_BR [Manual Sync] (#14750)
Translate django.po in pt_BR [Manual Sync]

75% of minimum 60% translated source file: 'django.po'
on 'pt_BR'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 13:10:28 +00:00
fb396f7737 translate: Updates for file web/xliff/en.xlf in it [Manual Sync] (#14744)
Translate web/xliff/en.xlf in it [Manual Sync]

99% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'it'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:50:23 +00:00
cf120ff3ff translate: Updates for file locale/en/LC_MESSAGES/django.po in pt [Manual Sync] (#14761)
Translate django.po in pt [Manual Sync]

98% of minimum 60% translated source file: 'django.po'
on 'pt'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:40:50 +00:00
3e4923d52e translate: Updates for file locale/en/LC_MESSAGES/django.po in ru [Manual Sync] (#14763)
Translate django.po in ru [Manual Sync]

87% of minimum 60% translated source file: 'django.po'
on 'ru'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:40:04 +00:00
01793088f0 translate: Updates for file locale/en/LC_MESSAGES/django.po in nl [Manual Sync] (#14760)
Translate django.po in nl [Manual Sync]

78% of minimum 60% translated source file: 'django.po'
on 'nl'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:39:28 +00:00
e2bf2ec2cc translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_TW [Manual Sync] (#14756)
Translate django.po in zh_TW [Manual Sync]

77% of minimum 60% translated source file: 'django.po'
on 'zh_TW'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:38:49 +00:00
4dfbe28709 translate: Updates for file locale/en/LC_MESSAGES/django.po in fi [Manual Sync] (#14758)
Translate django.po in fi [Manual Sync]

91% of minimum 60% translated source file: 'django.po'
on 'fi'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:38:08 +00:00
b2021a7191 translate: Updates for file web/xliff/en.xlf in zh_CN [Manual Sync] (#14752)
Translate web/xliff/en.xlf in zh_CN [Manual Sync]

99% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:37:55 +00:00
81e5fb0c18 translate: Updates for file web/xliff/en.xlf in ru [Manual Sync] (#14751)
Translate web/xliff/en.xlf in ru [Manual Sync]

88% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'ru'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:37:49 +00:00
a2a2d940a8 translate: Updates for file web/xliff/en.xlf in cs_CZ [Manual Sync] (#14754)
Translate web/xliff/en.xlf in cs_CZ [Manual Sync]

60% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'cs_CZ'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:37:34 +00:00
c034930219 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN [Manual Sync] (#14762)
Translate django.po in zh_CN [Manual Sync]

99% of minimum 60% translated source file: 'django.po'
on 'zh_CN'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:37:02 +00:00
da3dc51d87 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans [Manual Sync] (#14757)
Translate django.po in zh-Hans [Manual Sync]

99% of minimum 60% translated source file: 'django.po'
on 'zh-Hans'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:36:27 +00:00
d217a39513 translate: Updates for file locale/en/LC_MESSAGES/django.po in it [Manual Sync] (#14759)
Translate django.po in it [Manual Sync]

98% of minimum 60% translated source file: 'django.po'
on 'it'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:34:42 +00:00
7729a9317c translate: Updates for file locale/en/LC_MESSAGES/django.po in tr [Manual Sync] (#14755)
Translate django.po in tr [Manual Sync]

88% of minimum 60% translated source file: 'django.po'
on 'tr'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:33:28 +00:00
be5f5dd3f0 translate: Updates for file locale/en/LC_MESSAGES/django.po in de [Manual Sync] (#14753)
Translate django.po in de [Manual Sync]

95% of minimum 60% translated source file: 'django.po'
on 'de'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:32:45 +00:00
bed8d5da4b translate: Updates for file web/xliff/en.xlf in zh-Hans [Manual Sync] (#14746)
Translate en.xlf in zh-Hans [Manual Sync]

99% of minimum 60% translated source file: 'en.xlf'
on 'zh-Hans'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:31:11 +00:00
4f70f84e80 translate: Updates for file locale/en/LC_MESSAGES/django.po in ko [Manual Sync] (#14749)
Translate django.po in ko [Manual Sync]

65% of minimum 60% translated source file: 'django.po'
on 'ko'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:30:55 +00:00
97b8551866 translate: Updates for file web/xliff/en.xlf in fi [Manual Sync] (#14742)
Translate web/xliff/en.xlf in fi [Manual Sync]

93% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'fi'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:29:45 +00:00
9a0b67e700 translate: Updates for file web/xliff/en.xlf in zh_TW [Manual Sync] (#14747)
Translate web/xliff/en.xlf in zh_TW [Manual Sync]

70% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'zh_TW'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:28:51 +00:00
97e4c89cec translate: Updates for file web/xliff/en.xlf in nl [Manual Sync] (#14743)
Translate web/xliff/en.xlf in nl [Manual Sync]

66% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'nl'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:28:28 +00:00
65aedde8f7 translate: Updates for file web/xliff/en.xlf in pl [Manual Sync] (#14740)
Translate web/xliff/en.xlf in pl [Manual Sync]

84% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'pl'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:28:09 +00:00
17450f23bf translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#14738)
* Translate locale/en/LC_MESSAGES/django.po in fr

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'fr'.

* Translate locale/en/LC_MESSAGES/django.po in fr

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'fr'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:27:51 +00:00
ab3ad6b7fd translate: Updates for file web/xliff/en.xlf in fr [Manual Sync] (#14739)
Translate web/xliff/en.xlf in fr [Manual Sync]

100% translated source file: 'web/xliff/en.xlf'
on 'fr'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:27:35 +00:00
45bc3cbd41 translate: Updates for file web/xliff/en.xlf in de [Manual Sync] (#14741)
Translate web/xliff/en.xlf in de [Manual Sync]

71% of minimum 60% translated source file: 'web/xliff/en.xlf'
on 'de'.

Sync of partially translated files: 
untranslated content is included with an empty translation 
or source language content depending on file format

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-05-28 12:27:15 +00:00
9c1bcac6af web: bump API Client version (#14736)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-05-28 12:23:48 +00:00
0a133265c5 core, web: update translations (#14737)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-05-28 11:50:02 +00:00
57f25a97c9 providers/ldap: retain binder and update users instead of re-creating (#14735)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-05-28 13:43:35 +02:00
8f32242787 ESBuild Plugin: Setup and usage docs. (#14720)
* Prep readme for Typedoc. Clean up metadata.

* Add license.

* Ignore generated readme.

* Flesh out TypeDoc.

* Flesh out copy, usage.

* web: Update package-lock.
2025-05-28 11:35:53 +00:00
c4bb19051d sources/ldap: add forward deletion option (#14718)
* sources/ldap: add forward deletion option

* remove unnecessary `blank=True`

* clarify `validated_by` `help_text`

* add indices to `validated_by`

* factor out `get_identifier` everywhere and `get_attributes`

I don't know what that additional `in` check is for, but I'm not about
to find out.

* add tests for known good user and group

* fixup! add tests for known good user and group

* fixup! add tests for known good user and group
2025-05-28 13:22:59 +02:00
10f4fae711 stages/email: fix email scanner voiding token (#14325)
* stages/email: fix email scanner voiding flow token

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

* misc

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

* improve consent stage error handling and testing

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

* draw the rest of the owl

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

* add e2e test

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

* fix tests

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

* fix

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

* idk why this is broken now?

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

* fix other e2e test

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

* fix the other test too

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-05-28 13:09:30 +02:00
2d9eab3f60 web/admin: fix permissions modal button missing for PolicyBindings and FlowStageBindings (#14619)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-05-28 13:08:18 +02:00
fa66195619 web: Controller refinements, error handling (#14700)
* web: Partial fix for issue where config is not consistently available.

* web: Fix issues surrounding controller readiness.

* web: Catch abort errors when originating when wrapped by OpenAPI or Sentry.

* web: Fix color on dark mode.

---------

Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-05-28 07:08:09 -04:00
134eb126b6 web: Add specific Storybook dependency. (#14719)
Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-05-28 07:08:01 -04:00
f5a6136a58 web/NPM Workspaces: TypeScript API Client TSConfig. (#14555)
web: Use consistent TSConfig.
2025-05-28 07:07:52 -04:00
1a82dfcd61 web: bump core-js from 3.38.1 to 3.42.0 in /web (#14715)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.38.1 to 3.42.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.42.0/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  dependency-version: 3.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-28 12:28:37 +02:00
61fc1dc1fb web: fix lock file once again yay JS (#14721)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-05-28 01:35:11 +02:00
1f921cc18e ci: fix broken cache (#14725)
* ci: fix broken cache

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

* fix commit hash

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-05-28 01:06:49 +02:00
2f94ee3f1f core: bump msgraph-sdk from 1.30.0 to 1.31.0 (#14585)
Bumps [msgraph-sdk](https://github.com/microsoftgraph/msgraph-sdk-python) from 1.30.0 to 1.31.0.
- [Release notes](https://github.com/microsoftgraph/msgraph-sdk-python/releases)
- [Changelog](https://github.com/microsoftgraph/msgraph-sdk-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoftgraph/msgraph-sdk-python/compare/v1.30.0...v1.31.0)

---
updated-dependencies:
- dependency-name: msgraph-sdk
  dependency-version: 1.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-27 19:55:12 +02:00
154fba12e0 website/docs: add login page source note to all source docs (#14667)
* Updates all source documents with note on how to add source to login page

* Updated the wording on the guide itself

* Updated wording on notes

* Fixes capitalization on header

* Fixed broken links in google docs
2025-05-27 12:31:23 -05:00
0d18c1d797 web: fix regression in subpath support (#14646)
* web: fix regression in subpath support, part 1

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

* fix media path in subpath

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-05-27 18:42:47 +02:00
e905dd52d8 lib/sync/outgoing: sync in parallel (#14697)
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-05-27 15:26:43 +02:00
245126a1c3 core, web: update translations (#14707)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-05-27 11:32:31 +00:00
15d84d30ba tests/e2e: fix flaky SAML Source test (#14708) 2025-05-27 13:18:03 +02:00
c6333f9e19 web: fix lock (#14705)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-05-27 03:28:56 +02:00
56565b0895 Update packages-npm-publish.yml (#14702)
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
2025-05-26 16:20:58 +00:00
cbbc7c1825 website/integrations: coder: fix typo (#14514)
Signed-off-by: Dominic R <dominic@sdko.org>
2025-05-26 17:23:17 +02:00
908aaa5afa ci: Update packages-npm-publish.yml (#14701)
Update packages-npm-publish.yml

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
2025-05-26 15:10:47 +00:00
937342eab1 web: bump the swc group across 2 directories with 12 updates (#14623)
Bumps the swc group with 2 updates in the /web directory: [@swc/cli](https://github.com/swc-project/pkgs) and [@swc/core](https://github.com/swc-project/swc).
Bumps the swc group with 1 update in the /web/packages/sfe directory: [@swc/cli](https://github.com/swc-project/pkgs).


Updates `@swc/cli` from 0.4.0 to 0.7.7
- [Commits](https://github.com/swc-project/pkgs/commits)

Updates `@swc/core` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-darwin-arm64` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-darwin-x64` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-arm64-gnu` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-arm64-musl` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-x64-gnu` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-x64-musl` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-win32-arm64-msvc` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-win32-ia32-msvc` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-win32-x64-msvc` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-darwin-arm64` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-darwin-x64` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-arm-gnueabihf` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-arm64-gnu` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-arm64-musl` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-x64-gnu` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-linux-x64-musl` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-win32-arm64-msvc` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-win32-ia32-msvc` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/core-win32-x64-msvc` from 1.7.28 to 1.11.29
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.7.28...v1.11.29)

Updates `@swc/cli` from 0.4.0 to 0.7.7
- [Commits](https://github.com/swc-project/pkgs/commits)

---
updated-dependencies:
- dependency-name: "@swc/cli"
  dependency-version: 0.7.7
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-version: 1.11.29
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/cli"
  dependency-version: 0.7.7
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: swc
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 16:22:43 +02:00
82823a7449 web: Use engine available on Github Actions. (#14699) 2025-05-26 16:02:57 +02:00
ad50f14a3e web: bump the rollup group across 1 directory with 4 updates (#14682)
Bumps the rollup group with 4 updates in the /web directory: [@rollup/rollup-darwin-arm64](https://github.com/rollup/rollup), [@rollup/rollup-linux-arm64-gnu](https://github.com/rollup/rollup), [@rollup/rollup-linux-x64-gnu](https://github.com/rollup/rollup) and [rollup](https://github.com/rollup/rollup).


Updates `@rollup/rollup-darwin-arm64` from 4.41.0 to 4.41.1
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.41.0...v4.41.1)

Updates `@rollup/rollup-linux-arm64-gnu` from 4.41.0 to 4.41.1
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.41.0...v4.41.1)

Updates `@rollup/rollup-linux-x64-gnu` from 4.41.0 to 4.41.1
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.41.0...v4.41.1)

Updates `rollup` from 4.41.0 to 4.41.1
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.41.0...v4.41.1)

---
updated-dependencies:
- dependency-name: "@rollup/rollup-darwin-arm64"
  dependency-version: 4.41.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-arm64-gnu"
  dependency-version: 4.41.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-x64-gnu"
  dependency-version: 4.41.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: rollup
  dependency-version: 4.41.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: rollup
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 16:02:38 +02:00
e0cf6128df ci: test with postgres 17 (#13967) 2025-05-26 13:55:34 +00:00
bfbe8b8038 web: bump knip from 5.33.0 to 5.58.0 in /web (#14685)
Bumps [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) from 5.33.0 to 5.58.0.
- [Release notes](https://github.com/webpro-nl/knip/releases)
- [Changelog](https://github.com/webpro-nl/knip/blob/main/packages/knip/.release-it.json)
- [Commits](https://github.com/webpro-nl/knip/commits/5.58.0/packages/knip)

---
updated-dependencies:
- dependency-name: knip
  dependency-version: 5.58.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 15:06:28 +02:00
36ba8bc4e7 web: bump fuse.js from 7.0.0 to 7.1.0 in /web (#14687)
Bumps [fuse.js](https://github.com/krisk/Fuse) from 7.0.0 to 7.1.0.
- [Release notes](https://github.com/krisk/Fuse/releases)
- [Changelog](https://github.com/krisk/Fuse/blob/main/CHANGELOG.md)
- [Commits](https://github.com/krisk/Fuse/compare/v7.0.0...v7.1.0)

---
updated-dependencies:
- dependency-name: fuse.js
  dependency-version: 7.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 15:06:17 +02:00
dd5edf7fd9 web: bump @formatjs/intl-listformat from 7.5.7 to 7.7.11 in /web (#14689)
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.5.7 to 7.7.11.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.5.7...@formatjs/intl-listformat@7.7.11)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  dependency-version: 7.7.11
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 15:06:07 +02:00
da1b252f3b root: do not use /bin/bash directly (#14698) 2025-05-26 14:38:29 +02:00
a8e543972a website/integrations: minio: notice about sso deprecation on CE (#14679)
* website/integrations: minio: notice about sso deprecation on CE

Starting with RELEASE.2025-05-24T17-08-30Z, MinIO has limited SSO support to their enterprise edition. This pr adds a warning to inform users and recommends sticking with earlier versions to retain SSO functionality.


Signed-off-by: Dominic R <dominic@sdko.org>

* sugg

Signed-off-by: Dominic R <dominic@sdko.org>

* tweak

Signed-off-by: Dominic R <dominic@sdko.org>

---------

Signed-off-by: Dominic R <dominic@sdko.org>
2025-05-26 07:37:49 -05:00
6e03045d1f core: bump cryptography from 44.0.3 to 45.0.3 (#14690)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 12:37:44 +00:00
f4b39e7465 core: bump django-tenants from 3.7.0 to 3.8.0 (#14691)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 12:36:49 +00:00
e7cd5880b5 core: bump astral-sh/uv from 0.7.7 to 0.7.8 (#14681)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 12:26:25 +00:00
d8c6a2417d core: bump axllent/mailpit from v1.25.0 to v1.25.1 in /tests/e2e (#14693)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 14:25:34 +02:00
a1fe471a59 core: Publish web packages. (#14648) 2025-05-26 08:25:20 -04:00
054dfda73f website/integrations: add push security (#14429)
* Updates integrations sidebar and adds push security doc. WIP

* Partially added push instructions

* Added final instructions

* Fixed broken link

* Added few lines and changed formatting.

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Added note about login from push login URL, and added suggestions from Dominic

* Applied suggestions from Dominic

* Fixed verification cert line

* Added note to recommend users follow the extra verificaton step

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/integrations/services/push-security/index.mdx

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* moved resouces section to end of document

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-05-26 07:23:40 -05:00
2e5e8f5c58 docs: fix typos in developer and user documentation (#14680) 2025-05-26 11:51:17 +00:00
c28b65a3f2 Web: Controllers cleanup (#14616)
* web: Fix issues surrounding availability of controllers during init.

web: Fix edgecase where flow does not have brand.

* web: Fix import path.

* web: Clean up mixin/controller paths.

* web: Prepare for consistent import styling.

- Prep for Storybook fixes.

* web: Update MDX types.

* web: Fix issues surrounding async imports, MDX typing, relative paths.

* web: Format. Clarify.

* web: Group module types.
2025-05-26 07:06:14 -04:00
afc9847e36 website: Fix issue where OpenAPI docs template generates semi-synthet… (#14674)
* website: Fix issue where OpenAPI docs template generates semi-synthetic title.

* website: Clarify linter behavior. Tidy components.
2025-05-26 10:50:45 +00:00
620c95dfa1 web: bump the goauthentik group across 4 directories with 3 updates (#14640)
Bumps the goauthentik group with 1 update in the /packages/docusaurus-config directory: @goauthentik/prettier-config.
Bumps the goauthentik group with 2 updates in the /packages/eslint-config directory: @goauthentik/prettier-config and @goauthentik/tsconfig.
Bumps the goauthentik group with 1 update in the /packages/prettier-config directory: @goauthentik/tsconfig.
Bumps the goauthentik group with 2 updates in the /web directory: @goauthentik/prettier-config and @goauthentik/eslint-config.


Updates `@goauthentik/prettier-config` from 1.0.4 to 1.0.5

Updates `@goauthentik/prettier-config` from 1.0.1 to 1.0.5

Updates `@goauthentik/tsconfig` from 1.0.1 to 1.0.4

Updates `@goauthentik/tsconfig` from 1.0.1 to 1.0.4

Updates `@goauthentik/prettier-config` from 1.0.4 to 1.0.5

Updates `@goauthentik/eslint-config` from 1.0.4 to 1.0.5

---
updated-dependencies:
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 1.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 1.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
- dependency-name: "@goauthentik/tsconfig"
  dependency-version: 1.0.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
- dependency-name: "@goauthentik/tsconfig"
  dependency-version: 1.0.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 1.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
- dependency-name: "@goauthentik/eslint-config"
  dependency-version: 1.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 03:52:23 +02:00
15c7a0a9be core, web: update translations (#14676)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-05-26 00:30:51 +02:00
5fed8ca575 web: Type Tidy (#14647)
* web: Update Sentry types.

* web: Update MDX types.

* web: Format. Remove unused script.

* web: Clean up test types.

* web: Fix label in dark mode.
2025-05-23 17:31:59 +02:00
f471ddfb29 core: bump pydantic from 2.11.4 to 2.11.5 (#14652)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.11.4 to 2.11.5.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/v2.11.5/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.11.4...v2.11.5)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-version: 2.11.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 17:24:55 +02:00
1b1f06c9f7 core: bump google-api-python-client from 2.169.0 to 2.170.0 (#14653)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.169.0 to 2.170.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.169.0...v2.170.0)

---
updated-dependencies:
- dependency-name: google-api-python-client
  dependency-version: 2.170.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 17:24:42 +02:00
67c31a8ac3 sources/scim: fix all users being added to group when no members are given (#14645)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-05-23 13:57:50 +02:00
638180d246 web: bump @codemirror/lang-javascript from 6.2.2 to 6.2.4 in /web (#14657)
Bumps [@codemirror/lang-javascript](https://github.com/codemirror/lang-javascript) from 6.2.2 to 6.2.4.
- [Changelog](https://github.com/codemirror/lang-javascript/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/lang-javascript/compare/6.2.2...6.2.4)

---
updated-dependencies:
- dependency-name: "@codemirror/lang-javascript"
  dependency-version: 6.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:51:48 +02:00
a3be1bbb57 web: bump @types/node from 22.15.19 to 22.15.21 in /web (#14660)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.15.19 to 22.15.21.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.15.21
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:51:31 +02:00
fbd0ba2865 core: bump astral-sh/uv from 0.7.6 to 0.7.7 (#14651)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.7.6 to 0.7.7.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.7.6...0.7.7)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.7.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:51:15 +02:00
182ad912cb web: bump wireit from 0.14.9 to 0.14.12 in /web (#14656)
Bumps [wireit](https://github.com/google/wireit) from 0.14.9 to 0.14.12.
- [Changelog](https://github.com/google/wireit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/wireit/compare/v0.14.9...v0.14.12)

---
updated-dependencies:
- dependency-name: wireit
  dependency-version: 0.14.12
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:50:19 +02:00
e850b2ba1a web: bump country-flag-icons from 1.5.13 to 1.5.19 in /web (#14659)
Bumps [country-flag-icons](https://gitlab.com/catamphetamine/country-flag-icons) from 1.5.13 to 1.5.19.
- [Changelog](https://gitlab.com/catamphetamine/country-flag-icons/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/catamphetamine/country-flag-icons/compare/v1.5.13...v1.5.19)

---
updated-dependencies:
- dependency-name: country-flag-icons
  dependency-version: 1.5.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:49:50 +02:00
b4ce7f9ab0 web: bump @trivago/prettier-plugin-sort-imports from 4.3.0 to 5.2.2 in /web (#14661)
web: bump @trivago/prettier-plugin-sort-imports in /web

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.3.0 to 5.2.2.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.3.0...v5.2.2)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  dependency-version: 5.2.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:49:23 +02:00
5f0bd6f5ea web: bump chart.js from 4.4.4 to 4.4.9 in /web (#14655)
Bumps [chart.js](https://github.com/chartjs/Chart.js) from 4.4.4 to 4.4.9.
- [Release notes](https://github.com/chartjs/Chart.js/releases)
- [Commits](https://github.com/chartjs/Chart.js/compare/v4.4.4...v4.4.9)

---
updated-dependencies:
- dependency-name: chart.js
  dependency-version: 4.4.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:49:07 +02:00
f5944ccb95 website: bump the goauthentik group in /website with 3 updates (#14654)
Bumps the goauthentik group in /website with 3 updates: @goauthentik/docusaurus-config, @goauthentik/eslint-config and @goauthentik/prettier-config.


Updates `@goauthentik/docusaurus-config` from 1.0.6 to 1.1.0

Updates `@goauthentik/eslint-config` from 1.0.4 to 1.0.5

Updates `@goauthentik/prettier-config` from 1.0.4 to 1.0.5

---
updated-dependencies:
- dependency-name: "@goauthentik/docusaurus-config"
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: goauthentik
- dependency-name: "@goauthentik/eslint-config"
  dependency-version: 1.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
- dependency-name: "@goauthentik/prettier-config"
  dependency-version: 1.0.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: goauthentik
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:48:45 +02:00
9bd3bad605 web: bump dompurify from 3.2.4 to 3.2.6 in /web (#14658)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.2.4 to 3.2.6.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.2.4...3.2.6)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 13:48:22 +02:00
dff60ee9fb web: fix lint (#14665)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-05-23 13:47:10 +02:00
436 changed files with 76442 additions and 47338 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2025.4.1
current_version = 2025.6.3
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
@ -21,6 +21,8 @@ optional_value = final
[bumpversion:file:package.json]
[bumpversion:file:package-lock.json]
[bumpversion:file:docker-compose.yml]
[bumpversion:file:schema.yml]
@ -31,6 +33,4 @@ optional_value = final
[bumpversion:file:internal/constants/constants.go]
[bumpversion:file:web/src/common/constants.ts]
[bumpversion:file:lifecycle/aws/template.yaml]

View File

@ -28,15 +28,15 @@ runs:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: web/package.json
cache: "npm"
cache-dependency-path: package-lock.json
cache-dependency-path: web/package-lock.json
- name: Setup go
uses: actions/setup-go@v5
with:
go-version-file: "go.mod"
- name: Setup docker cache
uses: ScribeMD/docker-cache@0.5.0
uses: AndreKurait/docker-cache@0fe76702a40db986d9663c24954fc14c6a6031b7
with:
key: docker-images-${{ runner.os }}-${{ hashFiles('.github/actions/setup/docker-compose.yml', 'Makefile') }}-${{ inputs.postgresql_version }}
- name: Setup dependencies
@ -44,7 +44,7 @@ runs:
run: |
export PSQL_TAG=${{ inputs.postgresql_version }}
docker compose -f .github/actions/setup/docker-compose.yml up -d
npm ci
cd web && npm ci
- name: Generate config
shell: uv run python {0}
run: |

View File

@ -20,11 +20,8 @@ jobs:
token: ${{ steps.generate_token.outputs.token }}
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: web/package.json
registry-url: "https://registry.npmjs.org"
- name: Prepare Dependencies
run: |
npm ci
- name: Generate API Client
run: make gen-client-ts
- name: Publish package
@ -35,13 +32,15 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
- name: Upgrade /web
working-directory: web
run: |
export VERSION=`node -e 'console.log(require("./gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION -w @goauthentik/web
export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION
- name: Upgrade /web/packages/sfe
working-directory: web/packages/sfe
run: |
export VERSION=`node -e 'console.log(require("./gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION -w @goauthentik/web-sfe
export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION
- uses: peter-evans/create-pull-request@v7
id: cpr
with:

View File

@ -62,6 +62,7 @@ jobs:
psql:
- 15-alpine
- 16-alpine
- 17-alpine
run_id: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v4
@ -116,6 +117,7 @@ jobs:
psql:
- 15-alpine
- 16-alpine
- 17-alpine
run_id: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v4
@ -193,22 +195,23 @@ jobs:
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Setup E2E environment (Chrome, etc)
- name: Setup e2e env (chrome, etc)
run: |
docker compose -f tests/e2e/docker-compose.yml up -d --quiet-pull
- id: cache-web
uses: actions/cache@v4
with:
path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
- name: Prepare Web UI
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
- name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true'
working-directory: web
run: |
npm ci
make gen-client-ts
npm run build -w @goauthentik/web
npm run build -w @goauthentik/web-sfe
- name: Run E2E
make -C .. gen-client-ts
npm run build
npm run build:sfe
- name: run e2e
run: |
uv run coverage run manage.py test ${{ matrix.job.glob }}
uv run coverage xml

View File

@ -26,7 +26,7 @@ jobs:
mkdir -p web/dist
mkdir -p website/help
touch web/dist/test website/help/test
- name: Generate Golang API Client
- name: Generate API
run: make gen-client-go
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
@ -43,7 +43,7 @@ jobs:
go-version-file: "go.mod"
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Generate Golang API Client
- name: Generate API
run: make gen-client-go
- name: Go unittests
run: |
@ -99,7 +99,7 @@ jobs:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Golang API Client
- name: Generate API
run: make gen-client-go
- name: Build Docker Image
id: push
@ -145,17 +145,16 @@ jobs:
go-version-file: "go.mod"
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: web/package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Generate Golang API Client
cache-dependency-path: web/package-lock.json
- name: Generate API
run: make gen-client-go
- name: Prepare Dependencies
- name: Build web
working-directory: web/
run: |
npm ci
- name: Run ESBuild
run: |
npm run build-proxy -w @goauthentik/web
npm run build-proxy
- name: Build outpost
run: |
set -x

View File

@ -19,45 +19,47 @@ jobs:
matrix:
command:
- lint
- lint:lockfile
- tsc
- prettier-check
project:
- web
include:
- command: tsc
project: web
- command: lit-analyse
project: web
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: ${{ matrix.project }}/package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
cache-dependency-path: ${{ matrix.project }}/package-lock.json
- working-directory: ${{ matrix.project }}/
run: |
npm ci
- name: Generate TypeScript API
- name: Generate API
run: make gen-client-ts
- name: Lint Project
run: |
npm run build-locales -w @goauthentik/web
npm run lint:types
- name: Lint Web
run: npm run ${{ matrix.command }} -w @goauthentik/web
- name: Lint
working-directory: ${{ matrix.project }}/
run: npm run ${{ matrix.command }}
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: web/package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
cache-dependency-path: web/package-lock.json
- working-directory: web/
run: npm ci
- name: Generate TypeScript API
- name: Generate API
run: make gen-client-ts
- name: build
run: npm run build -w @goauthentik/web
working-directory: web/
run: npm run build
ci-web-mark:
if: always()
needs:
@ -76,12 +78,13 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: web/package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
cache-dependency-path: web/package-lock.json
- working-directory: web/
run: npm ci
- name: Generate TypeScript API
- name: Generate API
run: make gen-client-ts
- name: test
run: npm run test -w @goauthentik/web || exit 0
working-directory: web/
run: npm run test || exit 0

View File

@ -14,44 +14,54 @@ on:
jobs:
lint:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
command:
- lint:lockfile
- prettier-check
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
- working-directory: website/
run: npm ci
- name: Lint
run: npm run prettier-check -w @goauthentik/docs
working-directory: website/
run: npm run ${{ matrix.command }}
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: website/package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
cache-dependency-path: website/package-lock.json
- working-directory: website/
run: npm ci
- name: test
run: npm test -w @goauthentik/docs
working-directory: website/
run: npm test
build:
runs-on: ubuntu-latest
name: ${{ matrix.job }}
strategy:
fail-fast: false
matrix:
job:
- build
- build:integrations
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: website/package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
cache-dependency-path: website/package-lock.json
- working-directory: website/
run: npm ci
- name: Run Docusaurus
run: npm run build -w @goauthentik/docs
- name: build
working-directory: website/
run: npm run ${{ matrix.job }}
ci-website-mark:
if: always()
needs:

View File

@ -2,7 +2,7 @@ name: "CodeQL"
on:
push:
branches: [main, "*", next, version*]
branches: [main, next, version*]
pull_request:
branches: [main]
schedule:

View File

@ -7,7 +7,7 @@ on:
- packages/eslint-config/**
- packages/prettier-config/**
- packages/tsconfig/**
- packages/web/esbuild-plugin-live-reload/**
- web/packages/esbuild-plugin-live-reload/**
workflow_dispatch:
jobs:
publish:
@ -21,7 +21,7 @@ jobs:
- packages/eslint-config
- packages/prettier-config
- packages/tsconfig
- packages/web/esbuild-plugin-live-reload
- web/packages/esbuild-plugin-live-reload
steps:
- uses: actions/checkout@v4
with:

View File

@ -106,14 +106,14 @@ jobs:
go-version-file: "go.mod"
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: web/package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
run: npm ci
- name: Run ESBuild (Proxy)
cache-dependency-path: web/package-lock.json
- name: Build web
working-directory: web/
run: |
npm run build-proxy -w @goauthentik/web
npm ci
npm run build-proxy
- name: Build outpost
run: |
set -x

View File

@ -32,25 +32,15 @@ jobs:
if: ${{ github.event_name == 'pull_request' }}
- name: Setup authentik env
uses: ./.github/actions/setup
- uses: actions/setup-node@v4
with:
node-version-file: package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
run: npm ci
- name: Generate TypeScript API
- name: Generate API
run: make gen-client-ts
- name: Run extract
- name: run extract
run: |
uv run make i18n-extract
- name: Run UV compile
- name: run compile
run: |
uv run ak compilemessages
- name: Lint Project
run: |
npm run build-locales -w @goauthentik/web
npm run lint:types
make web-check-compile
- name: Create Pull Request
if: ${{ github.event_name != 'pull_request' }}
uses: peter-evans/create-pull-request@v7

View File

@ -36,19 +36,12 @@ coverage
*.mdx
*.md
## Import order matters
poly.ts
src/locale-codes.ts
src/locales/
# Storybook
storybook-static/
.storybook/css-import-maps*
# JSON Schemas
schemas/**/*.json
blueprints/**/*.json
authentik/**/*.json
lifecycle/**/*.json
# Locales
web/src/locale-codes.ts
web/src/locales/
# Wireit's cache
.wireit

View File

@ -17,6 +17,6 @@
"ms-python.vscode-pylance",
"redhat.vscode-yaml",
"Tobermory.es6-string-html",
"unifiedjs.vscode-mdx"
"unifiedjs.vscode-mdx",
]
}

40
.vscode/tasks.json vendored
View File

@ -4,7 +4,12 @@
{
"label": "authentik/core: make",
"command": "uv",
"args": ["run", "make", "lint-fix", "lint"],
"args": [
"run",
"make",
"lint-fix",
"lint"
],
"presentation": {
"panel": "new"
},
@ -13,7 +18,11 @@
{
"label": "authentik/core: run",
"command": "uv",
"args": ["run", "ak", "server"],
"args": [
"run",
"ak",
"server"
],
"group": "build",
"presentation": {
"panel": "dedicated",
@ -23,13 +32,17 @@
{
"label": "authentik/web: make",
"command": "make",
"args": ["web"],
"args": [
"web"
],
"group": "build"
},
{
"label": "authentik/web: watch",
"command": "make",
"args": ["web-watch"],
"args": [
"web-watch"
],
"group": "build",
"presentation": {
"panel": "dedicated",
@ -39,19 +52,26 @@
{
"label": "authentik: install",
"command": "make",
"args": ["install", "-j4"],
"args": [
"install",
"-j4"
],
"group": "build"
},
{
"label": "authentik/website: make",
"command": "make",
"args": ["website"],
"args": [
"website"
],
"group": "build"
},
{
"label": "authentik/website: watch",
"command": "make",
"args": ["website-watch"],
"args": [
"website-watch"
],
"group": "build",
"presentation": {
"panel": "dedicated",
@ -61,7 +81,11 @@
{
"label": "authentik/api: generate",
"command": "uv",
"args": ["run", "make", "gen"],
"args": [
"run",
"make",
"gen"
],
"group": "build"
}
]

View File

@ -1,41 +1,49 @@
# syntax=docker/dockerfile:1
# Stage 1: Build Node packages
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-slim AS node-packages
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
WORKDIR /work
COPY ./SECURITY.md /work
COPY ./schema.yml /work
COPY ./docker-compose.yml /work
COPY ./blueprints /work/blueprints/
COPY ./package.json /work
COPY ./package-lock.json /work
COPY ./tsconfig.json /work
COPY ./packages/ /work/packages/
COPY ./web /work/web/
COPY ./website /work/website/
COPY ./gen-ts-api /work/gen-ts-api/
RUN --mount=type=cache,id=npm-node,sharing=shared,target=/root/.npm \
npm ci
RUN cd ./gen-ts-api && npm link
RUN npm link @goauthentik/api -w @goauthentik/web
# Stage 1: Build website
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24 AS website-builder
ENV NODE_ENV=production
RUN npm run build -w @goauthentik/web
RUN npm run build -w @goauthentik/web-sfe
WORKDIR /work/website
RUN npm run build:api -w @goauthentik/docs
RUN npm run build:docusaurus -w @goauthentik/docs
RUN --mount=type=bind,target=/work/website/package.json,src=./website/package.json \
--mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \
--mount=type=cache,id=npm-website,sharing=shared,target=/root/.npm \
npm ci --include=dev
# Stage 2: Build go proxy
COPY ./website /work/website/
COPY ./blueprints /work/blueprints/
COPY ./schema.yml /work/
COPY ./SECURITY.md /work/
RUN npm run build-bundled
# Stage 2: Build webui
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24 AS web-builder
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
ENV NODE_ENV=production
WORKDIR /work/web
RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \
--mount=type=bind,target=/work/web/packages/sfe/package.json,src=./web/packages/sfe/package.json \
--mount=type=bind,target=/work/web/scripts,src=./web/scripts \
--mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
npm ci --include=dev
COPY ./package.json /work
COPY ./web /work/web/
COPY ./website /work/website/
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build && \
npm run build:sfe
# Stage 3: Build go proxy
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
ARG TARGETOS
@ -60,8 +68,8 @@ RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \
COPY ./cmd /go/src/goauthentik.io/cmd
COPY ./authentik/lib /go/src/goauthentik.io/authentik/lib
COPY ./web/static.go /go/src/goauthentik.io/web/static.go
COPY --from=node-packages /work/web/robots.txt /go/src/goauthentik.io/web/robots.txt
COPY --from=node-packages /work/web/security.txt /go/src/goauthentik.io/web/security.txt
COPY --from=web-builder /work/web/robots.txt /go/src/goauthentik.io/web/robots.txt
COPY --from=web-builder /work/web/security.txt /go/src/goauthentik.io/web/security.txt
COPY ./internal /go/src/goauthentik.io/internal
COPY ./go.mod /go/src/goauthentik.io/go.mod
COPY ./go.sum /go/src/goauthentik.io/go.sum
@ -72,7 +80,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/authentik ./cmd/server
# Stage 3: MaxMind GeoIP
# Stage 4: MaxMind GeoIP
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN"
@ -85,10 +93,10 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
mkdir -p /usr/share/GeoIP && \
/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
FROM ghcr.io/astral-sh/uv:0.7.6 AS uv
# Stage 5: Base python image
FROM ghcr.io/goauthentik/fips-python:3.13.3-slim-bookworm-fips AS python-base
# Stage 5: Download uv
FROM ghcr.io/astral-sh/uv:0.7.8 AS uv
# Stage 6: Base python image
FROM ghcr.io/goauthentik/fips-python:3.13.5-slim-bookworm-fips AS python-base
ENV VENV_PATH="/ak-root/.venv" \
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
@ -101,7 +109,7 @@ WORKDIR /ak-root/
COPY --from=uv /uv /uvx /bin/
# Stage 6: Python dependencies
# Stage 7: Python dependencies
FROM python-base AS python-deps
ARG TARGETARCH
@ -136,7 +144,7 @@ RUN --mount=type=bind,target=pyproject.toml,src=pyproject.toml \
--mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-dev
# Stage 7: Run
# Stage 8: Run
FROM python-base AS final-image
ARG VERSION
@ -179,9 +187,9 @@ COPY ./lifecycle/ /lifecycle
COPY ./authentik/sources/kerberos/krb5.conf /etc/krb5.conf
COPY --from=go-builder /go/authentik /bin/authentik
COPY --from=python-deps /ak-root/.venv /ak-root/.venv
COPY --from=node-packages /work/web/dist/ /web/dist/
COPY --from=node-packages /work/web/authentik/ /web/authentik/
COPY --from=node-packages /work/website/build/ /website/help/
COPY --from=web-builder /work/web/dist/ /web/dist/
COPY --from=web-builder /work/web/authentik/ /web/authentik/
COPY --from=website-builder /work/website/build/ /website/help/
COPY --from=geoip /usr/share/GeoIP /geoip
USER 1000

View File

@ -1,6 +1,6 @@
.PHONY: gen dev-reset all clean test web website
SHELL := /bin/bash
SHELL := /usr/bin/env bash
.SHELLFLAGS += ${SHELLFLAGS} -e -o pipefail
PWD = $(shell pwd)
UID = $(shell id -u)
@ -73,7 +73,7 @@ core-i18n-extract:
--ignore website \
-l en
install: npm-install core-install ## Install all requires dependencies for `web`, `website` and `core`
install: web-install website-install core-install ## Install all requires dependencies for `web`, `website` and `core`
dev-drop-db:
dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
@ -86,6 +86,10 @@ dev-create-db:
dev-reset: dev-drop-db dev-create-db migrate ## Drop and restore the Authentik PostgreSQL instance to a "fresh install" state.
update-test-mmdb: ## Update test GeoIP and ASN Databases
curl -L https://raw.githubusercontent.com/maxmind/MaxMind-DB/refs/heads/main/test-data/GeoLite2-ASN-Test.mmdb -o ${PWD}/tests/GeoLite2-ASN-Test.mmdb
curl -L https://raw.githubusercontent.com/maxmind/MaxMind-DB/refs/heads/main/test-data/GeoLite2-City-Test.mmdb -o ${PWD}/tests/GeoLite2-City-Test.mmdb
#########################
## API Schema
#########################
@ -146,8 +150,9 @@ gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescri
--additional-properties=npmVersion=${NPM_VERSION} \
--git-repo-id authentik \
--git-user-id goauthentik
cd ./${GEN_API_TS} && npm link
npm link @goauthentik/api -w @goauthentik/web
mkdir -p web/node_modules/@goauthentik/api
cd ${PWD}/${GEN_API_TS} && npm i
\cp -rf ${PWD}/${GEN_API_TS}/* web/node_modules/@goauthentik/api
gen-client-py: gen-clean-py ## Build and install the authentik API for Python
docker run \
@ -182,34 +187,38 @@ gen: gen-build gen-client-ts
## Web
#########################
web-build: npm-install ## Build the Authentik UI
npm run build -w @goauthentik/web
web-build: web-install ## Build the Authentik UI
cd web && npm run build
web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
npm-install: ## Install the necessary libraries to build the Authentik UI
npm ci
web-install: ## Install the necessary libraries to build the Authentik UI
cd web && npm ci
web-test: ## Run tests for the Authentik UI
npm run test -w @goauthentik/web
cd web && npm run test
web-watch: ## Build and watch the Authentik UI for changes, updating automatically
npm run watch -w @goauthentik/web
rm -rf web/dist/
mkdir web/dist/
touch web/dist/.gitkeep
cd web && npm run watch
web-storybook-watch: ## Build and run the storybook documentation server
npm run storybook -w @goauthentik/web
cd web && npm run storybook
web-lint-fix:
npm run prettier -w @goauthentik/web
cd web && npm run prettier
web-lint:
npm run lint -w @goauthentik/web
cd web && npm run lint
cd web && npm run lit-analyse
web-check-compile:
npm run lint:types
cd web && npm run tsc
web-i18n-extract:
npm run extract-locales -w @goauthentik/web
cd web && npm run extract-locales
#########################
## Website
@ -217,14 +226,17 @@ web-i18n-extract:
website: website-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it
website-install:
cd website && npm ci
website-lint-fix: lint-codespell
npm run prettier --prefix website
cd website && npm run prettier
website-build:
npm run build --prefix website
cd website && npm run build
website-watch: ## Build and watch the documentation website, updating automatically
npm run watch --prefix website
cd website && npm run watch
#########################
## Docker

View File

@ -20,8 +20,8 @@ Even if the issue is not a CVE, we still greatly appreciate your help in hardeni
| Version | Supported |
| --------- | --------- |
| 2025.2.x | ✅ |
| 2025.4.x | ✅ |
| 2025.6.x | ✅ |
## Reporting a Vulnerability

View File

@ -2,7 +2,7 @@
from os import environ
__version__ = "2025.4.1"
__version__ = "2025.6.3"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -148,3 +148,14 @@ class TestBrands(APITestCase):
"default_locale": "",
},
)
def test_custom_css(self):
"""Test custom_css"""
brand = create_test_brand()
brand.branding_custom_css = """* {
font-family: "Foo bar";
}"""
brand.save()
res = self.client.get(reverse("authentik_core:if-user"))
self.assertEqual(res.status_code, 200)
self.assertIn(brand.branding_custom_css, res.content.decode())

View File

@ -5,6 +5,8 @@ from typing import Any
from django.db.models import F, Q
from django.db.models import Value as V
from django.http.request import HttpRequest
from django.utils.html import _json_script_escapes
from django.utils.safestring import mark_safe
from authentik import get_full_version
from authentik.brands.models import Brand
@ -32,8 +34,13 @@ def context_processor(request: HttpRequest) -> dict[str, Any]:
"""Context Processor that injects brand object into every template"""
brand = getattr(request, "brand", DEFAULT_BRAND)
tenant = getattr(request, "tenant", Tenant())
# similarly to `json_script` we escape everything HTML-related, however django
# only directly exposes this as a function that also wraps it in a <script> tag
# which we dont want for CSS
brand_css = mark_safe(str(brand.branding_custom_css).translate(_json_script_escapes)) # nosec
return {
"brand": brand,
"brand_css": brand_css,
"footer_links": tenant.footer_links,
"html_meta": {**get_http_meta()},
"version": get_full_version(),

View File

@ -84,6 +84,7 @@ from authentik.flows.views.executor import QS_KEY_TOKEN
from authentik.lib.avatars import get_avatar
from authentik.rbac.decorators import permission_required
from authentik.rbac.models import get_permission_choices
from authentik.stages.email.flow import pickle_flow_token_for_email
from authentik.stages.email.models import EmailStage
from authentik.stages.email.tasks import send_mails
from authentik.stages.email.utils import TemplateEmailMessage
@ -451,7 +452,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs)
def _create_recovery_link(self) -> tuple[str, Token]:
def _create_recovery_link(self, for_email=False) -> tuple[str, Token]:
"""Create a recovery link (when the current brand has a recovery flow set),
that can either be shown to an admin or sent to the user directly"""
brand: Brand = self.request._request.brand
@ -473,12 +474,16 @@ class UserViewSet(UsedByMixin, ModelViewSet):
raise ValidationError(
{"non_field_errors": "Recovery flow not applicable to user"}
) from None
_plan = FlowToken.pickle(plan)
if for_email:
_plan = pickle_flow_token_for_email(plan)
token, __ = FlowToken.objects.update_or_create(
identifier=f"{user.uid}-password-reset",
defaults={
"user": user,
"flow": flow,
"_plan": FlowToken.pickle(plan),
"_plan": _plan,
"revoke_on_execution": not for_email,
},
)
querystring = urlencode({QS_KEY_TOKEN: token.key})
@ -648,7 +653,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
if for_user.email == "":
LOGGER.debug("User doesn't have an email address")
raise ValidationError({"non_field_errors": "User does not have an email address set."})
link, token = self._create_recovery_link()
link, token = self._create_recovery_link(for_email=True)
# Lookup the email stage to assure the current user can access it
stages = get_objects_for_user(
request.user, "authentik_stages_email.view_emailstage"

View File

@ -79,6 +79,7 @@ def _migrate_session(
AuthenticatedSession.objects.using(db_alias).create(
session=session,
user=old_auth_session.user,
uuid=old_auth_session.uuid,
)

View File

@ -1,10 +1,81 @@
# Generated by Django 5.1.9 on 2025-05-14 11:15
from django.apps.registry import Apps
from django.apps.registry import Apps, apps as global_apps
from django.db import migrations
from django.contrib.contenttypes.management import create_contenttypes
from django.contrib.auth.management import create_permissions
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def migrate_authenticated_session_permissions(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
"""Migrate permissions from OldAuthenticatedSession to AuthenticatedSession"""
db_alias = schema_editor.connection.alias
# `apps` here is just an instance of `django.db.migrations.state.AppConfigStub`, we need the
# real config for creating permissions and content types
authentik_core_config = global_apps.get_app_config("authentik_core")
# These are only ran by django after all migrations, but we need them right now.
# `global_apps` is needed,
create_permissions(authentik_core_config, using=db_alias, verbosity=1)
create_contenttypes(authentik_core_config, using=db_alias, verbosity=1)
# But from now on, this is just a regular migration, so use `apps`
Permission = apps.get_model("auth", "Permission")
ContentType = apps.get_model("contenttypes", "ContentType")
try:
old_ct = ContentType.objects.using(db_alias).get(
app_label="authentik_core", model="oldauthenticatedsession"
)
new_ct = ContentType.objects.using(db_alias).get(
app_label="authentik_core", model="authenticatedsession"
)
except ContentType.DoesNotExist:
# This should exist at this point, but if not, let's cut our losses
return
# Get all permissions for the old content type
old_perms = Permission.objects.using(db_alias).filter(content_type=old_ct)
# Create equivalent permissions for the new content type
for old_perm in old_perms:
new_perm = (
Permission.objects.using(db_alias)
.filter(
content_type=new_ct,
codename=old_perm.codename,
)
.first()
)
if not new_perm:
# This should exist at this point, but if not, let's cut our losses
continue
# Global user permissions
User = apps.get_model("authentik_core", "User")
User.user_permissions.through.objects.using(db_alias).filter(
permission=old_perm
).all().update(permission=new_perm)
# Global role permissions
DjangoGroup = apps.get_model("auth", "Group")
DjangoGroup.permissions.through.objects.using(db_alias).filter(
permission=old_perm
).all().update(permission=new_perm)
# Object user permissions
UserObjectPermission = apps.get_model("guardian", "UserObjectPermission")
UserObjectPermission.objects.using(db_alias).filter(permission=old_perm).all().update(
permission=new_perm, content_type=new_ct
)
# Object role permissions
GroupObjectPermission = apps.get_model("guardian", "GroupObjectPermission")
GroupObjectPermission.objects.using(db_alias).filter(permission=old_perm).all().update(
permission=new_perm, content_type=new_ct
)
def remove_old_authenticated_session_content_type(
apps: Apps, schema_editor: BaseDatabaseSchemaEditor
):
@ -21,7 +92,12 @@ class Migration(migrations.Migration):
]
operations = [
migrations.RunPython(
code=migrate_authenticated_session_permissions,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
code=remove_old_authenticated_session_content_type,
reverse_code=migrations.RunPython.noop,
),
]

View File

@ -16,7 +16,7 @@
{% block head_before %}
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<style>{{ brand.branding_custom_css }}</style>
<style>{{ brand_css }}</style>
<script src="{% versioned_script 'dist/poly-%v.js' %}" type="module"></script>
<script src="{% versioned_script 'dist/standalone/loading/index-%v.js' %}" type="module"></script>
{% block head %}

View File

@ -15,13 +15,13 @@ class MMDBContextProcessor(EventContextProcessor):
self.reader: Reader | None = None
self._last_mtime: float = 0.0
self.logger = get_logger()
self.open()
self.load()
def path(self) -> str | None:
"""Get the path to the MMDB file to load"""
raise NotImplementedError
def open(self):
def load(self):
"""Get GeoIP Reader, if configured, otherwise none"""
path = self.path()
if path == "" or not path:
@ -44,7 +44,7 @@ class MMDBContextProcessor(EventContextProcessor):
diff = self._last_mtime < mtime
if diff > 0:
self.logger.info("Found new MMDB Database, reopening", diff=diff, path=path)
self.open()
self.load()
except OSError as exc:
self.logger.warning("Failed to check MMDB age", exc=exc)

View File

@ -0,0 +1,18 @@
# Generated by Django 5.1.9 on 2025-05-27 12:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0027_auto_20231028_1424"),
]
operations = [
migrations.AddField(
model_name="flowtoken",
name="revoke_on_execution",
field=models.BooleanField(default=True),
),
]

View File

@ -303,9 +303,10 @@ class FlowToken(Token):
flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
_plan = models.TextField()
revoke_on_execution = models.BooleanField(default=True)
@staticmethod
def pickle(plan) -> str:
def pickle(plan: "FlowPlan") -> str:
"""Pickle into string"""
data = dumps(plan)
return b64encode(data).decode()

View File

@ -99,9 +99,10 @@ class ChallengeStageView(StageView):
self.logger.debug("Got StageInvalidException", exc=exc)
return self.executor.stage_invalid()
if not challenge.is_valid():
self.logger.warning(
self.logger.error(
"f(ch): Invalid challenge",
errors=challenge.errors,
challenge=challenge.data,
)
return HttpChallengeResponse(challenge)

View File

@ -146,7 +146,8 @@ class FlowExecutorView(APIView):
except (AttributeError, EOFError, ImportError, IndexError) as exc:
LOGGER.warning("f(exec): Failed to restore token plan", exc=exc)
finally:
token.delete()
if token.revoke_on_execution:
token.delete()
if not isinstance(plan, FlowPlan):
return None
plan.context[PLAN_CONTEXT_IS_RESTORED] = token

View File

@ -81,7 +81,6 @@ debugger: false
log_level: info
session_storage: cache
sessions:
unauthenticated_age: days=1

View File

@ -1,6 +1,7 @@
from collections.abc import Callable
from dataclasses import asdict
from celery import group
from celery.exceptions import Retry
from celery.result import allow_join_result
from django.core.paginator import Paginator
@ -82,21 +83,41 @@ class SyncTasks:
self.logger.debug("Failed to acquire sync lock, skipping", provider=provider.name)
return
try:
for page in users_paginator.page_range:
messages.append(_("Syncing page {page} of users".format(page=page)))
for msg in sync_objects.apply_async(
args=(class_to_path(User), page, provider_pk),
time_limit=PAGE_TIMEOUT,
soft_time_limit=PAGE_TIMEOUT,
).get():
messages.append(_("Syncing users"))
user_results = (
group(
[
sync_objects.signature(
args=(class_to_path(User), page, provider_pk),
time_limit=PAGE_TIMEOUT,
soft_time_limit=PAGE_TIMEOUT,
)
for page in users_paginator.page_range
]
)
.apply_async()
.get()
)
for result in user_results:
for msg in result:
messages.append(LogEvent(**msg))
for page in groups_paginator.page_range:
messages.append(_("Syncing page {page} of groups".format(page=page)))
for msg in sync_objects.apply_async(
args=(class_to_path(Group), page, provider_pk),
time_limit=PAGE_TIMEOUT,
soft_time_limit=PAGE_TIMEOUT,
).get():
messages.append(_("Syncing groups"))
group_results = (
group(
[
sync_objects.signature(
args=(class_to_path(Group), page, provider_pk),
time_limit=PAGE_TIMEOUT,
soft_time_limit=PAGE_TIMEOUT,
)
for page in groups_paginator.page_range
]
)
.apply_async()
.get()
)
for result in group_results:
for msg in result:
messages.append(LogEvent(**msg))
except TransientSyncException as exc:
self.logger.warning("transient sync exception", exc=exc)
@ -109,7 +130,7 @@ class SyncTasks:
def sync_objects(
self, object_type: str, page: int, provider_pk: int, override_dry_run=False, **filter
):
_object_type = path_to_class(object_type)
_object_type: type[Model] = path_to_class(object_type)
self.logger = get_logger().bind(
provider_type=class_to_path(self._provider_model),
provider_pk=provider_pk,
@ -132,6 +153,19 @@ class SyncTasks:
self.logger.debug("starting discover")
client.discover()
self.logger.debug("starting sync for page", page=page)
messages.append(
asdict(
LogEvent(
_(
"Syncing page {page} of {object_type}".format(
page=page, object_type=_object_type._meta.verbose_name_plural
)
),
log_level="info",
logger=f"{provider._meta.verbose_name}@{object_type}",
)
)
)
for obj in paginator.page(page).object_list:
obj: Model
try:

View File

@ -1,11 +1,9 @@
"""Websocket tests"""
from dataclasses import asdict
from unittest.mock import patch
from channels.routing import URLRouter
from channels.testing import WebsocketCommunicator
from django.contrib.contenttypes.models import ContentType
from django.test import TransactionTestCase
from authentik import __version__
@ -16,12 +14,6 @@ from authentik.providers.proxy.models import ProxyProvider
from authentik.root import websocket
def patched__get_ct_cached(app_label, codename):
"""Caches `ContentType` instances like its `QuerySet` does."""
return ContentType.objects.get(app_label=app_label, permission__codename=codename)
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
class TestOutpostWS(TransactionTestCase):
"""Websocket tests"""

View File

@ -66,7 +66,10 @@ class RACClientConsumer(AsyncWebsocketConsumer):
def init_outpost_connection(self):
"""Initialize guac connection settings"""
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")
.first()
)

View File

@ -166,7 +166,6 @@ class ConnectionToken(ExpiringModel):
always_merger.merge(settings, default_settings)
always_merger.merge(settings, self.endpoint.provider.settings)
always_merger.merge(settings, self.endpoint.settings)
always_merger.merge(settings, self.settings)
def mapping_evaluator(mappings: QuerySet):
for mapping in mappings:
@ -191,6 +190,7 @@ class ConnectionToken(ExpiringModel):
mapping_evaluator(
RACPropertyMapping.objects.filter(endpoint__in=[self.endpoint]).order_by("name")
)
always_merger.merge(settings, self.settings)
settings["drive-path"] = f"/tmp/connection/{self.token}" # nosec
settings["create-drive-path"] = "true"

View File

@ -90,23 +90,6 @@ class TestModels(TransactionTestCase):
"resize-method": "display-update",
},
)
# Set settings in token
token.settings = {
"level": "token",
}
token.save()
self.assertEqual(
token.get_settings(),
{
"hostname": self.endpoint.host.split(":")[0],
"port": "1324",
"client-name": f"authentik - {self.user}",
"drive-path": path,
"create-drive-path": "true",
"level": "token",
"resize-method": "display-update",
},
)
# Set settings in property mapping (provider)
mapping = RACPropertyMapping.objects.create(
name=generate_id(),
@ -151,3 +134,22 @@ class TestModels(TransactionTestCase):
"resize-method": "display-update",
},
)
# Set settings in token
token.settings = {
"level": "token",
}
token.save()
self.assertEqual(
token.get_settings(),
{
"hostname": self.endpoint.host.split(":")[0],
"port": "1324",
"client-name": f"authentik - {self.user}",
"drive-path": path,
"create-drive-path": "true",
"foo": "true",
"bar": "6",
"resize-method": "display-update",
"level": "token",
},
)

View File

@ -87,3 +87,22 @@ class TestRACViews(APITestCase):
)
body = loads(flow_response.content)
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"))

View File

@ -20,6 +20,9 @@ from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.engine import PolicyEngine
from authentik.policies.views import PolicyAccessView
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
PLAN_CONNECTION_SETTINGS = "connection_settings"
class RACStartView(PolicyAccessView):
@ -65,7 +68,10 @@ class RACInterface(InterfaceView):
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
# 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:
return redirect("authentik_core:if-user")
self.token = token
@ -109,10 +115,15 @@ class RACFinalStage(RedirectStage):
return super().dispatch(request, *args, **kwargs)
def get_challenge(self, *args, **kwargs) -> RedirectChallenge:
settings = self.executor.plan.context.get(PLAN_CONNECTION_SETTINGS)
if not settings:
settings = self.executor.plan.context.get(PLAN_CONTEXT_PROMPT, {}).get(
PLAN_CONNECTION_SETTINGS
)
token = ConnectionToken.objects.create(
provider=self.provider,
endpoint=self.endpoint,
settings=self.executor.plan.context.get("connection_settings", {}),
settings=settings or {},
session=self.request.session["authenticatedsession"],
expires=now() + timedelta_from_string(self.provider.connection_expiry),
expiring=True,

View File

@ -47,15 +47,16 @@ class SCIMGroupClient(SCIMClient[Group, SCIMProviderGroup, SCIMGroupSchema]):
def to_schema(self, obj: Group, connection: SCIMProviderGroup) -> SCIMGroupSchema:
"""Convert authentik user into SCIM"""
raw_scim_group = super().to_schema(
obj,
connection,
schemas=(SCIM_GROUP_SCHEMA,),
)
raw_scim_group = super().to_schema(obj, connection)
try:
scim_group = SCIMGroupSchema.model_validate(delete_none_values(raw_scim_group))
except ValidationError as exc:
raise StopSync(exc, obj) from exc
if SCIM_GROUP_SCHEMA not in scim_group.schemas:
scim_group.schemas.insert(0, SCIM_GROUP_SCHEMA)
# As this might be unset, we need to tell pydantic it's set so ensure the schemas
# are included, even if its just the defaults
scim_group.schemas = list(scim_group.schemas)
if not scim_group.externalId:
scim_group.externalId = str(obj.pk)

View File

@ -31,15 +31,16 @@ class SCIMUserClient(SCIMClient[User, SCIMProviderUser, SCIMUserSchema]):
def to_schema(self, obj: User, connection: SCIMProviderUser) -> SCIMUserSchema:
"""Convert authentik user into SCIM"""
raw_scim_user = super().to_schema(
obj,
connection,
schemas=(SCIM_USER_SCHEMA,),
)
raw_scim_user = super().to_schema(obj, connection)
try:
scim_user = SCIMUserSchema.model_validate(delete_none_values(raw_scim_user))
except ValidationError as exc:
raise StopSync(exc, obj) from exc
if SCIM_USER_SCHEMA not in scim_user.schemas:
scim_user.schemas.insert(0, SCIM_USER_SCHEMA)
# As this might be unset, we need to tell pydantic it's set so ensure the schemas
# are included, even if its just the defaults
scim_user.schemas = list(scim_user.schemas)
if not scim_user.externalId:
scim_user.externalId = str(obj.uid)
return scim_user

View File

@ -91,6 +91,57 @@ class SCIMUserTests(TestCase):
},
)
@Mocker()
def test_user_create_custom_schema(self, mock: Mocker):
"""Test user creation with custom schema"""
schema = SCIMMapping.objects.create(
name="custom_schema",
expression="""return {"schemas": ["foo"]}""",
)
self.provider.property_mappings.add(schema)
scim_id = generate_id()
mock.get(
"https://localhost/ServiceProviderConfig",
json={},
)
mock.post(
"https://localhost/Users",
json={
"id": scim_id,
},
)
uid = generate_id()
user = User.objects.create(
username=uid,
name=f"{uid} {uid}",
email=f"{uid}@goauthentik.io",
)
self.assertEqual(mock.call_count, 2)
self.assertEqual(mock.request_history[0].method, "GET")
self.assertEqual(mock.request_history[1].method, "POST")
self.assertJSONEqual(
mock.request_history[1].body,
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", "foo"],
"active": True,
"emails": [
{
"primary": True,
"type": "other",
"value": f"{uid}@goauthentik.io",
}
],
"externalId": user.uid,
"name": {
"familyName": uid,
"formatted": f"{uid} {uid}",
"givenName": uid,
},
"displayName": f"{uid} {uid}",
"userName": uid,
},
)
@Mocker()
def test_user_create_different_provider_same_id(self, mock: Mocker):
"""Test user creation with multiple providers that happen
@ -384,7 +435,7 @@ class SCIMUserTests(TestCase):
self.assertIn(request.method, SAFE_METHODS)
task = SystemTask.objects.filter(uid=slugify(self.provider.name)).first()
self.assertIsNotNone(task)
drop_msg = task.messages[2]
drop_msg = task.messages[3]
self.assertEqual(drop_msg["event"], "Dropping mutating request due to dry run")
self.assertIsNotNone(drop_msg["attributes"]["url"])
self.assertIsNotNone(drop_msg["attributes"]["body"])

View File

@ -424,7 +424,7 @@ else:
"BACKEND": "authentik.root.storages.FileStorage",
"OPTIONS": {
"location": Path(CONFIG.get("storage.media.file.path")),
"base_url": "/media/",
"base_url": CONFIG.get("web.path", "/") + "media/",
},
}
# Compatibility for apps not supporting top-level STORAGES

View File

@ -3,25 +3,46 @@
import os
from argparse import ArgumentParser
from unittest import TestCase
from unittest.mock import patch
import pytest
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.test.runner import DiscoverRunner
from structlog.stdlib import get_logger
from authentik.events.context_processors.asn import ASN_CONTEXT_PROCESSOR
from authentik.events.context_processors.geoip import GEOIP_CONTEXT_PROCESSOR
from authentik.lib.config import CONFIG
from authentik.lib.sentry import sentry_init
from authentik.root.signals import post_startup, pre_startup, startup
from tests.e2e.utils import get_docker_tag
# globally set maxDiff to none to show full assert error
TestCase.maxDiff = None
def get_docker_tag() -> str:
"""Get docker-tag based off of CI variables"""
env_pr_branch = "GITHUB_HEAD_REF"
default_branch = "GITHUB_REF"
branch_name = os.environ.get(default_branch, "main")
if os.environ.get(env_pr_branch, "") != "":
branch_name = os.environ[env_pr_branch]
branch_name = branch_name.replace("refs/heads/", "").replace("/", "-")
return f"gh-{branch_name}"
def patched__get_ct_cached(app_label, codename):
"""Caches `ContentType` instances like its `QuerySet` does."""
return ContentType.objects.get(app_label=app_label, permission__codename=codename)
class PytestTestRunner(DiscoverRunner): # pragma: no cover
"""Runs pytest to discover and run tests."""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.logger = get_logger().bind(runner="pytest")
self.args = []
if self.failfast:
@ -31,6 +52,8 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
if kwargs.get("randomly_seed", None):
self.args.append(f"--randomly-seed={kwargs['randomly_seed']}")
if kwargs.get("no_capture", False):
self.args.append("--capture=no")
settings.TEST = True
settings.CELERY["task_always_eager"] = True
@ -46,6 +69,10 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
CONFIG.set("error_reporting.sample_rate", 0)
CONFIG.set("error_reporting.environment", "testing")
CONFIG.set("error_reporting.send_pii", True)
ASN_CONTEXT_PROCESSOR.load()
GEOIP_CONTEXT_PROCESSOR.load()
sentry_init()
pre_startup.send(sender=self, mode="test")
@ -64,6 +91,11 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
"Default behaviour: use random.Random().getrandbits(32), so the seed is"
"different on each run.",
)
parser.add_argument(
"--no-capture",
action="store_true",
help="Disable any capturing of stdout/stderr during tests.",
)
def run_tests(self, test_labels, extra_tests=None, **kwargs):
"""Run pytest and return the exitcode.
@ -106,4 +138,10 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
f"path instead."
)
return pytest.main(self.args)
self.logger.info("Running tests", test_files=self.args)
with patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached):
try:
return pytest.main(self.args)
except Exception as e:
self.logger.error("Error running tests", error=str(e), test_files=self.args)
return 1

View File

@ -103,6 +103,7 @@ class LDAPSourceSerializer(SourceSerializer):
"user_object_filter",
"group_object_filter",
"group_membership_field",
"user_membership_attribute",
"object_uniqueness_field",
"password_login_update_internal_password",
"sync_users",
@ -111,6 +112,7 @@ class LDAPSourceSerializer(SourceSerializer):
"sync_parent_group",
"connectivity",
"lookup_groups_from_user",
"delete_not_found_objects",
]
extra_kwargs = {"bind_password": {"write_only": True}}
@ -138,6 +140,7 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
"user_object_filter",
"group_object_filter",
"group_membership_field",
"user_membership_attribute",
"object_uniqueness_field",
"password_login_update_internal_password",
"sync_users",
@ -147,6 +150,7 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
"user_property_mappings",
"group_property_mappings",
"lookup_groups_from_user",
"delete_not_found_objects",
]
search_fields = ["name", "slug"]
ordering = ["name"]

View File

@ -0,0 +1,48 @@
# Generated by Django 5.1.9 on 2025-05-28 08:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0048_delete_oldauthenticatedsession_content_type"),
("authentik_sources_ldap", "0008_groupldapsourceconnection_userldapsourceconnection"),
]
operations = [
migrations.AddField(
model_name="groupldapsourceconnection",
name="validated_by",
field=models.UUIDField(
blank=True,
help_text="Unique ID used while checking if this object still exists in the directory.",
null=True,
),
),
migrations.AddField(
model_name="ldapsource",
name="delete_not_found_objects",
field=models.BooleanField(
default=False,
help_text="Delete authentik users and groups which were previously supplied by this source, but are now missing from it.",
),
),
migrations.AddField(
model_name="userldapsourceconnection",
name="validated_by",
field=models.UUIDField(
blank=True,
help_text="Unique ID used while checking if this object still exists in the directory.",
null=True,
),
),
migrations.AddIndex(
model_name="groupldapsourceconnection",
index=models.Index(fields=["validated_by"], name="authentik_s_validat_b70447_idx"),
),
migrations.AddIndex(
model_name="userldapsourceconnection",
index=models.Index(fields=["validated_by"], name="authentik_s_validat_ff2ebc_idx"),
),
]

View File

@ -0,0 +1,32 @@
# Generated by Django 5.1.9 on 2025-05-29 11:22
from django.apps.registry import Apps
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def set_user_membership_attribute(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
LDAPSource = apps.get_model("authentik_sources_ldap", "LDAPSource")
db_alias = schema_editor.connection.alias
LDAPSource.objects.using(db_alias).filter(group_membership_field="memberUid").all().update(
user_membership_attribute="ldap_uniq"
)
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_ldap", "0009_groupldapsourceconnection_validated_by_and_more"),
]
operations = [
migrations.AddField(
model_name="ldapsource",
name="user_membership_attribute",
field=models.TextField(
default="distinguishedName",
help_text="Attribute which matches the value of `group_membership_field`.",
),
),
migrations.RunPython(set_user_membership_attribute, migrations.RunPython.noop),
]

View File

@ -100,6 +100,10 @@ class LDAPSource(Source):
default="(objectClass=person)",
help_text=_("Consider Objects matching this filter to be Users."),
)
user_membership_attribute = models.TextField(
default=LDAP_DISTINGUISHED_NAME,
help_text=_("Attribute which matches the value of `group_membership_field`."),
)
group_membership_field = models.TextField(
default="member", help_text=_("Field which contains members of a group.")
)
@ -137,6 +141,14 @@ class LDAPSource(Source):
),
)
delete_not_found_objects = models.BooleanField(
default=False,
help_text=_(
"Delete authentik users and groups which were previously supplied by this source, "
"but are now missing from it."
),
)
@property
def component(self) -> str:
return "ak-source-ldap-form"
@ -321,6 +333,12 @@ class LDAPSourcePropertyMapping(PropertyMapping):
class UserLDAPSourceConnection(UserSourceConnection):
validated_by = models.UUIDField(
null=True,
blank=True,
help_text=_("Unique ID used while checking if this object still exists in the directory."),
)
@property
def serializer(self) -> type[Serializer]:
from authentik.sources.ldap.api import (
@ -332,9 +350,18 @@ class UserLDAPSourceConnection(UserSourceConnection):
class Meta:
verbose_name = _("User LDAP Source Connection")
verbose_name_plural = _("User LDAP Source Connections")
indexes = [
models.Index(fields=["validated_by"]),
]
class GroupLDAPSourceConnection(GroupSourceConnection):
validated_by = models.UUIDField(
null=True,
blank=True,
help_text=_("Unique ID used while checking if this object still exists in the directory."),
)
@property
def serializer(self) -> type[Serializer]:
from authentik.sources.ldap.api import (
@ -346,3 +373,6 @@ class GroupLDAPSourceConnection(GroupSourceConnection):
class Meta:
verbose_name = _("Group LDAP Source Connection")
verbose_name_plural = _("Group LDAP Source Connections")
indexes = [
models.Index(fields=["validated_by"]),
]

View File

@ -9,7 +9,7 @@ from structlog.stdlib import BoundLogger, get_logger
from authentik.core.sources.mapper import SourceMapper
from authentik.lib.config import CONFIG
from authentik.lib.sync.mapper import PropertyMappingManager
from authentik.sources.ldap.models import LDAPSource
from authentik.sources.ldap.models import LDAPSource, flatten
class BaseLDAPSynchronizer:
@ -77,6 +77,16 @@ class BaseLDAPSynchronizer:
"""Get objects from LDAP, implemented in subclass"""
raise NotImplementedError()
def get_attributes(self, object):
if "attributes" not in object:
return
return object.get("attributes", {})
def get_identifier(self, attributes: dict):
if not attributes.get(self._source.object_uniqueness_field):
return
return flatten(attributes[self._source.object_uniqueness_field])
def search_paginator( # noqa: PLR0913
self,
search_base,

View File

@ -0,0 +1,61 @@
from collections.abc import Generator
from itertools import batched
from uuid import uuid4
from ldap3 import SUBTREE
from authentik.core.models import Group
from authentik.sources.ldap.models import GroupLDAPSourceConnection
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
from authentik.sources.ldap.sync.forward_delete_users import DELETE_CHUNK_SIZE, UPDATE_CHUNK_SIZE
class GroupLDAPForwardDeletion(BaseLDAPSynchronizer):
"""Delete LDAP Groups from authentik"""
@staticmethod
def name() -> str:
return "group_deletions"
def get_objects(self, **kwargs) -> Generator:
if not self._source.sync_groups or not self._source.delete_not_found_objects:
self.message("Group syncing is disabled for this Source")
return iter(())
uuid = uuid4()
groups = self._source.connection().extend.standard.paged_search(
search_base=self.base_dn_groups,
search_filter=self._source.group_object_filter,
search_scope=SUBTREE,
attributes=[self._source.object_uniqueness_field],
generator=True,
**kwargs,
)
for batch in batched(groups, UPDATE_CHUNK_SIZE, strict=False):
identifiers = []
for group in batch:
if not (attributes := self.get_attributes(group)):
continue
if identifier := self.get_identifier(attributes):
identifiers.append(identifier)
GroupLDAPSourceConnection.objects.filter(identifier__in=identifiers).update(
validated_by=uuid
)
return batched(
GroupLDAPSourceConnection.objects.filter(source=self._source)
.exclude(validated_by=uuid)
.values_list("group", flat=True)
.iterator(chunk_size=DELETE_CHUNK_SIZE),
DELETE_CHUNK_SIZE,
strict=False,
)
def sync(self, group_pks: tuple) -> int:
"""Delete authentik groups"""
if not self._source.sync_groups or not self._source.delete_not_found_objects:
self.message("Group syncing is disabled for this Source")
return -1
self._logger.debug("Deleting groups", group_pks=group_pks)
_, deleted_per_type = Group.objects.filter(pk__in=group_pks).delete()
return deleted_per_type.get(Group._meta.label, 0)

View File

@ -0,0 +1,63 @@
from collections.abc import Generator
from itertools import batched
from uuid import uuid4
from ldap3 import SUBTREE
from authentik.core.models import User
from authentik.sources.ldap.models import UserLDAPSourceConnection
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
UPDATE_CHUNK_SIZE = 10_000
DELETE_CHUNK_SIZE = 50
class UserLDAPForwardDeletion(BaseLDAPSynchronizer):
"""Delete LDAP Users from authentik"""
@staticmethod
def name() -> str:
return "user_deletions"
def get_objects(self, **kwargs) -> Generator:
if not self._source.sync_users or not self._source.delete_not_found_objects:
self.message("User syncing is disabled for this Source")
return iter(())
uuid = uuid4()
users = self._source.connection().extend.standard.paged_search(
search_base=self.base_dn_users,
search_filter=self._source.user_object_filter,
search_scope=SUBTREE,
attributes=[self._source.object_uniqueness_field],
generator=True,
**kwargs,
)
for batch in batched(users, UPDATE_CHUNK_SIZE, strict=False):
identifiers = []
for user in batch:
if not (attributes := self.get_attributes(user)):
continue
if identifier := self.get_identifier(attributes):
identifiers.append(identifier)
UserLDAPSourceConnection.objects.filter(identifier__in=identifiers).update(
validated_by=uuid
)
return batched(
UserLDAPSourceConnection.objects.filter(source=self._source)
.exclude(validated_by=uuid)
.values_list("user", flat=True)
.iterator(chunk_size=DELETE_CHUNK_SIZE),
DELETE_CHUNK_SIZE,
strict=False,
)
def sync(self, user_pks: tuple) -> int:
"""Delete authentik users"""
if not self._source.sync_users or not self._source.delete_not_found_objects:
self.message("User syncing is disabled for this Source")
return -1
self._logger.debug("Deleting users", user_pks=user_pks)
_, deleted_per_type = User.objects.filter(pk__in=user_pks).delete()
return deleted_per_type.get(User._meta.label, 0)

View File

@ -58,18 +58,16 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
return -1
group_count = 0
for group in page_data:
if "attributes" not in group:
if (attributes := self.get_attributes(group)) is None:
continue
attributes = group.get("attributes", {})
group_dn = flatten(flatten(group.get("entryDN", group.get("dn"))))
if not attributes.get(self._source.object_uniqueness_field):
if not (uniq := self.get_identifier(attributes)):
self.message(
f"Uniqueness field not found/not set in attributes: '{group_dn}'",
attributes=attributes.keys(),
dn=group_dn,
)
continue
uniq = flatten(attributes[self._source.object_uniqueness_field])
try:
defaults = {
k: flatten(v)

View File

@ -63,25 +63,19 @@ class MembershipLDAPSynchronizer(BaseLDAPSynchronizer):
group_member_dn = group_member.get("dn", {})
members.append(group_member_dn)
else:
if "attributes" not in group:
if (attributes := self.get_attributes(group)) is None:
continue
members = group.get("attributes", {}).get(self._source.group_membership_field, [])
members = attributes.get(self._source.group_membership_field, [])
ak_group = self.get_group(group)
if not ak_group:
continue
membership_mapping_attribute = LDAP_DISTINGUISHED_NAME
if self._source.group_membership_field == "memberUid":
# If memberships are based on the posixGroup's 'memberUid'
# attribute we use the RDN instead of the FDN to lookup members.
membership_mapping_attribute = LDAP_UNIQUENESS
users = User.objects.filter(
Q(**{f"attributes__{membership_mapping_attribute}__in": members})
Q(**{f"attributes__{self._source.user_membership_attribute}__in": members})
| Q(
**{
f"attributes__{membership_mapping_attribute}__isnull": True,
f"attributes__{self._source.user_membership_attribute}__isnull": True,
"ak_groups__in": [ak_group],
}
)

View File

@ -60,18 +60,16 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
return -1
user_count = 0
for user in page_data:
if "attributes" not in user:
if (attributes := self.get_attributes(user)) is None:
continue
attributes = user.get("attributes", {})
user_dn = flatten(user.get("entryDN", user.get("dn")))
if not attributes.get(self._source.object_uniqueness_field):
if not (uniq := self.get_identifier(attributes)):
self.message(
f"Uniqueness field not found/not set in attributes: '{user_dn}'",
attributes=attributes.keys(),
dn=user_dn,
)
continue
uniq = flatten(attributes[self._source.object_uniqueness_field])
try:
defaults = {
k: flatten(v)

View File

@ -17,6 +17,8 @@ from authentik.lib.utils.reflection import class_to_path, path_to_class
from authentik.root.celery import CELERY_APP
from authentik.sources.ldap.models import LDAPSource
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
from authentik.sources.ldap.sync.forward_delete_groups import GroupLDAPForwardDeletion
from authentik.sources.ldap.sync.forward_delete_users import UserLDAPForwardDeletion
from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer
from authentik.sources.ldap.sync.membership import MembershipLDAPSynchronizer
from authentik.sources.ldap.sync.users import UserLDAPSynchronizer
@ -52,11 +54,11 @@ def ldap_connectivity_check(pk: str | None = None):
@CELERY_APP.task(
# We take the configured hours timeout time by 2.5 as we run user and
# group in parallel and then membership, so 2x is to cover the serial tasks,
# We take the configured hours timeout time by 3.5 as we run user and
# group in parallel and then membership, then deletions, so 3x is to cover the serial tasks,
# and 0.5x on top of that to give some more leeway
soft_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 2.5,
task_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 2.5,
soft_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3.5,
task_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3.5,
)
def ldap_sync_single(source_pk: str):
"""Sync a single source"""
@ -69,18 +71,31 @@ def ldap_sync_single(source_pk: str):
return
# Delete all sync tasks from the cache
DBSystemTask.objects.filter(name="ldap_sync", uid__startswith=source.slug).delete()
task = chain(
# User and group sync can happen at once, they have no dependencies on each other
group(
ldap_sync_paginator(source, UserLDAPSynchronizer)
+ ldap_sync_paginator(source, GroupLDAPSynchronizer),
),
# Membership sync needs to run afterwards
group(
ldap_sync_paginator(source, MembershipLDAPSynchronizer),
),
# The order of these operations needs to be preserved as each depends on the previous one(s)
# 1. User and group sync can happen simultaneously
# 2. Membership sync needs to run afterwards
# 3. Finally, user and group deletions can happen simultaneously
user_group_sync = ldap_sync_paginator(source, UserLDAPSynchronizer) + ldap_sync_paginator(
source, GroupLDAPSynchronizer
)
task()
membership_sync = ldap_sync_paginator(source, MembershipLDAPSynchronizer)
user_group_deletion = ldap_sync_paginator(
source, UserLDAPForwardDeletion
) + ldap_sync_paginator(source, GroupLDAPForwardDeletion)
# Celery is buggy with empty groups, so we are careful only to add non-empty groups.
# See https://github.com/celery/celery/issues/9772
task_groups = []
if user_group_sync:
task_groups.append(group(user_group_sync))
if membership_sync:
task_groups.append(group(membership_sync))
if user_group_deletion:
task_groups.append(group(user_group_deletion))
all_tasks = chain(task_groups)
all_tasks()
def ldap_sync_paginator(source: LDAPSource, sync: type[BaseLDAPSynchronizer]) -> list:

View File

@ -2,6 +2,33 @@
from ldap3 import MOCK_SYNC, OFFLINE_SLAPD_2_4, Connection, Server
# The mock modifies these in place, so we have to define them per string
user_in_slapd_dn = "cn=user_in_slapd_cn,ou=users,dc=goauthentik,dc=io"
user_in_slapd_cn = "user_in_slapd_cn"
user_in_slapd_uid = "user_in_slapd_uid"
user_in_slapd_object_class = "person"
user_in_slapd = {
"dn": user_in_slapd_dn,
"attributes": {
"cn": user_in_slapd_cn,
"uid": user_in_slapd_uid,
"objectClass": user_in_slapd_object_class,
},
}
group_in_slapd_dn = "cn=user_in_slapd_cn,ou=groups,dc=goauthentik,dc=io"
group_in_slapd_cn = "group_in_slapd_cn"
group_in_slapd_uid = "group_in_slapd_uid"
group_in_slapd_object_class = "groupOfNames"
group_in_slapd = {
"dn": group_in_slapd_dn,
"attributes": {
"cn": group_in_slapd_cn,
"uid": group_in_slapd_uid,
"objectClass": group_in_slapd_object_class,
"member": [user_in_slapd["dn"]],
},
}
def mock_slapd_connection(password: str) -> Connection:
"""Create mock SLAPD connection"""
@ -96,5 +123,14 @@ def mock_slapd_connection(password: str) -> Connection:
"objectClass": "posixAccount",
},
)
# Known user and group
connection.strategy.add_entry(
user_in_slapd["dn"],
user_in_slapd["attributes"],
)
connection.strategy.add_entry(
group_in_slapd["dn"],
group_in_slapd["attributes"],
)
connection.bind()
return connection

View File

@ -13,14 +13,26 @@ from authentik.events.system_tasks import TaskStatus
from authentik.lib.generators import generate_id, generate_key
from authentik.lib.sync.outgoing.exceptions import StopSync
from authentik.lib.utils.reflection import class_to_path
from authentik.sources.ldap.models import LDAPSource, LDAPSourcePropertyMapping
from authentik.sources.ldap.models import (
GroupLDAPSourceConnection,
LDAPSource,
LDAPSourcePropertyMapping,
UserLDAPSourceConnection,
)
from authentik.sources.ldap.sync.forward_delete_users import DELETE_CHUNK_SIZE
from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer
from authentik.sources.ldap.sync.membership import MembershipLDAPSynchronizer
from authentik.sources.ldap.sync.users import UserLDAPSynchronizer
from authentik.sources.ldap.tasks import ldap_sync, ldap_sync_all
from authentik.sources.ldap.tests.mock_ad import mock_ad_connection
from authentik.sources.ldap.tests.mock_freeipa import mock_freeipa_connection
from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection
from authentik.sources.ldap.tests.mock_slapd import (
group_in_slapd_cn,
group_in_slapd_uid,
mock_slapd_connection,
user_in_slapd_cn,
user_in_slapd_uid,
)
LDAP_PASSWORD = generate_key()
@ -257,12 +269,56 @@ class LDAPSyncTests(TestCase):
self.source.group_membership_field = "memberUid"
self.source.user_object_filter = "(objectClass=posixAccount)"
self.source.group_object_filter = "(objectClass=posixGroup)"
self.source.user_membership_attribute = "uid"
self.source.user_property_mappings.set(
[
*LDAPSourcePropertyMapping.objects.filter(
Q(managed__startswith="goauthentik.io/sources/ldap/default")
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
).all(),
LDAPSourcePropertyMapping.objects.create(
name="name",
expression='return {"attributes": {"uid": list_flatten(ldap.get("uid"))}}',
),
]
)
self.source.group_property_mappings.set(
LDAPSourcePropertyMapping.objects.filter(
Q(managed__startswith="goauthentik.io/sources/ldap/default")
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
managed="goauthentik.io/sources/ldap/openldap-cn"
)
)
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
self.source.save()
user_sync = UserLDAPSynchronizer(self.source)
user_sync.sync_full()
group_sync = GroupLDAPSynchronizer(self.source)
group_sync.sync_full()
membership_sync = MembershipLDAPSynchronizer(self.source)
membership_sync.sync_full()
# Test if membership mapping based on memberUid works.
posix_group = Group.objects.filter(name="group-posix").first()
self.assertTrue(posix_group.users.filter(name="user-posix").exists())
def test_sync_groups_openldap_posix_group_nonstandard_membership_attribute(self):
"""Test posix group sync"""
self.source.object_uniqueness_field = "cn"
self.source.group_membership_field = "memberUid"
self.source.user_object_filter = "(objectClass=posixAccount)"
self.source.group_object_filter = "(objectClass=posixGroup)"
self.source.user_membership_attribute = "cn"
self.source.user_property_mappings.set(
[
*LDAPSourcePropertyMapping.objects.filter(
Q(managed__startswith="goauthentik.io/sources/ldap/default")
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
).all(),
LDAPSourcePropertyMapping.objects.create(
name="name",
expression='return {"attributes": {"cn": list_flatten(ldap.get("cn"))}}',
),
]
)
self.source.group_property_mappings.set(
LDAPSourcePropertyMapping.objects.filter(
managed="goauthentik.io/sources/ldap/openldap-cn"
@ -308,3 +364,160 @@ class LDAPSyncTests(TestCase):
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
def test_user_deletion(self):
"""Test user deletion"""
user = User.objects.create_user(username="not-in-the-source")
UserLDAPSourceConnection.objects.create(
user=user, source=self.source, identifier="not-in-the-source"
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.delete_not_found_objects = True
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertFalse(User.objects.filter(username="not-in-the-source").exists())
def test_user_deletion_still_in_source(self):
"""Test that user is not deleted if it's still in the source"""
username = user_in_slapd_cn
identifier = user_in_slapd_uid
user = User.objects.create_user(username=username)
UserLDAPSourceConnection.objects.create(
user=user, source=self.source, identifier=identifier
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.delete_not_found_objects = True
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertTrue(User.objects.filter(username=username).exists())
def test_user_deletion_no_sync(self):
"""Test that user is not deleted if sync_users is False"""
user = User.objects.create_user(username="not-in-the-source")
UserLDAPSourceConnection.objects.create(
user=user, source=self.source, identifier="not-in-the-source"
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.delete_not_found_objects = True
self.source.sync_users = False
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertTrue(User.objects.filter(username="not-in-the-source").exists())
def test_user_deletion_no_delete(self):
"""Test that user is not deleted if delete_not_found_objects is False"""
user = User.objects.create_user(username="not-in-the-source")
UserLDAPSourceConnection.objects.create(
user=user, source=self.source, identifier="not-in-the-source"
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertTrue(User.objects.filter(username="not-in-the-source").exists())
def test_group_deletion(self):
"""Test group deletion"""
group = Group.objects.create(name="not-in-the-source")
GroupLDAPSourceConnection.objects.create(
group=group, source=self.source, identifier="not-in-the-source"
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.delete_not_found_objects = True
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertFalse(Group.objects.filter(name="not-in-the-source").exists())
def test_group_deletion_still_in_source(self):
"""Test that group is not deleted if it's still in the source"""
groupname = group_in_slapd_cn
identifier = group_in_slapd_uid
group = Group.objects.create(name=groupname)
GroupLDAPSourceConnection.objects.create(
group=group, source=self.source, identifier=identifier
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.delete_not_found_objects = True
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertTrue(Group.objects.filter(name=groupname).exists())
def test_group_deletion_no_sync(self):
"""Test that group is not deleted if sync_groups is False"""
group = Group.objects.create(name="not-in-the-source")
GroupLDAPSourceConnection.objects.create(
group=group, source=self.source, identifier="not-in-the-source"
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.delete_not_found_objects = True
self.source.sync_groups = False
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertTrue(Group.objects.filter(name="not-in-the-source").exists())
def test_group_deletion_no_delete(self):
"""Test that group is not deleted if delete_not_found_objects is False"""
group = Group.objects.create(name="not-in-the-source")
GroupLDAPSourceConnection.objects.create(
group=group, source=self.source, identifier="not-in-the-source"
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertTrue(Group.objects.filter(name="not-in-the-source").exists())
def test_batch_deletion(self):
"""Test batch deletion"""
BATCH_SIZE = DELETE_CHUNK_SIZE + 1
for i in range(BATCH_SIZE):
user = User.objects.create_user(username=f"not-in-the-source-{i}")
group = Group.objects.create(name=f"not-in-the-source-{i}")
group.users.add(user)
UserLDAPSourceConnection.objects.create(
user=user, source=self.source, identifier=f"not-in-the-source-{i}-user"
)
GroupLDAPSourceConnection.objects.create(
group=group, source=self.source, identifier=f"not-in-the-source-{i}-group"
)
self.source.object_uniqueness_field = "uid"
self.source.group_object_filter = "(objectClass=groupOfNames)"
self.source.delete_not_found_objects = True
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
ldap_sync_all.delay().get()
self.assertFalse(User.objects.filter(username__startswith="not-in-the-source").exists())
self.assertFalse(Group.objects.filter(name__startswith="not-in-the-source").exists())

View File

@ -9,6 +9,7 @@ from django.http.response import HttpResponseBadRequest
from django.shortcuts import get_object_or_404, redirect
from django.utils.decorators import method_decorator
from django.utils.http import urlencode
from django.utils.translation import gettext as _
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from structlog.stdlib import get_logger
@ -128,7 +129,9 @@ class InitiateView(View):
# otherwise we default to POST_AUTO, with direct redirect
if source.binding_type == SAMLBindingTypes.POST:
injected_stages.append(in_memory_stage(ConsentStageView))
plan_kwargs[PLAN_CONTEXT_CONSENT_HEADER] = f"Continue to {source.name}"
plan_kwargs[PLAN_CONTEXT_CONSENT_HEADER] = _(
"Continue to {source_name}".format(source_name=source.name)
)
injected_stages.append(in_memory_stage(AutosubmitStageView))
return self.handle_login_flow(
source,

View File

@ -97,7 +97,8 @@ class GroupsView(SCIMObjectView):
self.logger.warning("Invalid group member", exc=exc)
continue
query |= Q(uuid=member.value)
group.users.set(User.objects.filter(query))
if query:
group.users.set(User.objects.filter(query))
if not connection:
connection, _ = SCIMSourceGroup.objects.get_or_create(
source=self.source,

View File

@ -151,9 +151,7 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase):
webauthn_user_verification=UserVerification.PREFERRED,
)
stage.webauthn_allowed_device_types.set(
WebAuthnDeviceType.objects.filter(
description="Android Authenticator with SafetyNet Attestation"
)
WebAuthnDeviceType.objects.filter(description="YubiKey 5 Series")
)
session = self.client.session
plan = FlowPlan(flow_pk=flow.pk.hex)
@ -339,9 +337,7 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase):
device_classes=[DeviceClasses.WEBAUTHN],
)
stage.webauthn_allowed_device_types.set(
WebAuthnDeviceType.objects.filter(
description="Android Authenticator with SafetyNet Attestation"
)
WebAuthnDeviceType.objects.filter(description="YubiKey 5 Series")
)
session = self.client.session
plan = FlowPlan(flow_pk=flow.pk.hex)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -141,9 +141,7 @@ class TestAuthenticatorWebAuthnStage(FlowTestCase):
"""Test registration with restricted devices (fail)"""
webauthn_mds_import.delay(force=True).get()
self.stage.device_type_restrictions.set(
WebAuthnDeviceType.objects.filter(
description="Android Authenticator with SafetyNet Attestation"
)
WebAuthnDeviceType.objects.filter(description="YubiKey 5 Series")
)
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])

View File

@ -4,6 +4,8 @@ from uuid import uuid4
from django.http import HttpRequest, HttpResponse
from django.utils.timezone import now
from django.utils.translation import gettext as _
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField
from authentik.core.api.utils import PassiveSerializer
@ -47,6 +49,11 @@ class ConsentChallengeResponse(ChallengeResponse):
component = CharField(default="ak-stage-consent")
token = CharField(required=True)
def validate_token(self, token: str):
if token != self.stage.executor.request.session[SESSION_KEY_CONSENT_TOKEN]:
raise ValidationError(_("Invalid consent token, re-showing prompt"))
return token
class ConsentStageView(ChallengeStageView):
"""Simple consent checker."""
@ -120,9 +127,6 @@ class ConsentStageView(ChallengeStageView):
return super().get(request, *args, **kwargs)
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
if response.data["token"] != self.request.session[SESSION_KEY_CONSENT_TOKEN]:
self.logger.info("Invalid consent token, re-showing prompt")
return self.get(self.request)
if self.should_always_prompt():
return self.executor.stage_ok()
current_stage: ConsentStage = self.executor.current_stage

View File

@ -17,6 +17,7 @@ from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.generators import generate_id
from authentik.stages.consent.models import ConsentMode, ConsentStage, UserConsent
from authentik.stages.consent.stage import (
PLAN_CONTEXT_CONSENT_HEADER,
PLAN_CONTEXT_CONSENT_PERMISSIONS,
SESSION_KEY_CONSENT_TOKEN,
)
@ -33,6 +34,40 @@ class TestConsentStage(FlowTestCase):
slug=generate_id(),
)
def test_mismatched_token(self):
"""Test incorrect token"""
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
stage = ConsentStage.objects.create(name=generate_id(), mode=ConsentMode.ALWAYS_REQUIRE)
binding = FlowStageBinding.objects.create(target=flow, stage=stage, order=2)
plan = FlowPlan(flow_pk=flow.pk.hex, bindings=[binding], markers=[StageMarker()])
session = self.client.session
session[SESSION_KEY_PLAN] = plan
session.save()
response = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
)
self.assertEqual(response.status_code, 200)
session = self.client.session
response = self.client.post(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
{
"token": generate_id(),
},
)
self.assertEqual(response.status_code, 200)
self.assertStageResponse(
response,
flow,
component="ak-stage-consent",
response_errors={
"token": [{"string": "Invalid consent token, re-showing prompt", "code": "invalid"}]
},
)
self.assertFalse(UserConsent.objects.filter(user=self.user).exists())
def test_always_required(self):
"""Test always required consent"""
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
@ -158,6 +193,7 @@ class TestConsentStage(FlowTestCase):
context={
PLAN_CONTEXT_APPLICATION: self.application,
PLAN_CONTEXT_CONSENT_PERMISSIONS: [PermissionDict(id="foo", name="foo-desc")],
PLAN_CONTEXT_CONSENT_HEADER: "test header",
},
)
session = self.client.session

View File

@ -0,0 +1,38 @@
from base64 import b64encode
from copy import deepcopy
from pickle import dumps # nosec
from django.utils.translation import gettext as _
from authentik.flows.models import FlowToken, in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED, FlowPlan
from authentik.stages.consent.stage import PLAN_CONTEXT_CONSENT_HEADER, ConsentStageView
def pickle_flow_token_for_email(plan: FlowPlan):
"""Insert a consent stage into the flow plan and pickle it for a FlowToken,
to be sent via Email. This is to prevent automated email scanners, which sometimes
open links in emails in a full browser from breaking the link."""
plan_copy = deepcopy(plan)
plan_copy.insert_stage(in_memory_stage(EmailTokenRevocationConsentStageView), index=0)
plan_copy.context[PLAN_CONTEXT_CONSENT_HEADER] = _("Continue to confirm this email address.")
data = dumps(plan_copy)
return b64encode(data).decode()
class EmailTokenRevocationConsentStageView(ConsentStageView):
def get(self, request, *args, **kwargs):
token: FlowToken = self.executor.plan.context[PLAN_CONTEXT_IS_RESTORED]
try:
token.refresh_from_db()
except FlowToken.DoesNotExist:
return self.executor.stage_invalid(
_("Link was already used, please request a new link.")
)
return super().get(request, *args, **kwargs)
def challenge_valid(self, response):
token: FlowToken = self.executor.plan.context[PLAN_CONTEXT_IS_RESTORED]
token.delete()
return super().challenge_valid(response)

View File

@ -23,6 +23,7 @@ from authentik.flows.stage import ChallengeStageView
from authentik.flows.views.executor import QS_KEY_TOKEN, QS_QUERY
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.time import timedelta_from_string
from authentik.stages.email.flow import pickle_flow_token_for_email
from authentik.stages.email.models import EmailStage
from authentik.stages.email.tasks import send_mails
from authentik.stages.email.utils import TemplateEmailMessage
@ -86,7 +87,8 @@ class EmailStageView(ChallengeStageView):
user=pending_user,
identifier=identifier,
flow=self.executor.flow,
_plan=FlowToken.pickle(self.executor.plan),
_plan=pickle_flow_token_for_email(self.executor.plan),
revoke_on_execution=False,
)
token = tokens.first()
# Check if token is expired and rotate key if so

View File

@ -100,9 +100,11 @@ def send_mail(
# Because we use the Message-ID as UID for the task, manually assign it
message_object.extra_headers["Message-ID"] = message_id
# Add the logo (we can't add it in the previous message since MIMEImage
# can't be converted to json)
message_object.attach(logo_data())
# Add the logo if it is used in the email body (we can't add it in the
# previous message since MIMEImage can't be converted to json)
body = get_email_body(message_object)
if "cid:logo" in body:
message_object.attach(logo_data())
if (
message_object.to

View File

@ -96,7 +96,7 @@
<table width="100%" style="background-color: #FFFFFF; border-spacing: 0; margin-top: 15px;">
<tr height="80">
<td align="center" style="padding: 20px 0;">
<img src="{% block logo_url %}cid:logo.png{% endblock %}" border="0=" alt="authentik logo" class="flexibleImage logo">
<img src="{% block logo_url %}cid:logo{% endblock %}" border="0=" alt="authentik logo" class="flexibleImage logo">
</td>
</tr>
{% block content %}

View File

@ -174,5 +174,5 @@ class TestEmailStageSending(FlowTestCase):
response = self.client.post(url)
response = self.client.post(url)
self.assertEqual(response.status_code, 200)
self.assertTrue(len(mail.outbox) >= 1)
self.assertGreaterEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, "authentik")

View File

@ -17,6 +17,7 @@ from authentik.flows.tests import FlowTestCase
from authentik.flows.views.executor import QS_KEY_TOKEN, SESSION_KEY_PLAN, FlowExecutorView
from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id
from authentik.stages.consent.stage import SESSION_KEY_CONSENT_TOKEN
from authentik.stages.email.models import EmailStage
from authentik.stages.email.stage import PLAN_CONTEXT_EMAIL_OVERRIDE, EmailStageView
@ -160,6 +161,17 @@ class TestEmailStage(FlowTestCase):
kwargs={"flow_slug": self.flow.slug},
)
)
self.assertStageResponse(response, self.flow, component="ak-stage-consent")
response = self.client.post(
reverse(
"authentik_api:flow-executor",
kwargs={"flow_slug": self.flow.slug},
),
data={
"token": self.client.session[SESSION_KEY_CONSENT_TOKEN],
},
follow=True,
)
self.assertEqual(response.status_code, 200)
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
@ -182,6 +194,7 @@ class TestEmailStage(FlowTestCase):
# Set flow token user to a different user
token: FlowToken = FlowToken.objects.get(user=self.user)
token.user = create_test_admin_user()
token.revoke_on_execution = True
token.save()
with patch("authentik.flows.views.executor.FlowExecutorView.cancel", MagicMock()):

View File

@ -19,7 +19,8 @@ def logo_data() -> MIMEImage:
path = Path("web/dist/assets/icons/icon_left_brand.png")
with open(path, "rb") as _logo_file:
logo = MIMEImage(_logo_file.read())
logo.add_header("Content-ID", "logo.png")
logo.add_header("Content-ID", "<logo>")
logo.add_header("Content-Disposition", "inline", filename="logo.png")
return logo

View File

@ -101,9 +101,9 @@ class BoundSessionMiddleware(SessionMiddleware):
SESSION_KEY_BINDING_GEO, GeoIPBinding.NO_BINDING
)
if configured_binding_net != NetworkBinding.NO_BINDING:
self.recheck_session_net(configured_binding_net, last_ip, new_ip)
BoundSessionMiddleware.recheck_session_net(configured_binding_net, last_ip, new_ip)
if configured_binding_geo != GeoIPBinding.NO_BINDING:
self.recheck_session_geo(configured_binding_geo, last_ip, new_ip)
BoundSessionMiddleware.recheck_session_geo(configured_binding_geo, last_ip, new_ip)
# If we got to this point without any error being raised, we need to
# update the last saved IP to the current one
if SESSION_KEY_BINDING_NET in request.session or SESSION_KEY_BINDING_GEO in request.session:
@ -111,7 +111,8 @@ class BoundSessionMiddleware(SessionMiddleware):
# (== basically requires the user to be logged in)
request.session[request.session.model.Keys.LAST_IP] = new_ip
def recheck_session_net(self, binding: NetworkBinding, last_ip: str, new_ip: str):
@staticmethod
def recheck_session_net(binding: NetworkBinding, last_ip: str, new_ip: str):
"""Check network/ASN binding"""
last_asn = ASN_CONTEXT_PROCESSOR.asn(last_ip)
new_asn = ASN_CONTEXT_PROCESSOR.asn(new_ip)
@ -158,7 +159,8 @@ class BoundSessionMiddleware(SessionMiddleware):
new_ip,
)
def recheck_session_geo(self, binding: GeoIPBinding, last_ip: str, new_ip: str):
@staticmethod
def recheck_session_geo(binding: GeoIPBinding, last_ip: str, new_ip: str):
"""Check GeoIP binding"""
last_geo = GEOIP_CONTEXT_PROCESSOR.city(last_ip)
new_geo = GEOIP_CONTEXT_PROCESSOR.city(new_ip)
@ -179,8 +181,8 @@ class BoundSessionMiddleware(SessionMiddleware):
if last_geo.continent != new_geo.continent:
raise SessionBindingBroken(
"geoip.continent",
last_geo.continent,
new_geo.continent,
last_geo.continent.to_dict(),
new_geo.continent.to_dict(),
last_ip,
new_ip,
)
@ -192,8 +194,8 @@ class BoundSessionMiddleware(SessionMiddleware):
if last_geo.country != new_geo.country:
raise SessionBindingBroken(
"geoip.country",
last_geo.country,
new_geo.country,
last_geo.country.to_dict(),
new_geo.country.to_dict(),
last_ip,
new_ip,
)
@ -202,8 +204,8 @@ class BoundSessionMiddleware(SessionMiddleware):
if last_geo.city != new_geo.city:
raise SessionBindingBroken(
"geoip.city",
last_geo.city,
new_geo.city,
last_geo.city.to_dict(),
new_geo.city.to_dict(),
last_ip,
new_ip,
)

View File

@ -11,7 +11,7 @@ from rest_framework.fields import BooleanField, CharField
from authentik.core.models import Session, User
from authentik.events.middleware import audit_ignore
from authentik.flows.challenge import ChallengeResponse, WithUserInfoChallenge
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, PLAN_CONTEXT_SOURCE
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
from authentik.flows.stage import ChallengeStageView
from authentik.lib.utils.time import timedelta_from_string
from authentik.root.middleware import ClientIPMiddleware
@ -108,10 +108,6 @@ class UserLoginStageView(ChallengeStageView):
flow_slug=self.executor.flow.slug,
session_duration=delta,
)
# Only show success message if we don't have a source in the flow
# as sources show their own success messages
if not self.executor.plan.context.get(PLAN_CONTEXT_SOURCE, None):
messages.success(self.request, _("Successfully logged in!"))
if self.executor.current_stage.terminate_other_sessions:
Session.objects.filter(
authenticatedsession__user=user,

View File

@ -3,6 +3,7 @@
from time import sleep
from unittest.mock import patch
from django.http import HttpRequest
from django.urls import reverse
from django.utils.timezone import now
@ -17,7 +18,12 @@ from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.generators import generate_id
from authentik.lib.utils.time import timedelta_from_string
from authentik.root.middleware import ClientIPMiddleware
from authentik.stages.user_login.models import UserLoginStage
from authentik.stages.user_login.middleware import (
BoundSessionMiddleware,
SessionBindingBroken,
logout_extra,
)
from authentik.stages.user_login.models import GeoIPBinding, NetworkBinding, UserLoginStage
class TestUserLoginStage(FlowTestCase):
@ -192,3 +198,52 @@ class TestUserLoginStage(FlowTestCase):
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
response = self.client.get(reverse("authentik_api:application-list"))
self.assertEqual(response.status_code, 403)
def test_binding_net_break_log(self):
"""Test logout_extra with exception"""
# IPs from https://github.com/maxmind/MaxMind-DB/blob/main/source-data/GeoLite2-ASN-Test.json
for args, expect in [
[[NetworkBinding.BIND_ASN, "8.8.8.8", "8.8.8.8"], ["network.missing"]],
[[NetworkBinding.BIND_ASN, "1.0.0.1", "1.128.0.1"], ["network.asn"]],
[
[NetworkBinding.BIND_ASN_NETWORK, "12.81.96.1", "12.81.128.1"],
["network.asn_network"],
],
[[NetworkBinding.BIND_ASN_NETWORK_IP, "1.0.0.1", "1.0.0.2"], ["network.ip"]],
]:
with self.subTest(args[0]):
with self.assertRaises(SessionBindingBroken) as cm:
BoundSessionMiddleware.recheck_session_net(*args)
self.assertEqual(cm.exception.reason, expect[0])
# Ensure the request can be logged without throwing errors
self.client.force_login(self.user)
request = HttpRequest()
request.session = self.client.session
request.user = self.user
logout_extra(request, cm.exception)
def test_binding_geo_break_log(self):
"""Test logout_extra with exception"""
# IPs from https://github.com/maxmind/MaxMind-DB/blob/main/source-data/GeoLite2-City-Test.json
for args, expect in [
[[GeoIPBinding.BIND_CONTINENT, "8.8.8.8", "8.8.8.8"], ["geoip.missing"]],
[[GeoIPBinding.BIND_CONTINENT, "2.125.160.216", "67.43.156.1"], ["geoip.continent"]],
[
[GeoIPBinding.BIND_CONTINENT_COUNTRY, "81.2.69.142", "89.160.20.112"],
["geoip.country"],
],
[
[GeoIPBinding.BIND_CONTINENT_COUNTRY_CITY, "2.125.160.216", "81.2.69.142"],
["geoip.city"],
],
]:
with self.subTest(args[0]):
with self.assertRaises(SessionBindingBroken) as cm:
BoundSessionMiddleware.recheck_session_geo(*args)
self.assertEqual(cm.exception.reason, expect[0])
# Ensure the request can be logged without throwing errors
self.client.force_login(self.user)
request = HttpRequest()
request.session = self.client.session
request.user = self.user
logout_extra(request, cm.exception)

View File

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://goauthentik.io/blueprints/schema.json",
"type": "object",
"title": "authentik 2025.4.1 Blueprint schema",
"title": "authentik 2025.6.3 Blueprint schema",
"required": [
"version",
"entries"
@ -8147,6 +8147,12 @@
"title": "Group membership field",
"description": "Field which contains members of a group."
},
"user_membership_attribute": {
"type": "string",
"minLength": 1,
"title": "User membership attribute",
"description": "Attribute which matches the value of `group_membership_field`."
},
"object_uniqueness_field": {
"type": "string",
"minLength": 1,
@ -8180,6 +8186,11 @@
"type": "boolean",
"title": "Lookup groups from user",
"description": "Lookup group membership based on a user attribute instead of a group attribute. This allows nested group resolution on systems like FreeIPA and Active Directory"
},
"delete_not_found_objects": {
"type": "boolean",
"title": "Delete not found objects",
"description": "Delete authentik users and groups which were previously supplied by this source, but are now missing from it."
}
},
"required": []

View File

@ -31,7 +31,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.3}
restart: unless-stopped
command: server
environment:
@ -55,7 +55,7 @@ services:
redis:
condition: service_healthy
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.6.3}
restart: unless-stopped
command: worker
environment:

View File

@ -1,10 +0,0 @@
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
// @ts-check
/**
* ESLint configuration for authentik's monorepo.
*/
const ESLintConfig = createESLintPackageConfig();
export default ESLintConfig;

2
go.mod
View File

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

4
go.sum
View File

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

View File

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

View File

@ -28,16 +28,18 @@ func NewSessionBinder(si server.LDAPServerInstance, oldBinder bind.Binder) *Sess
si: si,
log: log.WithField("logger", "authentik.outpost.ldap.binder.session"),
}
if oldSb, ok := oldBinder.(*SessionBinder); ok {
sb.DirectBinder = oldSb.DirectBinder
sb.sessions = oldSb.sessions
sb.log.Debug("re-initialised session binder")
} else {
sb.sessions = ttlcache.New(ttlcache.WithDisableTouchOnHit[Credentials, ldap.LDAPResultCode]())
sb.DirectBinder = *direct.NewDirectBinder(si)
go sb.sessions.Start()
sb.log.Debug("initialised session binder")
if oldBinder != nil {
if oldSb, ok := oldBinder.(*SessionBinder); ok {
sb.DirectBinder = oldSb.DirectBinder
sb.sessions = oldSb.sessions
sb.log.Debug("re-initialised session binder")
return sb
}
}
sb.sessions = ttlcache.New(ttlcache.WithDisableTouchOnHit[Credentials, ldap.LDAPResultCode]())
sb.DirectBinder = *direct.NewDirectBinder(si)
go sb.sessions.Start()
sb.log.Debug("initialised session binder")
return sb
}

View File

@ -16,6 +16,7 @@ import (
memorybind "goauthentik.io/internal/outpost/ldap/bind/memory"
"goauthentik.io/internal/outpost/ldap/constants"
"goauthentik.io/internal/outpost/ldap/flags"
"goauthentik.io/internal/outpost/ldap/search"
directsearch "goauthentik.io/internal/outpost/ldap/search/direct"
memorysearch "goauthentik.io/internal/outpost/ldap/search/memory"
)
@ -85,7 +86,11 @@ func (ls *LDAPServer) Refresh() error {
providers[idx].certUUID = *kp
}
if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_CACHED {
providers[idx].searcher = memorysearch.NewMemorySearcher(providers[idx])
var oldSearcher search.Searcher
if existing != nil {
oldSearcher = existing.searcher
}
providers[idx].searcher = memorysearch.NewMemorySearcher(providers[idx], oldSearcher)
} else if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_DIRECT {
providers[idx].searcher = directsearch.NewDirectSearcher(providers[idx])
}

View File

@ -31,13 +31,26 @@ type MemorySearcher struct {
groups []api.Group
}
func NewMemorySearcher(si server.LDAPServerInstance) *MemorySearcher {
func NewMemorySearcher(si server.LDAPServerInstance, existing search.Searcher) *MemorySearcher {
ms := &MemorySearcher{
si: si,
log: log.WithField("logger", "authentik.outpost.ldap.searcher.memory"),
ds: direct.NewDirectSearcher(si),
}
if existing != nil {
if ems, ok := existing.(*MemorySearcher); ok {
ems.si = si
ems.fetch()
ems.log.Debug("re-initialised memory searcher")
return ems
}
}
ms.fetch()
ms.log.Debug("initialised memory searcher")
return ms
}
func (ms *MemorySearcher) fetch() {
// Error is not handled here, we get an empty/truncated list and the error is logged
users, _ := ak.Paginator(ms.si.GetAPIClient().CoreApi.CoreUsersList(context.TODO()).IncludeGroups(true), ak.PaginatorOptions{
PageSize: 100,
@ -49,7 +62,6 @@ func NewMemorySearcher(si server.LDAPServerInstance) *MemorySearcher {
Logger: ms.log,
})
ms.groups = groups
return ms
}
func (ms *MemorySearcher) SearchBase(req *search.Request) (ldap.ServerSearchResult, error) {

View File

@ -5,6 +5,7 @@ import (
"crypto/sha256"
"crypto/tls"
"encoding/gob"
"encoding/hex"
"fmt"
"html/template"
"net/http"
@ -118,8 +119,8 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server, old
mux := mux.NewRouter()
// Save cookie name, based on hashed client ID
h := sha256.New()
bs := string(h.Sum([]byte(*p.ClientId)))
hs := sha256.Sum256([]byte(*p.ClientId))
bs := hex.EncodeToString(hs[:])
sessionName := fmt.Sprintf("authentik_proxy_%s", bs[:8])
// When HOST_BROWSER is set, use that as Host header for token requests to make the issuer match

View File

@ -3,6 +3,7 @@ package application
type ProxyClaims struct {
UserAttributes map[string]interface{} `json:"user_attributes"`
BackendOverride string `json:"backend_override"`
HostHeader string `json:"host_header"`
IsSuperuser bool `json:"is_superuser"`
}

View File

@ -74,13 +74,18 @@ func (a *Application) proxyModifyRequest(ou *url.URL) func(req *http.Request) {
r.URL.Scheme = ou.Scheme
r.URL.Host = ou.Host
claims := a.getClaimsFromSession(r)
if claims != nil && claims.Proxy != nil && claims.Proxy.BackendOverride != "" {
u, err := url.Parse(claims.Proxy.BackendOverride)
if err != nil {
a.log.WithField("backend_override", claims.Proxy.BackendOverride).WithError(err).Warning("failed parse user backend override")
} else {
r.URL.Scheme = u.Scheme
r.URL.Host = u.Host
if claims != nil && claims.Proxy != nil {
if claims.Proxy.BackendOverride != "" {
u, err := url.Parse(claims.Proxy.BackendOverride)
if err != nil {
a.log.WithField("backend_override", claims.Proxy.BackendOverride).WithError(err).Warning("failed parse user backend override")
} else {
r.URL.Scheme = u.Scheme
r.URL.Host = u.Host
}
}
if claims.Proxy.HostHeader != "" {
r.Host = claims.Proxy.HostHeader
}
}
a.log.WithField("upstream_url", r.URL.String()).Trace("final upstream url")

View File

@ -2,6 +2,7 @@ package radius
import (
"crypto/sha512"
"encoding/hex"
"time"
"github.com/getsentry/sentry-go"
@ -68,7 +69,9 @@ func (rs *RadiusServer) ServeRADIUS(w radius.ResponseWriter, r *radius.Request)
}
}
if pi == nil {
nr.Log().WithField("hashed_secret", string(sha512.New().Sum(r.Secret))).Warning("No provider found")
hs := sha512.Sum512([]byte(r.Secret))
bs := hex.EncodeToString(hs[:])
nr.Log().WithField("hashed_secret", bs).Warning("No provider found")
_ = w.Write(r.Response(radius.CodeAccessReject))
return
}

View File

@ -67,11 +67,15 @@ func (ws *WebServer) configureStatic() {
// Media files, if backend is file
if config.Get().Storage.Media.Backend == "file" {
fsMedia := http.StripPrefix("/media", http.FileServer(http.Dir(config.Get().Storage.Media.File.Path)))
indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/media/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
fsMedia.ServeHTTP(w, r)
})
fsMedia := http.FileServer(http.Dir(config.Get().Storage.Media.File.Path))
indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/media/").Handler(pathStripper(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
fsMedia.ServeHTTP(w, r)
}),
"media/",
config.Get().Web.Path,
))
}
staticRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/if/help/").Handler(pathStripper(

View File

@ -26,7 +26,7 @@ Parameters:
Description: authentik Docker image
AuthentikVersion:
Type: String
Default: 2025.4.1
Default: 2025.6.3
Description: authentik Docker image tag
AuthentikServerCPU:
Type: Number

Binary file not shown.

View File

@ -32,15 +32,17 @@
# datenschmutz, 2025
# 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025
# Dominic Wagner <mail@dominic-wagner.de>, 2025
# Till-Frederik Riechard, 2025
# Alexander Mnich, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Dominic Wagner <mail@dominic-wagner.de>, 2025\n"
"Last-Translator: Alexander Mnich, 2025\n"
"Language-Team: German (https://app.transifex.com/authentik/teams/119923/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -132,6 +134,10 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver."
msgstr "Vom Authentik-Core-Webserver verwendetes Zertifikat."
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
#: authentik/brands/models.py
msgid "Brand"
msgstr "Marke"
@ -405,7 +411,7 @@ msgstr "Eigenschaften"
#: authentik/core/models.py
msgid "session data"
msgstr ""
msgstr "Sitzungsdaten"
#: authentik/core/models.py
msgid "Session"
@ -533,7 +539,7 @@ msgstr ""
#: authentik/enterprise/policies/unique_password/models.py
msgid "Number of passwords to check against."
msgstr ""
msgstr "Anzahl Passwörter, gegen die geprüft wird."
#: authentik/enterprise/policies/unique_password/models.py
#: authentik/policies/password/models.py
@ -543,18 +549,20 @@ msgstr "Passwort nicht im Kontext festgelegt"
#: authentik/enterprise/policies/unique_password/models.py
msgid "This password has been used previously. Please choose a different one."
msgstr ""
"Dieses Passwort wurde in Vergangenheit bereits verwendet. Bitte nutzen Sie "
"ein anderes."
#: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policy"
msgstr ""
msgstr "Passwort-Einzigartigkeits-Richtlinie"
#: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policies"
msgstr ""
msgstr "Passwort-Einzigartigkeits-Richtlinien"
#: authentik/enterprise/policies/unique_password/models.py
msgid "User Password History"
msgstr ""
msgstr "Nutzer-Passwort-Historie"
#: authentik/enterprise/policy.py
msgid "Enterprise required to access this feature."
@ -693,6 +701,33 @@ msgstr "Endgeräte"
msgid "Verifying your browser..."
msgstr "Verifiziere deinen Browser..."
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
#: authentik/enterprise/stages/source/models.py
msgid ""
"Amount of time a user can take to return from the source to continue the "
@ -988,7 +1023,7 @@ msgstr ""
#: authentik/flows/models.py
msgid "Evaluate policies when the Stage is presented to the user."
msgstr ""
msgstr "Richtlinien auswerten, wenn die Phase dem Benutzer angezeigt wird."
#: authentik/flows/models.py
msgid ""
@ -1043,9 +1078,12 @@ msgid "Starting full provider sync"
msgstr "Starte komplette Provider Synchronisation."
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgstr "Synchonisiere Benutzer Seite {page}"
msgid "Syncing users"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
@ -1593,11 +1631,11 @@ msgstr "ES256 (Asymmetrische Verschlüsselung)"
#: authentik/providers/oauth2/models.py
msgid "ES384 (Asymmetric Encryption)"
msgstr ""
msgstr "ES384 (Asymmetrische Verschlüsselung)"
#: authentik/providers/oauth2/models.py
msgid "ES512 (Asymmetric Encryption)"
msgstr ""
msgstr "ES5122 (Asymmetrische Verschlüsselung)"
#: authentik/providers/oauth2/models.py
msgid "Scope used by the client"
@ -2183,11 +2221,11 @@ msgstr "Standard"
#: authentik/providers/scim/models.py
msgid "AWS"
msgstr ""
msgstr "AWS"
#: authentik/providers/scim/models.py
msgid "Slack"
msgstr ""
msgstr "Slack"
#: authentik/providers/scim/models.py
msgid "Base URL to SCIM requests, usually ends in /v2"
@ -2199,7 +2237,7 @@ msgstr "Authentifizierungstoken"
#: authentik/providers/scim/models.py
msgid "SCIM Compatibility Mode"
msgstr ""
msgstr "SCIM Kompatibilitätsmodus"
#: authentik/providers/scim/models.py
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
@ -2231,7 +2269,7 @@ msgstr "Rollen"
#: authentik/rbac/models.py
msgid "Initial Permissions"
msgstr ""
msgstr "Initiale Berechtigungen"
#: authentik/rbac/models.py
msgid "System permission"
@ -2487,6 +2525,12 @@ msgid ""
"Active Directory"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr "LDAP Quelle"
@ -2504,20 +2548,25 @@ msgid "LDAP Source Property Mappings"
msgstr "LDAP Quelle Eigenschafts-Zuordnungen"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr "Benutzer LDAP-Quellverbindung"
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections"
msgstr ""
msgstr "Benutzer LDAP-Quellverbindungen"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection"
msgstr ""
msgstr "LDAP Gruppen Quellverbindung"
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections"
msgstr ""
msgstr "LDAP Gruppen Quellverbindungen"
#: authentik/sources/ldap/signals.py
msgid "Password does not match Active Directory Complexity."
@ -2530,7 +2579,7 @@ msgstr "Kein Token empfangen."
#: authentik/sources/oauth/models.py
msgid "HTTP Basic Authentication"
msgstr ""
msgstr "HTTP Basic Authentifizierung"
#: authentik/sources/oauth/models.py
msgid "Include the client ID and secret as request parameters"
@ -2896,6 +2945,11 @@ msgstr "SAML Gruppen Quellverbindung"
msgid "Group SAML Source Connections"
msgstr "SAML Gruppen Quellverbindungen"
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr "SCIM Quelle"
@ -2930,7 +2984,7 @@ msgstr "Duo Geräte"
#: authentik/stages/authenticator_email/models.py
msgid "Email OTP"
msgstr ""
msgstr "E-Mail Einmalpasswort"
#: authentik/stages/authenticator_email/models.py
#: authentik/stages/email/models.py
@ -2963,11 +3017,11 @@ msgstr "Beim Rendern der E-Mail-Vorlage ist ein Fehler aufgetreten"
#: authentik/stages/authenticator_email/models.py
msgid "Email Device"
msgstr ""
msgstr "E-Mail Gerät"
#: authentik/stages/authenticator_email/models.py
msgid "Email Devices"
msgstr ""
msgstr "E-Mail Geräte"
#: authentik/stages/authenticator_email/stage.py
#: authentik/stages/authenticator_sms/stage.py
@ -2977,7 +3031,7 @@ msgstr "Code stimmt nicht überein"
#: authentik/stages/authenticator_email/stage.py
msgid "Invalid email"
msgstr ""
msgstr "Ungültige E-Mail"
#: authentik/stages/authenticator_email/templates/email/email_otp.html
#: authentik/stages/email/templates/email/password_reset.html
@ -3273,6 +3327,10 @@ msgstr "Zustimmung der Benutzer"
msgid "User Consents"
msgstr "Zustimmungen der Benutzer"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr "Verweigerungsstufe"
@ -3289,6 +3347,14 @@ msgstr "Dummy Stufe"
msgid "Dummy Stages"
msgstr "Dummy Stufen"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr "Passwort zurücksetzen"
@ -3890,10 +3956,11 @@ msgstr ""
#: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr ""
"Reputation kann nicht niedriger als dieser Wert sein. Null oder negativ."
#: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr ""
msgstr "Reputation kann nicht höher als dieser Wert sein. Null oder positiv."
#: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages."

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-20 00:10+0000\n"
"POT-Creation-Date: 2025-06-02 00:12+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -961,8 +961,11 @@ msgid "Starting full provider sync"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgid "Syncing users"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
@ -2223,6 +2226,10 @@ msgstr ""
msgid "Consider Objects matching this filter to be Users."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "Attribute which matches the value of `group_membership_field`."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "Field which contains members of a group."
msgstr ""
@ -2252,6 +2259,12 @@ msgid ""
"Active Directory"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr ""
@ -2268,6 +2281,11 @@ msgstr ""
msgid "LDAP Source Property Mappings"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr ""
@ -2639,6 +2657,11 @@ msgstr ""
msgid "Group SAML Source Connections"
msgstr ""
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr ""
@ -2994,6 +3017,10 @@ msgstr ""
msgid "User Consents"
msgstr ""
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr ""
@ -3010,6 +3037,14 @@ msgstr ""
msgid "Dummy Stages"
msgstr ""
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr ""
@ -3462,10 +3497,6 @@ msgstr ""
msgid "No Pending user to login."
msgstr ""
#: authentik/stages/user_login/stage.py
msgid "Successfully logged in!"
msgstr ""
#: authentik/stages/user_logout/models.py
msgid "User Logout Stage"
msgstr ""

Binary file not shown.

View File

@ -15,7 +15,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
@ -109,6 +109,10 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver."
msgstr "Certificado Web usado por el servidor web Core de authentik"
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
#: authentik/brands/models.py
msgid "Brand"
msgstr "Marca"
@ -671,6 +675,33 @@ msgstr "Dispositivos de Punto de Conexión"
msgid "Verifying your browser..."
msgstr "Verificando tu navegador..."
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
#: authentik/enterprise/stages/source/models.py
msgid ""
"Amount of time a user can take to return from the source to continue the "
@ -1009,9 +1040,12 @@ msgid "Starting full provider sync"
msgstr "Iniciando sincronización completa de proveedor"
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgstr "Sincronizando página {page} de usuarios"
msgid "Syncing users"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
@ -2452,6 +2486,12 @@ msgid ""
"Active Directory"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr "Fuente de LDAP"
@ -2468,6 +2508,11 @@ msgstr "Asignación de Propiedades de Fuente de LDAP"
msgid "LDAP Source Property Mappings"
msgstr "Asignaciones de Propiedades de Fuente de LDAP"
#: authentik/sources/ldap/models.py
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr ""
@ -2859,6 +2904,11 @@ msgstr "Conexión de Fuente de SAML de Grupo"
msgid "Group SAML Source Connections"
msgstr "Conexiones de Fuente de SAML de Grupo"
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr "Fuente de SCIM"
@ -3245,6 +3295,10 @@ msgstr "Consentimiento del usuario"
msgid "User Consents"
msgstr "Consentimientos del usuario"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr "Etapa de denegación"
@ -3261,6 +3315,14 @@ msgstr "Escenario ficticio"
msgid "Dummy Stages"
msgstr "Etapas ficticias"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr "Restablecimiento de contraseña"

Binary file not shown.

View File

@ -15,7 +15,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Ville Ranki, 2025\n"
"Language-Team: Finnish (https://app.transifex.com/authentik/teams/119923/fi/)\n"
@ -106,6 +106,10 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver."
msgstr "Web-sertifikaatti, jota authentik Core -verkkopalvelin käyttää."
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
#: authentik/brands/models.py
msgid "Brand"
msgstr "Brändi"
@ -658,6 +662,33 @@ msgstr "Päätelaitteet"
msgid "Verifying your browser..."
msgstr "Selaintasi varmennetaan..."
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
#: authentik/enterprise/stages/source/models.py
msgid ""
"Amount of time a user can take to return from the source to continue the "
@ -996,9 +1027,12 @@ msgid "Starting full provider sync"
msgstr "Käynnistetään palveluntarjoajan täysi synkronisointi"
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgstr "Synkronoidaan käyttäjien sivua {page}"
msgid "Syncing users"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
@ -2429,6 +2463,12 @@ msgid ""
"Active Directory"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr "LDAP-lähde"
@ -2445,6 +2485,11 @@ msgstr "LDAP-lähteen ominaisuuskytkentä"
msgid "LDAP Source Property Mappings"
msgstr "LDAP-lähteen ominaisuuskytkennät"
#: authentik/sources/ldap/models.py
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr ""
@ -2837,6 +2882,11 @@ msgstr "Ryhmän SAML-lähteen yhteys"
msgid "Group SAML Source Connections"
msgstr "Ryhmän SAML-lähteen yhteydet"
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr "SCIM-lähde"
@ -3216,6 +3266,10 @@ msgstr "Käyttäjän hyväksyntä"
msgid "User Consents"
msgstr "Käyttäjän hyväksynnät"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr "Kieltovaihe"
@ -3232,6 +3286,14 @@ msgstr "Valevaihe"
msgid "Dummy Stages"
msgstr "Valevaiheet"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr "Salasanan nollaus"

View File

@ -19,7 +19,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-20 00:10+0000\n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Marc Schmitt, 2025\n"
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
@ -1056,9 +1056,12 @@ msgid "Starting full provider sync"
msgstr "Démarrage d'une synchronisation complète du fournisseur"
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgstr "Synchronisation de la page {page} d'utilisateurs"
msgid "Syncing users"
msgstr "Synchronisation des utilisateurs"
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr "Synchronisation des groupes"
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
@ -2508,6 +2511,14 @@ msgstr ""
"plutôt que sur un attribut de groupe. Cela permet la résolution des groupes "
"imbriqués sur des systèmes tels que FreeIPA et Active Directory."
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
"Supprimer les utilisateurs et les groupes authentik qui étaient auparavant "
"fournis par cette source, mais qui en sont maintenant absents."
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr "Source LDAP"
@ -2524,6 +2535,13 @@ msgstr "Mappage de propriété source LDAP"
msgid "LDAP Source Property Mappings"
msgstr "Mappages de propriété source LDAP"
#: authentik/sources/ldap/models.py
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
"ID unique utilisé pour vérifier si cet objet existe toujours dans le "
"répertoire."
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr "Connexion de l'utilisateur à la source LDAP"
@ -2918,6 +2936,11 @@ msgstr "Connexion du groupe à la source SAML"
msgid "Group SAML Source Connections"
msgstr "Connexions du groupe à la source SAML"
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr "Continuer vers {source_name}"
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr "Source SCIM"
@ -3308,6 +3331,10 @@ msgstr "Consentement Utilisateur"
msgid "User Consents"
msgstr "Consentements Utilisateur"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr "Jeton de consentement invalide, réaffichage de l'invite"
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr "Étape de Refus"
@ -3324,6 +3351,14 @@ msgstr "Étape factice"
msgid "Dummy Stages"
msgstr "Étapes factices"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr "Continuer pour confirmer cette adresse courriel."
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr "Ce lien a déjà été utilisé, veuillez en demander un nouveau."
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr "Réinitialiser le Mot de Passe"

View File

@ -20,7 +20,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n"
"Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n"
@ -114,6 +114,10 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver."
msgstr "Certificato Web utilizzato dal server Web authentik Core."
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
#: authentik/brands/models.py
msgid "Brand"
msgstr "Brand"
@ -672,6 +676,33 @@ msgstr "Dispositivi di Accesso"
msgid "Verifying your browser..."
msgstr "Verifica del tuo browser..."
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
#: authentik/enterprise/stages/source/models.py
msgid ""
"Amount of time a user can take to return from the source to continue the "
@ -1018,9 +1049,12 @@ msgid "Starting full provider sync"
msgstr "Avvio della sincronizzazione completa del provider"
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgstr "Sincronizzando pagina {page} degli utenti"
msgid "Syncing users"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
@ -2463,6 +2497,12 @@ msgstr ""
"attributo di gruppo. Questo consente la risoluzione di gruppi nidificati su "
"sistemi come FreeIPA e Active Directory."
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr "Sorgente LDAP"
@ -2479,6 +2519,11 @@ msgstr "Mappatura delle proprietà sorgente LDAP"
msgid "LDAP Source Property Mappings"
msgstr "Mappature delle proprietà della sorgente LDAP"
#: authentik/sources/ldap/models.py
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr "Connessione Sorgente LDAP Utente"
@ -2872,6 +2917,11 @@ msgstr "Connessione sorgente SAML di gruppo"
msgid "Group SAML Source Connections"
msgstr "Connessioni sorgente SAML di gruppo"
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr "Sorgente SCIM"
@ -3269,6 +3319,10 @@ msgstr "Consenso utente"
msgid "User Consents"
msgstr "Consensi utente"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr "Fase di negazione"
@ -3285,6 +3339,14 @@ msgstr "Fase fittizia"
msgid "Dummy Stages"
msgstr "Fasi fittizie"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr "Ripristino password"

View File

@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: NavyStack, 2023\n"
"Language-Team: Korean (https://app.transifex.com/authentik/teams/119923/ko/)\n"
@ -99,6 +99,10 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver."
msgstr "Authentik Core 웹서버에서 사용하는 웹 인증서."
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
#: authentik/brands/models.py
msgid "Brand"
msgstr ""
@ -625,6 +629,33 @@ msgstr ""
msgid "Verifying your browser..."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
#: authentik/enterprise/stages/source/models.py
msgid ""
"Amount of time a user can take to return from the source to continue the "
@ -946,8 +977,11 @@ msgid "Starting full provider sync"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgid "Syncing users"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
@ -2263,6 +2297,12 @@ msgid ""
"Active Directory"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr "LDAP 소스"
@ -2279,6 +2319,11 @@ msgstr ""
msgid "LDAP Source Property Mappings"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr ""
@ -2657,6 +2702,11 @@ msgstr ""
msgid "Group SAML Source Connections"
msgstr ""
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr ""
@ -3017,6 +3067,10 @@ msgstr "사용자 동의"
msgid "User Consents"
msgstr "사용자 동의"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr "거부 스테이지"
@ -3033,6 +3087,14 @@ msgstr "더미 스테이지"
msgid "Dummy Stages"
msgstr "더미 스테이지"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr "비밀번호 초기화"

Binary file not shown.

View File

@ -19,7 +19,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Dany Sluijk, 2025\n"
"Language-Team: Dutch (https://app.transifex.com/authentik/teams/119923/nl/)\n"
@ -113,6 +113,10 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver."
msgstr "Webcertificaat gebruikt door de authentik Core-webserver."
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
#: authentik/brands/models.py
msgid "Brand"
msgstr "Merk"
@ -191,6 +195,7 @@ msgid "User's display name."
msgstr "Weergavenaam van de gebruiker."
#: authentik/core/models.py authentik/providers/oauth2/models.py
#: authentik/rbac/models.py
msgid "User"
msgstr "Gebruiker"
@ -379,6 +384,18 @@ msgstr "Eigenschapskoppeling"
msgid "Property Mappings"
msgstr "Eigenschapskoppelingen"
#: authentik/core/models.py
msgid "session data"
msgstr ""
#: authentik/core/models.py
msgid "Session"
msgstr "Sessie"
#: authentik/core/models.py
msgid "Sessions"
msgstr "Sessies"
#: authentik/core/models.py
msgid "Authenticated Session"
msgstr "Geauthenticeerde Sessie"
@ -486,6 +503,38 @@ msgstr "Licentie Gebruik"
msgid "License Usage Records"
msgstr "Licentie Gebruik Records"
#: authentik/enterprise/policies/unique_password/models.py
#: authentik/policies/password/models.py
msgid "Field key to check, field keys defined in Prompt stages are available."
msgstr ""
"Veldsleutel om te controleren, veldsleutels gedefinieerd in Prompt-stadia "
"zijn beschikbaar."
#: authentik/enterprise/policies/unique_password/models.py
msgid "Number of passwords to check against."
msgstr ""
#: authentik/enterprise/policies/unique_password/models.py
#: authentik/policies/password/models.py
msgid "Password not set in context"
msgstr "Wachtwoord niet ingesteld in context"
#: authentik/enterprise/policies/unique_password/models.py
msgid "This password has been used previously. Please choose a different one."
msgstr ""
#: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policy"
msgstr ""
#: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policies"
msgstr ""
#: authentik/enterprise/policies/unique_password/models.py
msgid "User Password History"
msgstr ""
#: authentik/enterprise/policy.py
msgid "Enterprise required to access this feature."
msgstr "Enterprise benodigd voor toegang tot deze functie."
@ -622,6 +671,33 @@ msgstr ""
msgid "Verifying your browser..."
msgstr "Uw browser wordt geverifieerd..."
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
#: authentik/enterprise/stages/source/models.py
msgid ""
"Amount of time a user can take to return from the source to continue the "
@ -963,8 +1039,11 @@ msgid "Starting full provider sync"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
#, python-brace-format
msgid "Syncing page {page} of users"
msgid "Syncing users"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
msgid "Syncing groups"
msgstr ""
#: authentik/lib/sync/outgoing/tasks.py
@ -1265,12 +1344,6 @@ msgstr ""
msgid "Clear Policy's cache metrics"
msgstr ""
#: authentik/policies/password/models.py
msgid "Field key to check, field keys defined in Prompt stages are available."
msgstr ""
"Veldsleutel om te controleren, veldsleutels gedefinieerd in Prompt-stadia "
"zijn beschikbaar."
#: authentik/policies/password/models.py
msgid "How many times the password hash is allowed to be on haveibeenpwned"
msgstr "Hoe vaak het wachtwoordhash op haveibeenpwned mag voorkomen"
@ -1282,10 +1355,6 @@ msgstr ""
"Als de zxcvbn-score gelijk is aan of lager is dan deze waarde, zal het "
"beleid falen."
#: authentik/policies/password/models.py
msgid "Password not set in context"
msgstr "Wachtwoord niet ingesteld in context"
#: authentik/policies/password/models.py
msgid "Invalid password."
msgstr ""
@ -1327,20 +1396,6 @@ msgstr "Reputatie Score"
msgid "Reputation Scores"
msgstr "Reputatie Scores"
#: authentik/policies/templates/policies/buffer.html
msgid "Waiting for authentication..."
msgstr ""
#: authentik/policies/templates/policies/buffer.html
msgid ""
"You're already authenticating in another tab. This page will refresh once "
"authentication is completed."
msgstr ""
#: authentik/policies/templates/policies/buffer.html
msgid "Authenticate in this tab"
msgstr ""
#: authentik/policies/templates/policies/denied.html
msgid "Permission denied"
msgstr "Toestemming geweigerd"
@ -2160,6 +2215,10 @@ msgstr ""
msgid "Roles"
msgstr ""
#: authentik/rbac/models.py
msgid "Initial Permissions"
msgstr ""
#: authentik/rbac/models.py
msgid "System permission"
msgstr ""
@ -2392,6 +2451,12 @@ msgid ""
"Active Directory"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Delete authentik users and groups which were previously supplied by this "
"source, but are now missing from it."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "LDAP Source"
msgstr "LDAP-bron"
@ -2408,6 +2473,27 @@ msgstr ""
msgid "LDAP Source Property Mappings"
msgstr ""
#: authentik/sources/ldap/models.py
msgid ""
"Unique ID used while checking if this object still exists in the directory."
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection"
msgstr ""
#: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections"
msgstr ""
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection"
msgstr ""
#: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections"
msgstr ""
#: authentik/sources/ldap/signals.py
msgid "Password does not match Active Directory Complexity."
msgstr ""
@ -2417,6 +2503,14 @@ msgstr ""
msgid "No token received."
msgstr "Geen token ontvangen."
#: authentik/sources/oauth/models.py
msgid "HTTP Basic Authentication"
msgstr ""
#: authentik/sources/oauth/models.py
msgid "Include the client ID and secret as request parameters"
msgstr ""
#: authentik/sources/oauth/models.py
msgid "Request Token URL"
msgstr "URL voor aanvragen van token"
@ -2458,6 +2552,12 @@ msgstr ""
msgid "Additional Scopes"
msgstr "Aanvullende scopes"
#: authentik/sources/oauth/models.py
msgid ""
"How to perform authentication during an authorization_code token request "
"flow"
msgstr ""
#: authentik/sources/oauth/models.py
msgid "OAuth Source"
msgstr "OAuth-bron"
@ -2769,6 +2869,11 @@ msgstr ""
msgid "Group SAML Source Connections"
msgstr ""
#: authentik/sources/saml/views.py
#, python-brace-format
msgid "Continue to {source_name}"
msgstr ""
#: authentik/sources/scim/models.py
msgid "SCIM Source"
msgstr ""
@ -3142,6 +3247,10 @@ msgstr "Gebruikerstoestemming"
msgid "User Consents"
msgstr "Gebruikersinstemmingen"
#: authentik/stages/consent/stage.py
msgid "Invalid consent token, re-showing prompt"
msgstr ""
#: authentik/stages/deny/models.py
msgid "Deny Stage"
msgstr "Weigerfase"
@ -3158,6 +3267,14 @@ msgstr "Dummystadium"
msgid "Dummy Stages"
msgstr "Dummystadia"
#: authentik/stages/email/flow.py
msgid "Continue to confirm this email address."
msgstr ""
#: authentik/stages/email/flow.py
msgid "Link was already used, please request a new link."
msgstr ""
#: authentik/stages/email/models.py
msgid "Password Reset"
msgstr "Wachtwoordherstel"
@ -3357,6 +3474,12 @@ msgstr ""
"Wanneer ingeschakeld, slaagt de stap en gaat verder wanneer ongeldige "
"gebruikersgegevens zijn ingevoerd."
#: authentik/stages/identification/models.py
msgid ""
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
" to skip straight to entering their password."
msgstr ""
#: authentik/stages/identification/models.py
msgid "Optional enrollment flow, which is linked at the bottom of the page."
msgstr "Optionele inschrijvingsflow, die onderaan de pagina is gekoppeld."
@ -3742,6 +3865,14 @@ msgstr ""
"Gebeurtenissen worden verwijderd na deze duur. (Indeling: "
"weken=3;dagen=2;uren=3;seconden=2)."
#: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr ""
#: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr ""
#: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages."
msgstr "De optie stelt de voettekst links in op de flow uitvoer pagina's."

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