Compare commits

...

364 Commits

Author SHA1 Message Date
b0679bb0fa website/docs: Break line. 2025-04-14 17:16:15 +02:00
153fc7cc3b website/docs: Add whitespace. 2025-04-14 17:07:23 +02:00
5eb848e376 core: Bump django from 5.0.14 to 5.1.8 (#14059)
Bump django from 5.0.14 to 5.1.8
2025-04-14 14:54:58 +00:00
61a293daad core: bump django-rest-framework from 3.14.0 to 3.16.0 (#14057)
upgrade `django-rest-framework` to `3.16.0`

The reverted commit is purely an optimization which unfortunately breaks authentik, specifically Blueprints. It adds `getattr(serializer.instance, field)` to a validator. If `field` is a `RelatedObject`, that invocation queries the database.

When authentik creates objects using Blueprints, it doesn't place related objects into the database before the validator tries to get them from there, so with the reverted commit, it produces `RelatedObjectDoesNotExist`.

Perhaps a long-term solution is to revise how Blueprints work, or perhaps it is to change upstream. But in the meantime, Django 5.0 support ended and upgrading to Django 5.1 requires an upgrade of `django-rest-framework` to `3.16.0`, hence this workaround.

See
- https://github.com/encode/django-rest-framework/pull/9154
- https://github.com/encode/django-rest-framework/issues/9358
- https://github.com/encode/django-rest-framework/pull/9482
- https://github.com/encode/django-rest-framework/pull/9483
2025-04-14 16:24:11 +02:00
edf3300944 policies/reputation: limit reputation score (#14008)
* add limits to reputation score

* limit reputation score limits

Upper to non-negative, Lower to non-positive

* simplify tests

* "fix" bandit false-positives

* move magic numbers to constants

Is it too much to ask for a world in which I can just import these
straight from Python?
2025-04-14 14:18:59 +00:00
5d9c40eac8 ci: fix api-py-publish by disabling poetry cache (#14010) 2025-04-14 16:18:31 +02:00
6ebfbcb66e core: bump goauthentik/fips-python from 3.12.9-slim-bookworm-fips to 3.12.10-slim-bookworm-fips (#14044) 2025-04-14 08:15:20 -06:00
bf0235c113 ci: add NPM packages publish (#13974)
Co-authored-by: Teffen Ellis <teffen@nirri.us>
2025-04-14 08:14:17 -06:00
895cd23b57 root: add packages/ to codeowners (#13975) 2025-04-14 08:05:09 -06:00
c908d9e95e providers/oauth2, rac: make sure tokens are revoked after session deletion (#14011) 2025-04-14 15:48:39 +02:00
a07fd8d54b core: bump multidict from 6.4.2 to v6.4.3 (#14051) 2025-04-14 13:26:50 +00:00
39a46a6dc4 core: bump uvicorn from 0.34.0 to v0.34.1 (#14056) 2025-04-14 13:26:10 +00:00
ad71960d77 core: bump typing-extensions from 4.13.1 to v4.13.2 (#14055) 2025-04-14 13:04:16 +00:00
2a384511f5 core: bump ruff from 0.11.4 to v0.11.5 (#14053) 2025-04-14 13:03:52 +00:00
4dcc104947 core: bump boto3 from 1.37.31 to v1.37.33 (#14045) 2025-04-14 09:02:05 -04:00
71fe526e47 core: bump opentelemetry-api from 1.31.1 to v1.32.0 (#14052) 2025-04-14 09:01:39 -04:00
03e3f516ac core: bump httpcore from 1.0.7 to v1.0.8 (#14050) 2025-04-14 13:00:58 +00:00
3b59333246 core: bump google-api-python-client from 2.166.0 to v2.167.0 (#14048) 2025-04-14 13:00:20 +00:00
4e800c14cb core: bump googleapis-common-protos from 1.69.2 to v1.70.0 (#14049) 2025-04-14 12:59:54 +00:00
789b29a3e7 core: bump debugpy from 1.8.13 to v1.8.14 (#14047) 2025-04-14 12:59:21 +00:00
857b6e63a0 root: prevent docker-compose up when secret key is missing (#14043) 2025-04-14 12:56:41 +00:00
edc937dd78 core: bump goauthentik.io/api/v3 from 3.2025024.2 to 3.2025024.4 (#14042)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 14:49:32 +02:00
d98b6f29d4 core: bump github.com/sethvargo/go-envconfig from 1.1.1 to 1.2.0 (#14041)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-14 14:49:17 +02:00
53ba2a0ca8 core, web: update translations (#14037)
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-04-14 14:40:38 +02:00
ae364292e6 website: Port WWW theme to docs site. Prep for package. (#13962)
Update sidebar.css

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

website/docs: Update paths.

website/docs: Use package theme.
2025-04-12 01:31:57 +02:00
f15bc2df97 translate: Updates for file locale/en/LC_MESSAGES/django.po in nl [Manual Sync] (#14026)
Translate django.po in nl [Manual Sync]

80% of minimum 75% 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-04-11 15:55:33 +00:00
b27d49e55f translate: Updates for file web/xliff/en.xlf in fi [Manual Sync] (#14012)
Translate web/xliff/en.xlf in fi [Manual Sync]

95% of minimum 75% 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-04-11 17:38:37 +02:00
e0d2beb225 translate: Updates for file locale/en/LC_MESSAGES/django.po in de [Manual Sync] (#14020)
Translate django.po in de [Manual Sync]

96% of minimum 75% 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-04-11 17:38:11 +02:00
2313b4755b translate: Updates for file locale/en/LC_MESSAGES/django.po in pt_BR [Manual Sync] (#14027)
Translate django.po in pt_BR [Manual Sync]

75% of minimum 75% 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-04-11 17:37:55 +02:00
1cffadecb0 translate: Updates for file locale/en/LC_MESSAGES/django.po in it [Manual Sync] (#14024)
Translate django.po in it [Manual Sync]

99% of minimum 75% 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-04-11 17:37:40 +02:00
5e163d6da1 translate: Updates for file locale/en/LC_MESSAGES/django.po in pl [Manual Sync] (#14025)
Translate django.po in pl [Manual Sync]

82% of minimum 75% translated source file: 'django.po'
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-04-11 17:37:23 +02:00
0626e18674 translate: Updates for file locale/en/LC_MESSAGES/django.po in fi [Manual Sync] (#14023)
Translate django.po in fi [Manual Sync]

94% of minimum 75% 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-04-11 17:37:04 +02:00
e986a62a12 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_TW [Manual Sync] (#14031)
Translate django.po in zh_TW [Manual Sync]

79% of minimum 75% 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-04-11 17:36:48 +02:00
e25afcb84a translate: Updates for file web/xliff/en.xlf in pl [Manual Sync] (#14015)
Translate web/xliff/en.xlf in pl [Manual Sync]

85% of minimum 75% 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-04-11 17:36:33 +02:00
bb95613104 translate: Updates for file web/xliff/en.xlf in zh_CN [Manual Sync] (#14017)
Translate web/xliff/en.xlf in zh_CN [Manual Sync]

99% of minimum 75% 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-04-11 17:36:17 +02:00
89dfac2f57 translate: Updates for file web/xliff/en.xlf in it [Manual Sync] (#14016)
Translate web/xliff/en.xlf in it [Manual Sync]

99% of minimum 75% 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-04-11 17:36:14 +02:00
31462b55e6 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN [Manual Sync] (#14028)
Translate django.po in zh_CN [Manual Sync]

99% of minimum 75% 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-04-11 17:36:08 +02:00
60337c1cf0 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans [Manual Sync] (#14029)
Translate django.po in zh-Hans [Manual Sync]

99% of minimum 75% 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-04-11 17:36:03 +02:00
343d3bb1fb translate: Updates for file locale/en/LC_MESSAGES/django.po in ru [Manual Sync] (#14032)
Translate django.po in ru [Manual Sync]

91% of minimum 75% 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-04-11 15:09:01 +00:00
11fe86c4f6 translate: Updates for file locale/en/LC_MESSAGES/django.po in fr [Manual Sync] (#14022)
Translate django.po in fr [Manual Sync]

99% of minimum 75% translated source file: 'django.po'
on 'fr'.

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-04-11 15:07:16 +00:00
963ce085e4 translate: Updates for file locale/en/LC_MESSAGES/django.po in es [Manual Sync] (#14019)
Translate django.po in es [Manual Sync]

95% of minimum 75% 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-04-11 15:06:47 +00:00
3642b89ab0 translate: Updates for file web/xliff/en.xlf in zh-Hans [Manual Sync] (#14021)
Translate en.xlf in zh-Hans [Manual Sync]

99% of minimum 75% 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-04-11 15:06:07 +00:00
8cfb371ed3 translate: Updates for file web/xliff/en.xlf in ru [Manual Sync] (#14013)
Translate web/xliff/en.xlf in ru [Manual Sync]

90% of minimum 75% 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-04-11 15:05:28 +00:00
6e74edb9f2 web: bump API Client version (#13972)
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-04-11 14:32:58 +02:00
397905f8f0 translate: Updates for file web/xliff/en.xlf in fr [Manual Sync] (#13979)
* Translate web/xliff/en.xlf in fr [Manual Sync]

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

* Removing web/xliff/en.xlf in fr

99% of minimum 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-04-11 14:22:54 +02:00
7fd35b1dfc sources/ldap: add source connections (#13796) 2025-04-11 12:07:18 +00:00
9ba03f5439 core: bump urllib3 from 2.3.0 to 2.4.0 (#14006)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-11 12:00:56 +00:00
1139d6d27c translate: Updates for file web/xliff/en.xlf in zh-Hans [Manual Sync] (#13985)
* Translate en.xlf in zh-Hans [Manual Sync]

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

* Removing web/xliff/en.xlf in zh-Hans

99% of minimum 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-04-11 11:58:56 +00:00
077fd966c2 translate: Updates for file locale/en/LC_MESSAGES/django.po in ru [Manual Sync] (#13992)
Translate django.po in ru [Manual Sync]

91% 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-04-11 13:46:11 +02:00
bd41822a57 translate: Updates for file locale/en/LC_MESSAGES/django.po in de [Manual Sync] (#13986)
Translate django.po in de [Manual Sync]

96% 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-04-11 13:45:49 +02:00
dfd3d76434 translate: Updates for file locale/en/LC_MESSAGES/django.po in nl [Manual Sync] (#13991)
Translate django.po in nl [Manual Sync]

81% 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-04-11 13:45:24 +02:00
397e98906d translate: Updates for file locale/en/LC_MESSAGES/django.po in es [Manual Sync] (#13987)
Translate django.po in es [Manual Sync]

95% 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-04-11 13:45:12 +02:00
65d8da8c64 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_TW [Manual Sync] (#13994)
Translate django.po in zh_TW [Manual Sync]

79% 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-04-11 13:44:55 +02:00
5b435297c5 translate: Updates for file locale/en/LC_MESSAGES/django.po in fi [Manual Sync] (#13988)
Translate django.po in fi [Manual Sync]

94% 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-04-11 13:44:39 +02:00
f792fd42f6 translate: Updates for file web/xliff/en.xlf in fi [Manual Sync] (#13978)
Translate web/xliff/en.xlf in fi [Manual Sync]

95% 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-04-11 13:44:32 +02:00
70c0fdd5fa translate: Updates for file locale/en/LC_MESSAGES/django.po in pl [Manual Sync] (#13989)
Translate django.po in pl [Manual Sync]

82% of minimum 60% translated source file: 'django.po'
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-04-11 13:44:24 +02:00
9b636eba01 translate: Updates for file locale/en/LC_MESSAGES/django.po in pt_BR [Manual Sync] (#13990)
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-04-11 13:44:19 +02:00
a982224502 translate: Updates for file locale/en/LC_MESSAGES/django.po in tr [Manual Sync] (#13995)
Translate django.po in tr [Manual Sync]

91% 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-04-11 13:44:13 +02:00
6a16cccb40 translate: Updates for file locale/en/LC_MESSAGES/django.po in ko [Manual Sync] (#13993)
Translate django.po in ko [Manual Sync]

68% 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-04-11 13:43:49 +02:00
6dac91e2b4 core: bump github.com/getsentry/sentry-go from 0.31.1 to 0.32.0 (#14004)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 13:43:29 +02:00
3e2d0532d1 core: bump goauthentik.io/api/v3 from 3.2025024.1 to 3.2025024.2 (#14005)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 13:42:03 +02:00
4e1300650b core, web: update translations (#13999)
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-04-11 13:40:50 +02:00
06b3ed0c9c core: fix migrations (#14009) 2025-04-11 13:36:53 +02:00
395ad722b7 core: migrate all sessions to the database (#9736)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-11 09:10:55 +02:00
9917d81246 website/integrations: add openproject (#13838)
* Added scope mapping section

* Updated formatting

* Bolded UI elements

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

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

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

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

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

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

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

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

* Indented code block

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-10 15:52:00 -05:00
2a87687d34 website/integrations: add wazuh (#13776)
* Document explaining integration between authentik and knocknoc

* Clarified Knocknoc config

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Fixed typos

* Document mostly complete. Work to be done on Wazuh config section

* Completed the Wazuh config section

* Changed URL in Wazuh config

* typo

* Removed knocknoc doc

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

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

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

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

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

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

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

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

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

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

* Multiline codeblocks and moved SAML metadata note to beginning of section.

* Update sidebarsIntegrations.js to remove knoknok

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

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

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

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

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

* Changed group creation section to cut down on repetition of the word "click"

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

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

* Fixed mistake in the config.yml section and applied various suggestions from Dominic

* Fixed multilinecodeblocks and commands formatting

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Changed multiline codeblocks due to formatting issues.

* Clarified what run_as parameter does

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

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

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

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

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

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

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

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

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

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

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

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

* Fixed codeblock indenting and prettier issue

---------

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-04-10 15:43:02 -05:00
a726c2260a translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans [Manual Sync] (#13996)
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-04-10 15:38:46 +00:00
44e0bfd4ef website: dev docs: fix upper-case authentik (#13961)
Signed-off-by: Dominic R <dominic@sdko.org>
2025-04-10 16:06:17 +01:00
8d0b362c9c web: elements: Table: Fix table selection clearing behavior (#13959)
web: elements: Table: Fix table selection clearing and modal closing behavior

Closes https://github.com/goauthentik/authentik/issues/13831
2025-04-10 17:03:02 +02:00
e5e53f034e core: bump multidict from 6.2.0 to v6.4.2 (#13971) 2025-04-10 10:24:19 -04:00
71b87127d1 core: bump msgraph-sdk from 1.26.0 to v1.27.0 (#13970) 2025-04-10 10:23:42 -04:00
d5d67fe22d core: bump boto3 from 1.37.30 to v1.37.31 (#13968) 2025-04-10 10:23:18 -04:00
5d2685341d sources/ldap: lookup group memberships from user attribute (#12661)
* sources/ldap: add support for group lookups from user

* sources/ldap: implement working membership lookups

* sources/ldap: add schema changes

* sources/ldap: add group membership toggle ui element

* sources/ldap: lint changed files

* website/docs: add note about lookups to AD docs

* Update website/docs/users-sources/sources/directory-sync/active-directory/index.md

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Amélie Krejčí <amelie@krejci.vip>

* website/docs: simplify wording of attribute documentation

Follows suggestions from @jorhett

* sources/ldap: add missing spaces in docstrings

Follows suggestions from @jorhett

* Add a test for memberof attribute

* sources/ldap: implement test

* format

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

* re-migrate

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

* revert website changes in favor of #13966

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

* update frontend help text

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

---------

Signed-off-by: Amélie Krejčí <amelie@krejci.vip>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Shawn Weeks <sweeks@weeksconsulting.us>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Jo Rhett <geek@jorhett.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-10 14:37:38 +02:00
f1ac4ff9c9 translate: Updates for file web/xliff/en.xlf in it (#13956)
Translate web/xliff/en.xlf in it

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-04-10 13:40:33 +02:00
79f4c66286 translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#13957)
Translate locale/en/LC_MESSAGES/django.po in it

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-04-10 13:40:12 +02:00
1f82094c0b core: bump astral-sh/uv from 0.6.13 to 0.6.14 (#13964)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 13:36:27 +02:00
35440acba3 core: bump django from 5.0.13 to 5.0.14 (#13954)
bump django to 5.0.14
2025-04-10 12:55:27 +02:00
eca9901704 website/docs: Remove enterprise badge from Fleet integration (#13963)
website/docs: Remove enterprise badge.
2025-04-10 08:29:39 +01:00
6ddd5a3d5f website/integrations: add Homarr (#13818)
* Adding Homarr integration details

* Fixing typo in homarr doc

* Lint fix

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

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Nate Fonseka <882236+nfons@users.noreply.github.com>

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

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Nate Fonseka <882236+nfons@users.noreply.github.com>

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

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

---------

Signed-off-by: Nate Fonseka <882236+nfons@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: nfonseka <nfonseka@rxsense.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-10 08:15:15 +01:00
5664e62eca website/integration: update harbor integration document (#13816)
* Updates harbor integration doc to new template and fixes reported issue

* typo

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
2025-04-09 18:23:52 -05:00
1403f17d62 Fix redirect URL in wordpress integration guide (#13955)
Update wordpress integration guide to fix redirect URL

Signed-off-by: virtualboys <emanmomot@gmail.com>
2025-04-09 17:10:33 -05:00
1ac8989e81 lifecycle/aws: bump aws-cdk-lib (#13953) 2025-04-09 18:24:45 +00:00
b0a1db77e3 core: bump protobuf from 5.29.4 to v6.30.2 (#13950) 2025-04-09 18:01:53 +00:00
46da4cb59e core: bump pyasn1-modules from 0.4.1 to v0.4.2 (#13951) 2025-04-09 18:01:16 +00:00
154df5cdf7 core: bump microsoft-kiota-authentication-azure from 1.9.2 to v1.9.3 (#13948) 2025-04-09 18:00:55 +00:00
5b889456f6 core: bump microsoft-kiota-http from 1.9.2 to v1.9.3 (#13949) 2025-04-09 18:00:20 +00:00
3eaed82c48 core: bump trio-websocket from 0.11.1 to v0.12.2 (#13934) 2025-04-09 17:49:55 +00:00
feaf9d8bc9 core: bump msgraph-core from 1.3.1 to v1.3.3 (#13900) 2025-04-09 17:48:08 +00:00
2899668ae2 core: bump jsii from 1.109.0 to v1.111.0 (#13886) 2025-04-09 17:46:29 +00:00
4c25e1bb24 core: bump setuptools from 72.1.0 to v78.1.0 (#13928) 2025-04-09 19:29:15 +02:00
464ff3f5b1 core: bump kombu from 5.3.7 to v5.5.2 (#13888) 2025-04-09 19:27:57 +02:00
22eb5f56f1 core: bump msgpack from 1.0.8 to v1.1.0 (#13899) 2025-04-09 19:27:27 +02:00
7e48e87f49 core: bump msgraph-sdk from 1.24.0 to v1.26.0 (#13901) 2025-04-09 19:26:52 +02:00
8ce12f7850 core: bump proto-plus from 1.24.0 to v1.26.1 (#13910) 2025-04-09 19:26:37 +02:00
2514baabeb core: bump protobuf from 5.27.2 to v5.29.4 (#13911) 2025-04-09 19:26:16 +02:00
945930a507 core: bump pydantic from 2.10.6 to v2.11.3 (#13914) 2025-04-09 19:25:51 +02:00
537a80ad97 core: bump rich from 13.7.1 to v14.0.0 (#13922) 2025-04-09 19:25:26 +02:00
5c993e23fe core: bump twisted from 24.7.0 to v24.11.0 (#13936) 2025-04-09 19:25:02 +02:00
eb2db18494 core: bump watchfiles from 0.22.0 to v1.0.5 (#13941) 2025-04-09 19:24:40 +02:00
12a46a8426 core: bump typing-extensions from 4.12.2 to v4.13.1 (#13937) 2025-04-09 19:24:25 +02:00
4a1213310a core: bump multidict from 6.0.5 to v6.2.0 (#13902) 2025-04-09 19:24:11 +02:00
84c2097148 core: bump sentry-sdk from 2.22.0 to v2.25.1 (#13927) 2025-04-09 19:23:56 +02:00
c05dedc573 core: bump rpds-py from 0.19.1 to v0.24.0 (#13923) 2025-04-09 19:23:38 +02:00
18c197e75b core: bump propcache from 0.2.0 to v0.3.1 (#13909) 2025-04-09 19:23:29 +02:00
0c26a0bce2 core: bump pbr from 6.0.0 to v6.1.1 (#13905) 2025-04-09 19:23:17 +02:00
5fd6a4cead core: bump golang.org/x/sync from 0.12.0 to 0.13.0 (#13787)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 17:22:55 +00:00
51fb1bd8e7 core: bump ua-parser-builtins from 0.18.0 to v0.18.0.post1 (#13939) 2025-04-09 19:21:54 +02:00
4a30f87a42 core: bump msal from 1.30.0 to v1.32.0 (#13897) 2025-04-09 19:21:42 +02:00
8e6b6ede30 core: bump msal-extensions from 1.2.0 to v1.3.1 (#13898) 2025-04-09 19:21:33 +02:00
af30c2a68e core: bump prometheus-client from 0.20.0 to v0.21.1 (#13907) 2025-04-09 19:21:23 +02:00
9b65627a3e core: bump jsonschema-specifications from 2023.12.1 to v2024.10.1 (#13887) 2025-04-09 19:21:13 +02:00
4bad91c901 core: bump markupsafe from 2.1.5 to v3.0.2 (#13890) 2025-04-09 19:21:01 +02:00
f3c479d077 core: bump stevedore from 5.2.0 to v5.4.1 (#13932) 2025-04-09 19:20:47 +02:00
b024df9903 core: bump zope-interface from 6.4.post2 to v7.2 (#13946) 2025-04-09 19:20:30 +02:00
f6a6458088 core: bump websockets from 12.0 to v15.0.1 (#13942) 2025-04-09 19:18:14 +02:00
f0dc0e8900 core: bump platformdirs from 4.2.2 to v4.3.7 (#13906) 2025-04-09 19:17:21 +02:00
79e89b0376 core: bump selenium from 4.29.0 to v4.31.0 (#13926) 2025-04-09 19:17:11 +02:00
4cc7d91379 core: bump six from 1.16.0 to v1.17.0 (#13929) 2025-04-09 19:17:00 +02:00
245909e31a core: bump hpack from 4.0.0 to v4.1.0 (#13878) 2025-04-09 19:16:51 +02:00
997a1ddb3d core: bump iniconfig from 2.0.0 to v2.1.0 (#13885) 2025-04-09 19:16:34 +02:00
42335a60bf core: bump hyperframe from 6.0.1 to v6.1.0 (#13882) 2025-04-09 19:16:20 +02:00
fc539332e1 core: bump uvloop from 0.19.0 to v0.21.0 (#13940) 2025-04-09 19:16:05 +02:00
d9efb02078 core: bump httpx from 0.27.0 to v0.28.1 (#13880) 2025-04-09 19:15:53 +02:00
6212250e19 core: bump importlib-resources from 6.4.0 to v6.5.2 (#13884) 2025-04-09 19:15:40 +02:00
c18beefc8f core: bump zipp from 3.20.2 to v3.21.0 (#13945) 2025-04-09 19:15:30 +02:00
f23da6e402 core: bump trio from 0.26.0 to v0.29.0 (#13933) 2025-04-09 19:14:56 +02:00
e934b246c8 core: bump deprecated from 1.2.14 to v1.2.18 (#13866) 2025-04-09 19:14:29 +02:00
ead684a410 core: bump wrapt from 1.16.0 to v1.17.2 (#13943) 2025-04-09 19:14:04 +02:00
d782aadab7 core: bump h2 from 4.1.0 to v4.2.0 (#13877) 2025-04-09 19:13:50 +02:00
4ac6f83aea core: bump yarl from 1.17.2 to v1.19.0 (#13944) 2025-04-09 19:13:38 +02:00
6281d36a69 core: bump django-storages from 1.14.5 to v1.14.6 (#13869) 2025-04-09 17:10:57 +00:00
8129ad4ec0 core: bump github.com/coreos/go-oidc/v3 from 3.13.0 to 3.14.1 (#13772)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 19:01:47 +02:00
24eea415b2 core: bump golang.org/x/oauth2 from 0.28.0 to 0.29.0 (#13788)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 19:00:38 +02:00
a615ce8e95 web: bump API Client version (#13798)
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-04-09 18:59:59 +02:00
5b275cf7fb core: bump goauthentik.io/api/v3 from 3.2025023.4 to 3.2025024.1 (#13833)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 18:59:39 +02:00
d6e91c119f core, web: update translations (#13832)
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-04-09 18:59:17 +02:00
7841e47e74 core: bump celery from 5.4.0 to v5.5.1 (#13858) 2025-04-09 18:58:06 +02:00
ad2a4bea3e core: bump ruff from 0.9.10 to v0.11.4 (#13924) 2025-04-09 16:53:44 +00:00
a554c085c1 core: bump tzdata from 2024.1 to v2025.2 (#13938) 2025-04-09 16:20:39 +00:00
ff0d978754 core: bump std-uritemplate from 2.0.2 to v2.0.3 (#13931) 2025-04-09 16:19:54 +00:00
de48e62819 core: bump twilio from 9.5.0 to v9.5.2 (#13935) 2025-04-09 16:19:18 +00:00
e50e995d2f core: bump sqlparse from 0.5.1 to v0.5.3 (#13930) 2025-04-09 16:18:57 +00:00
3bf4156cb3 core: bump referencing from 0.35.1 to v0.36.2 (#13921) 2025-04-09 16:17:31 +00:00
89990facf5 core: bump pytest-django from 4.10.0 to v4.11.1 (#13917) 2025-04-09 16:17:26 +00:00
48545950ed core: bump redis from 5.0.7 to v5.2.1 (#13920) 2025-04-09 16:17:12 +00:00
0544aa5fae core: bump pyparsing from 3.1.2 to v3.2.3 (#13916) 2025-04-09 16:16:48 +00:00
5d69455b87 core: bump pytz from 2024.1 to v2025.2 (#13919) 2025-04-09 16:16:24 +00:00
3d291cf4da core: bump python-dotenv from 1.0.1 to v1.1.0 (#13918) 2025-04-09 16:15:36 +00:00
44d7c42dc7 core: bump pyasn1 from 0.6.0 to v0.6.1 (#13912) 2025-04-09 16:15:22 +00:00
4ea4e925e3 core: bump pygments from 2.18.0 to v2.19.1 (#13915) 2025-04-09 16:14:57 +00:00
169172c85f core: bump prompt-toolkit from 3.0.47 to v3.0.50 (#13908) 2025-04-09 16:14:52 +00:00
adea637fa4 core: bump pyasn1-modules from 0.4.0 to v0.4.1 (#13913) 2025-04-09 16:14:38 +00:00
0231277d9c core: bump opentelemetry-api from 1.31.0 to v1.31.1 (#13903) 2025-04-09 16:13:12 +00:00
45643ed1f6 core: bump microsoft-kiota-serialization-form from 1.9.2 to v1.9.3 (#13893) 2025-04-09 16:12:37 +00:00
3823d56dbd core: bump orjson from 3.10.6 to v3.10.16 (#13904) 2025-04-09 16:12:22 +00:00
43cfd59ac0 core: bump microsoft-kiota-serialization-text from 1.9.2 to v1.9.3 (#13896) 2025-04-09 16:11:24 +00:00
c8555bbf59 core: bump microsoft-kiota-serialization-json from 1.9.2 to v1.9.3 (#13894) 2025-04-09 16:11:07 +00:00
a4251a3410 core: bump microsoft-kiota-serialization-multipart from 1.9.2 to v1.9.3 (#13895) 2025-04-09 16:10:33 +00:00
50985f9b0b core: bump lxml from 5.3.1 to v5.3.2 (#13889) 2025-04-09 16:08:51 +00:00
9ec24528d4 core: bump maxminddb from 2.6.2 to v2.6.3 (#13891) 2025-04-09 16:08:41 +00:00
5eac38c0cc core: bump humanize from 4.10.0 to v4.12.2 (#13881) 2025-04-09 16:08:36 +00:00
010df0c31c core: bump httpcore from 1.0.5 to v1.0.7 (#13879) 2025-04-09 16:08:18 +00:00
7ba858eff3 core: bump django-pgactivity from 1.4.1 to v1.7.1 (#13868) 2025-04-09 16:08:00 +00:00
817d2d5ff8 core: bump googleapis-common-protos from 1.63.2 to v1.69.2 (#13876) 2025-04-09 16:07:37 +00:00
70e34e03b4 core: bump dnspython from 2.6.1 to v2.7.0 (#13870) 2025-04-09 16:07:18 +00:00
d61f9f6d57 core: bump google-api-core from 2.19.1 to v2.24.2 (#13873) 2025-04-09 16:07:03 +00:00
bdf81706b8 core: bump duo-client from 5.4.0 to v5.5.0 (#13871) 2025-04-09 16:06:47 +00:00
7b56602fc9 core: bump idna from 3.7 to v3.10 (#13883) 2025-04-09 16:06:32 +00:00
7c6e25a996 core: bump google-api-python-client from 2.164.0 to v2.166.0 (#13874) 2025-04-09 16:06:15 +00:00
0eeaeaf1ff core: bump google-auth from 2.32.0 to v2.38.0 (#13875) 2025-04-09 16:06:03 +00:00
9ce4337b11 core: bump coverage from 7.6.12 to v7.8.0 (#13864) 2025-04-09 16:05:37 +00:00
c6a3c7371c core: bump frozenlist from 1.4.1 to v1.5.0 (#13872) 2025-04-09 16:05:21 +00:00
42a7cf10f2 core: bump decorator from 5.1.1 to v5.2.1 (#13865) 2025-04-09 16:04:55 +00:00
bb4f7b1193 core: bump click from 8.1.7 to v8.1.8 (#13863) 2025-04-09 16:04:14 +00:00
3eecfb835b core: bump charset-normalizer from 3.3.2 to v3.4.1 (#13862) 2025-04-09 16:02:41 +00:00
92ab856bd3 core: bump channels from 4.2.0 to v4.2.2 (#13861) 2025-04-09 16:01:28 +00:00
178549a756 core: bump cffi from 1.16.0 to v1.17.1 (#13860) 2025-04-09 15:59:19 +00:00
67d178aa11 core: bump certifi from 2024.7.4 to v2025.1.31 (#13859) 2025-04-09 15:56:20 +00:00
ef53abace9 core: bump cattrs from 24.1.2 to v24.1.3 (#13857) 2025-04-09 15:46:55 +00:00
5effb3a0f6 core: bump cachetools from 5.4.0 to v5.5.2 (#13856) 2025-04-09 15:43:53 +00:00
3a37916a8f core: bump boto3 from 1.34.150 to v1.37.30 (#13854) 2025-04-09 15:36:10 +00:00
428d5ac9cf core: bump attrs from 23.2.0 to 25.3.0 (#13846) 2025-04-09 17:33:00 +02:00
7b4037fdda core: bump anyio from 4.4.0 to 4.9.0 (#13845) 2025-04-09 17:32:28 +02:00
2c7bbcc27b core: bump billiard from 4.2.0 to v4.2.1 (#13853) 2025-04-09 15:19:45 +00:00
19fb24de99 core: bump azure-core from 1.30.2 to 1.33.0 (#13850) 2025-04-09 15:18:54 +00:00
2709702896 core: bump bcrypt from 4.2.0 to v4.3.0 (#13852) 2025-04-09 15:18:39 +00:00
7d0d5a7dc2 core: bump azure-identity from 1.17.1 to 1.21.0 (#13851) 2025-04-09 15:17:46 +00:00
6a04a2ca69 core: bump automat from 22.10.0 to 24.8.1 (#13848) 2025-04-09 15:15:01 +00:00
ea561c9da6 core: bump amqp from 5.2.0 to 5.3.1 (#13844) 2025-04-09 15:08:00 +00:00
9b9c55f17c core: bump aiosignal from 1.3.1 to 1.3.2 (#13843) 2025-04-09 15:07:22 +00:00
bd5e78bd44 core: bump aiohttp-retry from 2.8.3 to 2.9.1 (#13842) 2025-04-09 15:07:10 +00:00
ab98028022 core: bump aiohttp from 3.10.11 to 3.11.16 (#13841) 2025-04-09 15:03:36 +00:00
813ff64ba1 core: bump autobahn from 23.6.2 to 24.4.2 (#13847) 2025-04-09 15:02:57 +00:00
c99e742214 core: bump aiohappyeyeballs from 2.3.5 to 2.6.1 (#13840) 2025-04-09 17:00:49 +02:00
dac6ad3cd6 core: bump github.com/prometheus/client_golang from 1.21.1 to 1.22.0 (#13834)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-09 15:48:58 +02:00
e4d2a53ccc release: 2025.2.4 (#13830)
* release: 2025.2.4

* bump version in uv.lock
2025-04-08 19:16:00 +00:00
3b6775fd9c website/integrations: rename Hoarder to Karakeep (#13789)
* Hoarder renamed to karakeep

The Hoarder app has been renamed to Karakeep recently. https://www.reddit.com/r/selfhosted/comments/1js667o/hoarder_is_rebranding_to_karakeep/

Signed-off-by: petrsimunek <49954958+petrsimunek@users.noreply.github.com>

* folder hoarder renamed to karakeep

* sidebar changed from hoarder to karakeep

---------

Signed-off-by: petrsimunek <49954958+petrsimunek@users.noreply.github.com>
2025-04-08 13:09:11 -05:00
5882e0b2cb website/docs: Add release notes for 2025.2.4 (#13829) 2025-04-08 18:08:03 +00:00
65f0b471d8 website/docs: Add release notes for 2024.12.5 (#13828)
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-08 17:56:15 +00:00
7d054db1a5 Revert "core: fix non-exploitable open redirect (#13696)" (#13824) 2025-04-08 17:10:12 +00:00
cb75ba2e5e translate: Updates for file web/xliff/en.xlf in fr (#13822)
Translate web/xliff/en.xlf in fr

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-04-08 16:56:13 +00:00
36cecc1391 translate: Updates for file web/xliff/en.xlf in zh_CN (#13820)
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-04-08 18:42:16 +02:00
81b91d8777 translate: Updates for file web/xliff/en.xlf in zh-Hans (#13821)
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-04-08 18:41:58 +02:00
41dc23b3c2 core: users API: add date_joined (#13817) 2025-04-08 13:26:11 +00:00
370eff1494 website/integrations: fix ArgoCD redirect paths (#13804) 2025-04-08 15:24:46 +02:00
0ff8def03b core, web: update translations (#13806)
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-04-08 15:23:29 +02:00
b01cafd9fe core: bump goauthentik.io/api/v3 from 3.2025023.2 to 3.2025023.4 (#13811)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 15:19:30 +02:00
90aa8abb80 core: bump astral-sh/uv from 0.6.12 to 0.6.13 (#13812)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 15:19:04 +02:00
fd21aae4f9 website/docs: Correcting IDP URLs on Mailcow integration page (#13803)
Updating URLs to correct IDP URLs

Signed-off-by: Adam Berry <adam.berry@racklab.io>
2025-04-08 08:35:55 +01:00
360223a2ff web: Flesh out configs. (#13801) 2025-04-08 01:21:05 +02:00
0e83de2697 web: Tidy temporal utilities. (#13755) 2025-04-07 18:37:03 +00:00
a23bac9d9b website/integrations: nextcloud: add warning about admin lockout (#13782)
* docs: add a danger warning in nextcloud integration

If a user follwoing the guide for OpenID integration. They can lock out their Admin users, if used the customer profile scope and select the **use unique user ID** option. 
So a danger box was added to let people know that can happen and why

Signed-off-by: Unfaehig <38919962+Unfaehig@users.noreply.github.com>

* docs: website/integrations/services/nextcloud/index.mdx

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Unfaehig <38919962+Unfaehig@users.noreply.github.com>

* chore: nextcloud integration fix formating

---------

Signed-off-by: Unfaehig <38919962+Unfaehig@users.noreply.github.com>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-04-07 13:13:41 -05:00
220378b3f2 web: Fix TypeScript compilation issues for mixins, events. (#13766) 2025-04-07 19:53:51 +02:00
363d655378 web: Normalize client-side error handling (#13595)
web: Clean up error handling. Prep for permission checks.

- Add clearer reporting for API and network errors.
- Tidy error checking.
- Partial type safety for events.
2025-04-07 19:50:41 +02:00
e93b2a1a75 website/integrations: Open Web UI: add OPENID_REDIRECT_URI environment variable (#13785)
added OPENID_REDIRECT_URI open webui environment variable

Signed-off-by: Yuval Ziv <44985263+yuval-ziv@users.noreply.github.com>
2025-04-07 12:02:21 -05:00
76665cf65e website/integrations: add knocknoc (#13764)
* Document explaining integration between authentik and knocknoc

* Clarified Knocknoc config

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Fixed typos

* fixed note markdown

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Fixed line breaks, clarified provider section, added protocol settings header and other formatting improvements

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

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-04-07 12:00:43 -05:00
3ad7f4dc24 sources: move identifier to parent model (#13797)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-07 18:01:41 +02:00
c5045e8792 stages/email: fix for newlines in emails (#13799)
stages/email: fix for newlines in emails (#13712)

* Test fix for newlines in emails

* fix linting

* remove base64 names from email address

* Make better checks on message.to

* Remove unnecessary logger
2025-04-07 17:34:26 +02:00
a8c9b3a8ba sources/kerberos, saml: allow creation of connections from the API (#13794)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-07 14:35:52 +00:00
148506639a website/docs: add skip object instructions (#13749)
* Beginning of work

* Added instructions for skipobject to each source

* removed saml

* removed oauth

* Updates

* Added provider SkipObject instructions

* combined examples into one

* modified kerberos python snippet as per suggestion from Marc

* Update website/docs/add-secure-apps/providers/property-mappings/index.md

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

* Update website/docs/users-sources/sources/protocols/kerberos/index.md

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

* Clarified how to use the exception

* Update website/docs/add-secure-apps/providers/property-mappings/index.md

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

* Update website/docs/add-secure-apps/providers/property-mappings/index.md

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

* fixed missing ) after gws

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* fixed missing . from /scim

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* fixing broken links

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Fixed links

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-04 11:05:03 -05:00
53814d9919 website/integrations: jenkins: fix oidc redirect uri (#13771)
Signed-off-by: Dominic R <dominic@sdko.org>
2025-04-04 08:03:14 +01:00
08b04c32f5 website/docs: add log levels section to logs documentation (#13687)
* Added debugging section and removed timestamps option

* Added details on trace and debug modes

* changed file to .mdx format

* Updated to include all log levels and a warning about trace

* Modified trace section

* Applied suggestions from dominic

* Prettier update

* Fixed tabs and lowercased the headers

* More tab fixes - prettier causing issues

* Prettier fix

* removed headers from inside tab sections

* added tabs import

* Changed line positioning for tabs import

* Update website/docs/troubleshooting/logs.mdx

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

* Applied suggestions from Dominic and Tana

* .

* Added tabs to last 2 sections as per suggestion from Tana

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-04-03 12:20:42 -05:00
1c1d97339d website/docs: Updated redirect URI setup for Synology DSM (#13761)
Updated redirect URI setup

Based on the feedback from Synology's developers, and testing: the redirect URI should not contain #/signup as it breaks authentication if multiple redirect URIs have to be set.

Based on DSM 7.2's code itself, Host and HTTPS headers are used internally to match the corresponding entry in the list.

Hope that can help, this is from days of testing + discussing with the support and dev teams.

Signed-off-by: Florent <Wr0ngName@users.noreply.github.com>
2025-04-03 09:17:19 -05:00
cafa9c1737 core: bump python-kadmin-rs from 0.5.3 to 0.6.0 (#13758)
* core: bump python-kadmin-rs from 0.5.3 to 0.6.0

Bumps [python-kadmin-rs](https://github.com/authentik-community/kadmin-rs) from 0.5.3 to 0.6.0.
- [Release notes](https://github.com/authentik-community/kadmin-rs/releases)
- [Commits](https://github.com/authentik-community/kadmin-rs/compare/kadmin/version/0.5.3...kadmin/version/0.6.0)

---
updated-dependencies:
- dependency-name: python-kadmin-rs
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-03 13:06:03 +00:00
5f64347ba1 website/integrations: add sidero omni (#13675)
* Mostly documented

* Typo

* Added testing step and formatted URLs

* Removed unnecessary URL

* Updated to newer templater

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Edited code marks

* Bolded some UI elements

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-03 08:04:37 -05:00
45ef54480a website/integrations: add certificate instructions to apache guacamole (#13684)
* added self signed certs section

* Added mention of OS specific section

* Updated to include synology instructions

* Fixed typos

* Applied suggestions from Dominic and clarified the target of the commands

* Added headers

* Updated keytool documentation link to JDK21 (latest)

* Squashed commit of the following:

commit f0e58a6f49
Author: Dominic R <dominic@sdko.org>
Date:   Tue Apr 1 17:37:11 2025 -0400

    website/docs: sys-mgmt: service accounts (#13722)

    * website/docs: ops: service accounts

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Update website/docs/sys-mgmt/service-accounts.md

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

    * Dewi's suggestions

    ---------

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

commit a3d642c08e
Author: Ben <bmfk_m@yahoo.de>
Date:   Tue Apr 1 22:09:31 2025 +0200

    website/integrations: add mailcow (#13727)

    * Add mailcow to Applications

    * Update wording and layout

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

    Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
    Signed-off-by: Ben <bmfk_m@yahoo.de>

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

    Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
    Signed-off-by: Ben <bmfk_m@yahoo.de>

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

    Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
    Signed-off-by: Ben <bmfk_m@yahoo.de>

    * lint

    ---------

    Signed-off-by: Ben <bmfk_m@yahoo.de>
    Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>

commit 5d42cb9185
Author: Tana M Berry <tanamarieberry@yahoo.com>
Date:   Tue Apr 1 15:00:18 2025 -0500

    website: edit menu items (#13747)

    for review

    Co-authored-by: Tana M Berry <tana@goauthentik.com>

commit 1fd0cc5bb5
Author: Dominic R <dominic@sdko.org>
Date:   Tue Apr 1 14:31:07 2025 -0400

    website/integrations: slack,pocketbase,tandoor: convert to new authentik configuration format (#13742)

    * website/integrations-all: update authentik configuration template

    * website/integrations: slack,pocketbase,tandoor: convert to new authentik configuration format

    * Revert "website/integrations-all: update authentik configuration template"

    Not for this PR. Don't want to cause merge conflicts later on.

    This reverts commit 8378502090.

commit deef365ff5
Author: Dominic R <dominic@sdko.org>
Date:   Tue Apr 1 12:51:31 2025 -0400

    website/integrations-all: update authentik configuration template (#13740)

commit d1ae6287f2
Author: Jens L. <jens@goauthentik.io>
Date:   Tue Apr 1 18:35:35 2025 +0200

    web/admin: fix custom scope mappings being selected by default in proxy provider (#13735)

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

commit 2e152cd264
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 1 18:29:16 2025 +0200

    web: bump vite from 5.4.15 to 5.4.16 in /web (#13743)

    Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.15 to 5.4.16.
    - [Release notes](https://github.com/vitejs/vite/releases)
    - [Changelog](https://github.com/vitejs/vite/blob/v5.4.16/packages/vite/CHANGELOG.md)
    - [Commits](https://github.com/vitejs/vite/commits/v5.4.16/packages/vite)

    ---
    updated-dependencies:
    - dependency-name: vite
      dependency-version: 5.4.16
      dependency-type: indirect
    ...

    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

commit f5941e403b
Author: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
Date:   Tue Apr 1 18:18:59 2025 +0200

    translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13736)

    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>

commit ff3cf8c10e
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Tue Apr 1 18:18:42 2025 +0200

    core: bump goauthentik.io/api/v3 from 3.2025023.1 to 3.2025023.2 (#13746)

    Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025023.1 to 3.2025023.2.
    - [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.2025023.1...v3.2025023.2)

    ---
    updated-dependencies:
    - dependency-name: goauthentik.io/api/v3
      dependency-version: 3.2025023.2
      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>

commit bfa6328172
Author: Dominic R <dominic@sdko.org>
Date:   Tue Apr 1 09:46:29 2025 -0400

    web/common: utils: fix infinite value handling in getRelativeTime function (#13564)

    Squash sdko/closes-13562

commit 4c9691c932
Author: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Date:   Tue Apr 1 12:58:43 2025 +0200

    stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#13744)

    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>

commit a0f1566b4c
Author: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Date:   Tue Apr 1 02:15:47 2025 +0200

    web: bump API Client version (#13741)

    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>

commit 46261a4f42
Author: Jens L. <jens@goauthentik.io>
Date:   Tue Apr 1 01:41:18 2025 +0200

    */saml: allow for domainless SAML URLs (#13737)

commit 8b42ff1e97
Author: Dominic R <dominic@sdko.org>
Date:   Mon Mar 31 12:36:14 2025 -0400

    core: fix error when viewing used_by for built-in source (#13588)

    Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
    Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

commit ca4cb0d251
Author: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
Date:   Mon Mar 31 15:54:37 2025 +0000

    translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13738)

    * 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>

commit a5a0fa79dd
Author: Tana M Berry <tanamarieberry@yahoo.com>
Date:   Mon Mar 31 07:57:03 2025 -0500

    website/docs: style guide (#13704)

    * new word choices, tweaks

    * shockingly, a typo

    * tweaks

    * Update website/docs/developer-docs/docs/style-guide.mdx

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

    ---------

    Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
    Co-authored-by: Tana M Berry <tana@goauthentik.com>
    Co-authored-by: Dominic R <dominic@sdko.org>
    Co-authored-by: Jens Langhammer <jens@goauthentik.io>

commit c06a871f61
Author: Marcel Kempf <marcel.kempf@tum.de>
Date:   Mon Mar 31 12:58:03 2025 +0200

    core: fix double slash in cache key (#13721)

commit 4a3df67134
Author: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Date:   Mon Mar 31 12:57:16 2025 +0200

    core, web: update translations (#13728)

    Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
    Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>

commit 422ccf61fa
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Mon Mar 31 12:27:56 2025 +0200

    core: bump goauthentik.io/api/v3 from 3.2025022.6 to 3.2025023.1 (#13729)

    Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025022.6 to 3.2025023.1.
    - [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.2025022.6...v3.2025023.1)

    ---
    updated-dependencies:
    - dependency-name: goauthentik.io/api/v3
      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>

commit d989f23907
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Mon Mar 31 12:27:44 2025 +0200

    website: bump the build group in /website with 3 updates (#13730)

    Bumps the build group in /website with 3 updates: [@rspack/binding-darwin-arm64](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack), [@rspack/binding-linux-arm64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack) and [@rspack/binding-linux-x64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack).

    Updates `@rspack/binding-darwin-arm64` from 1.2.8 to 1.3.0
    - [Release notes](https://github.com/web-infra-dev/rspack/releases)
    - [Commits](https://github.com/web-infra-dev/rspack/commits/v1.3.0/packages/rspack)

    Updates `@rspack/binding-linux-arm64-gnu` from 1.2.8 to 1.3.0
    - [Release notes](https://github.com/web-infra-dev/rspack/releases)
    - [Commits](https://github.com/web-infra-dev/rspack/commits/v1.3.0/packages/rspack)

    Updates `@rspack/binding-linux-x64-gnu` from 1.2.8 to 1.3.0
    - [Release notes](https://github.com/web-infra-dev/rspack/releases)
    - [Commits](https://github.com/web-infra-dev/rspack/commits/v1.3.0/packages/rspack)

    ---
    updated-dependencies:
    - dependency-name: "@rspack/binding-darwin-arm64"
      dependency-type: direct:production
      update-type: version-update:semver-minor
      dependency-group: build
    - dependency-name: "@rspack/binding-linux-arm64-gnu"
      dependency-type: direct:production
      update-type: version-update:semver-minor
      dependency-group: build
    - dependency-name: "@rspack/binding-linux-x64-gnu"
      dependency-type: direct:production
      update-type: version-update:semver-minor
      dependency-group: build
    ...

    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

commit 059180edef
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Mon Mar 31 12:27:18 2025 +0200

    core: bump astral-sh/uv from 0.6.10 to 0.6.11 (#13733)

    Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.10 to 0.6.11.
    - [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.6.10...0.6.11)

    ---
    updated-dependencies:
    - dependency-name: astral-sh/uv
      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>

commit 22f30634a8
Author: garar <krystiankichewko@gmail.com>
Date:   Sun Mar 30 20:28:11 2025 +0200

    website/docs: Fix Caddy forward auth example (#13726)

commit 35ff418c42
Author: Jens L. <jens@goauthentik.io>
Date:   Sun Mar 30 19:56:03 2025 +0200

    policies: buffered policy access view for concurrent authorization attempts when unauthenticated (#13629)

    * policies: buffered policy access view for concurrent authorization attempts when unauthenticated

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

    * better cleanup

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

    * more polish

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

    * more cleanup

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

    * add tests

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

    * fix multiple redirects, add e2e test

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

    * unrelated: add sp initiated post test

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

    * add SAML parallel test

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

    * format

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

    * optimise detection of when authentication is in progress

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

    * better backoff timing

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

    ---------

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

commit 7826e7a605
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Sun Mar 30 03:26:30 2025 +0200

    core: bump oss/go/microsoft/golang from 1.23-fips-bookworm to 1.24-fips-bookworm (#13027)

    * core: bump oss/go/microsoft/golang

    Bumps oss/go/microsoft/golang from 1.23-fips-bookworm to 1.24-fips-bookworm.

    ---
    updated-dependencies:
    - dependency-name: oss/go/microsoft/golang
      dependency-type: direct:production
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

    * upstream docker image, use native fips

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

    * bump go version

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

    ---------

    Signed-off-by: dependabot[bot] <support@github.com>
    Signed-off-by: Jens Langhammer <jens@goauthentik.io>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Jens Langhammer <jens@goauthentik.io>

commit 64f1b8207d
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Sat Mar 29 00:51:08 2025 +0100

    web: bump tar-fs from 2.1.1 to 2.1.2 in /web (#13713)

    Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 2.1.1 to 2.1.2.
    - [Commits](https://github.com/mafintosh/tar-fs/compare/v2.1.1...v2.1.2)

    ---
    updated-dependencies:
    - dependency-name: tar-fs
      dependency-type: indirect
    ...

    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

commit b2c13f0614
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 22:14:15 2025 +0100

    core: fix flaky tests introduced with is_superuser API fix (#13709)

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

commit 6965628020
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 22:13:34 2025 +0100

    root: bump python patch version to 3.12.9 (#13710)

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

commit 608f63e9a2
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 17:42:45 2025 +0100

    website/docs: add reference to setting in CVE (#13707)

    * website/docs: add reference to setting in CVE

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

    * reword

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

    ---------

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

commit 22fa3a7fba
Author: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Date:   Fri Mar 28 17:42:24 2025 +0100

    web: bump API Client version (#13708)

    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>

commit bcfd6fefa7
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 17:08:57 2025 +0100

    release: 2025.2.3 (#13705)

    * release: 2025.2.3

    * fix uv lock not being bumped

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

    ---------

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

commit eae18d0016
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 14:55:56 2025 +0100

    website/docs: fix 2025 CVE category title (#13703)

    * website/docs: fix 2025 CVE category title

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

    * add sideeffect of changing session backend

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

    ---------

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

commit 4a12a57c5f
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 14:49:35 2025 +0100

    website/docs: update release notes for 2024.12 and 2025.2 (#13702)

    * website/docs: update release notes for 2025.2 and 2024.12

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

    * update

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

    * update v2

    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>

commit 71294b7deb
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 14:20:09 2025 +0100

    security: fix CVE-2025-29928 (#13695)

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

commit 5af907db0c
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 14:16:13 2025 +0100

    stages/identification: refresh captcha on failure (#13697)

    * refactor cleanup behavior after stage form submit

    * refresh captcha on failing Identification stage

    * Revert "stages/identification: check captcha after checking authentication (#13533)"

    This reverts commit b7beac6795.

    Including a Captcha stage in an Identification stage is partially to
    prevent password spraying attacks. The reverted commit negated this
    feature to fix a UX bug. After 6fde42a9170, the functionality can now be
    reinstated.

    ---------

    Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>

commit 63a118a2ba
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 14:15:39 2025 +0100

    core: fix non-exploitable open redirect (#13696)

    discovered by @dominic-r

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

commit d9a3c34a44
Author: Jens L. <jens@goauthentik.io>
Date:   Fri Mar 28 14:00:13 2025 +0100

    core: fix core/user is_superuser filter (#13693)

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

commit 23bdad7574
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Fri Mar 28 13:21:30 2025 +0100

    website: bump @types/semver from 7.5.8 to 7.7.0 in /website (#13682)

    Bumps [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver) from 7.5.8 to 7.7.0.
    - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
    - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

    ---
    updated-dependencies:
    - dependency-name: "@types/semver"
      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>

commit 8ee90826fc
Author: Jens L. <jens@goauthentik.io>
Date:   Thu Mar 27 19:07:36 2025 +0100

    enterprise/stages/source: set is_redirected in flow source stage redirects to (#13604)

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

commit 8c7d4d2f5e
Author: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Date:   Thu Mar 27 17:49:16 2025 +0100

    website/docs: Clarify frontend development. Document local overrides. (#13586)

    * website/docs: Clarify setup flow. Document local overrides.

    * Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

    * Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

    * Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

    * Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

    * Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

    * Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

    * Update website/docs/developer-docs/setup/full-dev-environment.mdx

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

    * Update website/docs/install-config/install/docker-compose.mdx

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

    * Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

    * Update website/docs/developer-docs/setup/full-dev-environment.mdx

    Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

    * Update authentik/lib/default.yml

    Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

    * fix linting to please the ci check

    ---------

    Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
    Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
    Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
    Co-authored-by: Dominic R <dominic@sdko.org>
    Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>

commit d72def0368
Author: Jens L. <jens@goauthentik.io>
Date:   Wed Mar 26 23:06:12 2025 +0000

    web/admin: add sync status refresh button (#13678)

    * web/admin: add refresh button to sync status card

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

    * auto-expand if there's just one task

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

    ---------

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

commit 5bcf501842
Author: Jens L. <jens@goauthentik.io>
Date:   Wed Mar 26 23:05:43 2025 +0000

    outposts/ldap: fix paginator going into infinite loop (#13677)

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

commit 13fc216c68
Author: Dominic R <dominic@sdko.org>
Date:   Wed Mar 26 17:38:57 2025 -0400

    website/integrations-all: convert authentik configuration to wizard (#13144)

    * init

    * 6 more

    * tana...

    * quick reformat

    * welp only time for one change

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * Revert "wip"

    This reverts commit e71f0d22e3f093350e8d12eaad5e5c0f9d38253c.

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * a

commit 27aed4b315
Author: Dominic R <dominic@sdko.org>
Date:   Wed Mar 26 13:16:46 2025 -0400

    web: ensure wizard modal closes on first cancel click (#13636)

    The application wizard modal previously required two clicks of the cancel
    button to close when opened from the User Interface.
    This was caused by improper event handling where events
    would propagate up the DOM tree potentially triggering multiple handlers.

commit 84b5992e55
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Wed Mar 26 18:03:20 2025 +0100

    ci: bump golangci/golangci-lint-action from 6 to 7 (#13661)

    * ci: bump golangci/golangci-lint-action from 6 to 7

    Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6 to 7.
    - [Release notes](https://github.com/golangci/golangci-lint-action/releases)
    - [Commits](https://github.com/golangci/golangci-lint-action/compare/v6...v7)

    ---
    updated-dependencies:
    - dependency-name: golangci/golangci-lint-action
      dependency-type: direct:production
      update-type: version-update:semver-major
    ...

    Signed-off-by: dependabot[bot] <support@github.com>

    * fix lint

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

    * fix v2

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

    * fix v3

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

    ---------

    Signed-off-by: dependabot[bot] <support@github.com>
    Signed-off-by: Jens Langhammer <jens@goauthentik.io>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Jens Langhammer <jens@goauthentik.io>

commit 7eb985f636
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Wed Mar 26 17:05:42 2025 +0100

    website: bump the build group in /website with 3 updates (#13660)

    Bumps the build group in /website with 3 updates: [@swc/core-darwin-arm64](https://github.com/swc-project/swc), [@swc/core-linux-arm64-gnu](https://github.com/swc-project/swc) and [@swc/core-linux-x64-gnu](https://github.com/swc-project/swc).

    Updates `@swc/core-darwin-arm64` from 1.11.12 to 1.11.13
    - [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.11.12...v1.11.13)

    Updates `@swc/core-linux-arm64-gnu` from 1.11.12 to 1.11.13
    - [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.11.12...v1.11.13)

    Updates `@swc/core-linux-x64-gnu` from 1.11.12 to 1.11.13
    - [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.11.12...v1.11.13)

    ---
    updated-dependencies:
    - dependency-name: "@swc/core-darwin-arm64"
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: build
    - dependency-name: "@swc/core-linux-arm64-gnu"
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: build
    - dependency-name: "@swc/core-linux-x64-gnu"
      dependency-type: direct:production
      update-type: version-update:semver-patch
      dependency-group: build
    ...

    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deployment -> host
2025-04-03 08:03:17 -05:00
a3dc8af4c6 core, web: update translations (#13753)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-04-03 14:27:34 +02:00
36933a0aca lifecycle/aws: bump aws-cdk from 2.1006.0 to 2.1007.0 in /lifecycle/aws (#13757)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1006.0 to 2.1007.0.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1007.0/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-version: 2.1007.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-04-03 14:15:50 +02:00
8f689890df core: bump astral-sh/uv from 0.6.11 to 0.6.12 (#13756)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.11 to 0.6.12.
- [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.6.11...0.6.12)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.6.12
  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-04-03 14:13:43 +02:00
ec49b2e0e0 website/integrations: calibre-web: document (#12477)
* website/integrations: calibre-web: add to sidebar

Adds the calibre-web integration to the sidebar.

Signed-off-by: 4d62 <github-user@sdko.org>

* website/integrations: calibre-web: init

Initializes the documentation with the placeholder. I have a feeling this is going to be funnnnnnnnnnnnnnnnn

Signed-off-by: 4d62 <github-user@sdko.org>

* website/integrations: calibre-web: service configuration

Adds configuration documentation for calibre-web

PS: Never setup a LDAP outpost before and I don't have calibre web so uhhh yea im gonna take care of this after the holidays (probably)

Signed-off-by: 4d62 <github-user@sdko.org>

* Update index.md

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Changed proider pair instructions to new version

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Update website/integrations/services/calibre-web/index.md

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

---------

Signed-off-by: 4d62 <github-user@sdko.org>
Signed-off-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-04-02 12:57:53 -05:00
22ebe05706 website: bump image-size from 1.1.1 to 1.2.1 in /website (#13750)
Bumps [image-size](https://github.com/image-size/image-size) from 1.1.1 to 1.2.1.
- [Release notes](https://github.com/image-size/image-size/releases)
- [Commits](https://github.com/image-size/image-size/compare/v1.1.1...v1.2.1)

---
updated-dependencies:
- dependency-name: image-size
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-02 18:41:59 +02:00
f0e58a6f49 website/docs: sys-mgmt: service accounts (#13722)
* website/docs: ops: service accounts

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Update website/docs/sys-mgmt/service-accounts.md

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

* Dewi's suggestions

---------

Signed-off-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-01 16:37:11 -05:00
Ben
a3d642c08e website/integrations: add mailcow (#13727)
* Add mailcow to Applications

* Update wording and layout

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

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Ben <bmfk_m@yahoo.de>

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

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Ben <bmfk_m@yahoo.de>

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

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Ben <bmfk_m@yahoo.de>

* lint

---------

Signed-off-by: Ben <bmfk_m@yahoo.de>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-01 15:09:31 -05:00
5d42cb9185 website: edit menu items (#13747)
for review

Co-authored-by: Tana M Berry <tana@goauthentik.com>
2025-04-01 15:00:18 -05:00
1fd0cc5bb5 website/integrations: slack,pocketbase,tandoor: convert to new authentik configuration format (#13742)
* website/integrations-all: update authentik configuration template

* website/integrations: slack,pocketbase,tandoor: convert to new authentik configuration format

* Revert "website/integrations-all: update authentik configuration template"

Not for this PR. Don't want to cause merge conflicts later on.

This reverts commit 8378502090.
2025-04-01 13:31:07 -05:00
deef365ff5 website/integrations-all: update authentik configuration template (#13740) 2025-04-01 11:51:31 -05:00
d1ae6287f2 web/admin: fix custom scope mappings being selected by default in proxy provider (#13735)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-04-01 18:35:35 +02:00
2e152cd264 web: bump vite from 5.4.15 to 5.4.16 in /web (#13743)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.15 to 5.4.16.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.16/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.16/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.16
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 18:29:16 +02:00
f5941e403b translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13736)
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-04-01 18:18:59 +02:00
ff3cf8c10e core: bump goauthentik.io/api/v3 from 3.2025023.1 to 3.2025023.2 (#13746)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025023.1 to 3.2025023.2.
- [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.2025023.1...v3.2025023.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-version: 3.2025023.2
  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-04-01 18:18:42 +02:00
bfa6328172 web/common: utils: fix infinite value handling in getRelativeTime function (#13564)
Squash sdko/closes-13562
2025-04-01 06:46:29 -07:00
4c9691c932 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#13744)
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-04-01 12:58:43 +02:00
a0f1566b4c web: bump API Client version (#13741)
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-04-01 02:15:47 +02:00
46261a4f42 */saml: allow for domainless SAML URLs (#13737) 2025-04-01 01:41:18 +02:00
8b42ff1e97 core: fix error when viewing used_by for built-in source (#13588)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-03-31 16:36:14 +00:00
ca4cb0d251 translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13738)
* 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-03-31 15:54:37 +00:00
a5a0fa79dd website/docs: style guide (#13704)
* new word choices, tweaks

* shockingly, a typo

* tweaks

* Update website/docs/developer-docs/docs/style-guide.mdx

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

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-03-31 07:57:03 -05:00
c06a871f61 core: fix double slash in cache key (#13721) 2025-03-31 12:58:03 +02:00
4a3df67134 core, web: update translations (#13728)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-03-31 12:57:16 +02:00
422ccf61fa core: bump goauthentik.io/api/v3 from 3.2025022.6 to 3.2025023.1 (#13729)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025022.6 to 3.2025023.1.
- [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.2025022.6...v3.2025023.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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-03-31 12:27:56 +02:00
d989f23907 website: bump the build group in /website with 3 updates (#13730)
Bumps the build group in /website with 3 updates: [@rspack/binding-darwin-arm64](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack), [@rspack/binding-linux-arm64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack) and [@rspack/binding-linux-x64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack).


Updates `@rspack/binding-darwin-arm64` from 1.2.8 to 1.3.0
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.3.0/packages/rspack)

Updates `@rspack/binding-linux-arm64-gnu` from 1.2.8 to 1.3.0
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.3.0/packages/rspack)

Updates `@rspack/binding-linux-x64-gnu` from 1.2.8 to 1.3.0
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.3.0/packages/rspack)

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 12:27:44 +02:00
059180edef core: bump astral-sh/uv from 0.6.10 to 0.6.11 (#13733)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.10 to 0.6.11.
- [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.6.10...0.6.11)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  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-03-31 12:27:18 +02:00
22f30634a8 website/docs: Fix Caddy forward auth example (#13726) 2025-03-30 20:28:11 +02:00
35ff418c42 policies: buffered policy access view for concurrent authorization attempts when unauthenticated (#13629)
* policies: buffered policy access view for concurrent authorization attempts when unauthenticated

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

* better cleanup

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

* more polish

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

* more cleanup

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

* add tests

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

* fix multiple redirects, add e2e test

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

* unrelated: add sp initiated post test

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

* add SAML parallel test

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

* format

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

* optimise detection of when authentication is in progress

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

* better backoff timing

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-30 19:56:03 +02:00
7826e7a605 core: bump oss/go/microsoft/golang from 1.23-fips-bookworm to 1.24-fips-bookworm (#13027)
* core: bump oss/go/microsoft/golang

Bumps oss/go/microsoft/golang from 1.23-fips-bookworm to 1.24-fips-bookworm.

---
updated-dependencies:
- dependency-name: oss/go/microsoft/golang
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* upstream docker image, use native fips

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

* bump go version

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-03-30 03:26:30 +02:00
64f1b8207d web: bump tar-fs from 2.1.1 to 2.1.2 in /web (#13713)
Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 2.1.1 to 2.1.2.
- [Commits](https://github.com/mafintosh/tar-fs/compare/v2.1.1...v2.1.2)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-29 00:51:08 +01:00
b2c13f0614 core: fix flaky tests introduced with is_superuser API fix (#13709)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 22:14:15 +01:00
6965628020 root: bump python patch version to 3.12.9 (#13710)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 22:13:34 +01:00
608f63e9a2 website/docs: add reference to setting in CVE (#13707)
* website/docs: add reference to setting in CVE

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

* reword

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 17:42:45 +01:00
22fa3a7fba web: bump API Client version (#13708)
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-03-28 17:42:24 +01:00
bcfd6fefa7 release: 2025.2.3 (#13705)
* release: 2025.2.3

* fix uv lock not being bumped

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 17:08:57 +01:00
eae18d0016 website/docs: fix 2025 CVE category title (#13703)
* website/docs: fix 2025 CVE category title

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

* add sideeffect of changing session backend

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 14:55:56 +01:00
4a12a57c5f website/docs: update release notes for 2024.12 and 2025.2 (#13702)
* website/docs: update release notes for 2025.2 and 2024.12

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

* update

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

* update v2

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>
2025-03-28 14:49:35 +01:00
71294b7deb security: fix CVE-2025-29928 (#13695)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 14:20:09 +01:00
5af907db0c stages/identification: refresh captcha on failure (#13697)
* refactor cleanup behavior after stage form submit

* refresh captcha on failing Identification stage

* Revert "stages/identification: check captcha after checking authentication (#13533)"

This reverts commit b7beac6795.

Including a Captcha stage in an Identification stage is partially to
prevent password spraying attacks. The reverted commit negated this
feature to fix a UX bug. After 6fde42a9170, the functionality can now be
reinstated.

---------

Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
2025-03-28 14:16:13 +01:00
63a118a2ba core: fix non-exploitable open redirect (#13696)
discovered by @dominic-r

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 14:15:39 +01:00
d9a3c34a44 core: fix core/user is_superuser filter (#13693)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 14:00:13 +01:00
23bdad7574 website: bump @types/semver from 7.5.8 to 7.7.0 in /website (#13682)
Bumps [@types/semver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/semver) from 7.5.8 to 7.7.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/semver)

---
updated-dependencies:
- dependency-name: "@types/semver"
  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-03-28 13:21:30 +01:00
8ee90826fc enterprise/stages/source: set is_redirected in flow source stage redirects to (#13604)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-27 19:07:36 +01:00
8c7d4d2f5e website/docs: Clarify frontend development. Document local overrides. (#13586)
* website/docs: Clarify setup flow. Document local overrides.

* Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

* Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

* Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

* Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

* Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

* Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

* Update website/docs/developer-docs/setup/full-dev-environment.mdx

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

* Update website/docs/install-config/install/docker-compose.mdx

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

* Update website/docs/developer-docs/setup/frontend-dev-environment.md

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

* Update website/docs/developer-docs/setup/full-dev-environment.mdx

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

* Update authentik/lib/default.yml

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

* fix linting to please the ci check

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-03-27 11:49:16 -05:00
d72def0368 web/admin: add sync status refresh button (#13678)
* web/admin: add refresh button to sync status card

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

* auto-expand if there's just one task

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-27 00:06:12 +01:00
5bcf501842 outposts/ldap: fix paginator going into infinite loop (#13677)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-27 00:05:43 +01:00
13fc216c68 website/integrations-all: convert authentik configuration to wizard (#13144)
* init

* 6 more

* tana...

* quick reformat

* welp only time for one change

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Revert "wip"

This reverts commit e71f0d22e3f093350e8d12eaad5e5c0f9d38253c.

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* a
2025-03-26 16:38:57 -05:00
27aed4b315 web: ensure wizard modal closes on first cancel click (#13636)
The application wizard modal previously required two clicks of the cancel
button to close when opened from the User Interface.
This was caused by improper event handling where events
would propagate up the DOM tree potentially triggering multiple handlers.
2025-03-26 18:16:46 +01:00
84b5992e55 ci: bump golangci/golangci-lint-action from 6 to 7 (#13661)
* ci: bump golangci/golangci-lint-action from 6 to 7

Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 6 to 7.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix lint

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

* fix v2

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

* fix v3

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-03-26 18:03:20 +01:00
7eb985f636 website: bump the build group in /website with 3 updates (#13660)
Bumps the build group in /website with 3 updates: [@swc/core-darwin-arm64](https://github.com/swc-project/swc), [@swc/core-linux-arm64-gnu](https://github.com/swc-project/swc) and [@swc/core-linux-x64-gnu](https://github.com/swc-project/swc).


Updates `@swc/core-darwin-arm64` from 1.11.12 to 1.11.13
- [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.11.12...v1.11.13)

Updates `@swc/core-linux-arm64-gnu` from 1.11.12 to 1.11.13
- [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.11.12...v1.11.13)

Updates `@swc/core-linux-x64-gnu` from 1.11.12 to 1.11.13
- [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.11.12...v1.11.13)

---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 17:05:42 +01:00
d3172ae904 web: bump vite from 5.4.14 to 5.4.15 in /web (#13672)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.14 to 5.4.15.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.15/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.15/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 14:22:25 +01:00
88662b54c1 core: bump astral-sh/uv from 0.6.9 to 0.6.10 (#13669)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.9 to 0.6.10.
- [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.6.9...0.6.10)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  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-03-26 12:01:43 +01:00
b38bc8c1c4 lifecycle/aws: bump aws-cdk from 2.1005.0 to 2.1006.0 in /lifecycle/aws (#13670)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1005.0 to 2.1006.0.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1006.0/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  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-03-26 12:00:06 +01:00
a9b648842a website/docs: Flesh out integrations copy changes. (#13619)
* website/docs: Flesh out integrations copy changes.

* Apply suggestions from code review

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

* Lint.

* Revert removed section. Fix links.

* reorder integrations page sections

Signed-off-by: Fletcher Heisler <fheisler@users.noreply.github.com>

* add back page title

Signed-off-by: Fletcher Heisler <fheisler@users.noreply.github.com>

* move cards to very end of topic

* fix broken anchor link

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Fletcher Heisler <fheisler@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Fletcher Heisler <fheisler@users.noreply.github.com>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
2025-03-25 12:40:21 -05:00
5fda531e2b website/docs: add section on how to capture logs (#13662)
* Added logs file with basic instructions for capturing logs

* Included kubernetes instructions

* Fixed typos

* Fixed commands

* typo

* Updated kubernetes section

* updated as per suggestions from Dominic

* further changes to simplify the document

* Added section about Ctrl + C to stop logs

---------

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-03-25 12:28:57 -05:00
921a3e6eb8 website/docs: Add Fleet integration. (#13618)
* website/docs: Add Fleet integration.

* Apply suggestions from code review

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

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

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

* Update index.md

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

* website/docs: Reorder.

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-03-25 11:54:16 -05:00
fd898bea66 stages/email: Clean newline characters in TemplateEmailMessage (#13666)
* Clean new line characters in TemplateEmailMessage

* Use blankspace replace in names

* Use blankspace replace in names
2025-03-25 12:39:29 -04:00
cbf9ee55ae root: new issue template for Docs (#13659)
* new issue template for Docs

* added note about a PR

* Update .github/ISSUE_TEMPLATE/docs_issue.md

Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update .github/ISSUE_TEMPLATE/docs_issue.md

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-03-25 11:38:17 -05:00
590ee7d9d4 core, web: update translations (#13658)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-03-25 12:47:51 +01:00
b8cd1d1ae2 website/docs: fix referral of Paperless-ng (#13657)
Original description referred to Paperless-ngx as being a fork of Paperless-ngx instead of Paperless-ng (without x).

Signed-off-by: joeftiger <j.oeftiger@protonmail.com>
2025-03-24 18:44:08 -05:00
9f9524fbcb ci: stop publishing latest tag (#13245)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-24 20:23:55 +00:00
1df87cdf77 root: fix dependency install due to description-file (#13655)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-24 20:18:18 +00:00
6383550914 admin: fix system API when using bearer token (#13651)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-03-24 14:42:20 +00:00
10771b4779 website: bump the build group in /website with 6 updates (#13645)
Bumps the build group in /website with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@swc/core-darwin-arm64](https://github.com/swc-project/swc) | `1.11.11` | `1.11.12` |
| [@swc/core-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.11.11` | `1.11.12` |
| [@swc/core-linux-x64-gnu](https://github.com/swc-project/swc) | `1.11.11` | `1.11.12` |
| [@swc/html-darwin-arm64](https://github.com/swc-project/swc) | `1.11.11` | `1.11.13` |
| [@swc/html-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.11.11` | `1.11.13` |
| [@swc/html-linux-x64-gnu](https://github.com/swc-project/swc) | `1.11.11` | `1.11.13` |


Updates `@swc/core-darwin-arm64` from 1.11.11 to 1.11.12
- [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.11.11...v1.11.12)

Updates `@swc/core-linux-arm64-gnu` from 1.11.11 to 1.11.12
- [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.11.11...v1.11.12)

Updates `@swc/core-linux-x64-gnu` from 1.11.11 to 1.11.12
- [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.11.11...v1.11.12)

Updates `@swc/html-darwin-arm64` from 1.11.11 to 1.11.13
- [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.11.11...v1.11.13)

Updates `@swc/html-linux-arm64-gnu` from 1.11.11 to 1.11.13
- [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.11.11...v1.11.13)

Updates `@swc/html-linux-x64-gnu` from 1.11.11 to 1.11.13
- [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.11.11...v1.11.13)

---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 14:41:38 +00:00
fcaf1193ed core: bump goauthentik.io/api/v3 from 3.2025022.5 to 3.2025022.6 (#13646)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025022.5 to 3.2025022.6.
- [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.2025022.5...v3.2025022.6)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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-03-24 14:41:27 +00:00
b9f6093e6f translate: Updates for file web/xliff/en.xlf in fr (#13653)
Translate web/xliff/en.xlf in fr

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-03-24 13:52:37 +00:00
47f6d59758 translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13652)
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-03-24 13:52:12 +00:00
59d20e3bc0 website/integrations: add tandoor (#13560)
* website/integrations: add tandoor

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <chwshka@outlook.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <chwshka@outlook.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <chwshka@outlook.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <chwshka@outlook.com>

* Updated to match recommendations

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <chwshka@outlook.com>

* Further updates to match suggestions

* Updated to use <kbd> and <em> tags

* fixed codeblock

* Added explanatory text and removed extra EM tags

* fixed prettier issue

* moved ` to line 52

---------

Signed-off-by: Dewi Roberts <chwshka@outlook.com>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-03-24 07:55:34 -05:00
ae347cd1c5 core, web: update translations (#13642)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-03-24 11:08:44 +01:00
7653a35caa providers/scim: fix group membership check failing (#13644)
closes #12917

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-24 02:51:04 +00:00
dc9b12fd37 ci: add semgrep (#13643)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-24 00:40:41 +00:00
b7dac0674a flows: fix API not returning configured background (#13641)
* flows: fix API not returning configured background

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

* add test

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-24 00:10:45 +00:00
5a17dea765 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13631)
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-03-23 20:08:15 +00:00
044547c316 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#13633)
Translate django.po in zh-Hans

100% translated source file: 'django.po'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-03-23 20:07:53 +00:00
6a84e7e6b0 translate: Updates for file web/xliff/en.xlf in zh_CN (#13632)
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-03-23 20:07:51 +00:00
6d4bb77960 translate: Updates for file web/xliff/en.xlf in zh-Hans (#13634)
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-03-23 20:07:37 +00:00
1b588b98bc brands: fix migration 0008 by removing incorrect context manager usage (#13635)
core: brands: fix migration 0008
2025-03-23 19:42:33 +00:00
3eccef88aa web: Fix prop. (#13630) 2025-03-22 17:18:07 +01:00
8f50dfa0c5 core, web: update translations (#13628)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-03-22 13:28:36 +00:00
8417d8508f web/admin: reworked sync status card (#13625)
* reworked sync status

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

* update imports

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

* add story and fix import

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>
2025-03-21 22:48:28 +00:00
b2c2fc001b core: bump github.com/golang-jwt/jwt/v5 from 5.2.1 to 5.2.2 (#13626)
Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.1 to 5.2.2.
- [Release notes](https://github.com/golang-jwt/jwt/releases)
- [Changelog](https://github.com/golang-jwt/jwt/blob/main/VERSION_HISTORY.md)
- [Commits](https://github.com/golang-jwt/jwt/compare/v5.2.1...v5.2.2)

---
updated-dependencies:
- dependency-name: github.com/golang-jwt/jwt/v5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-21 22:48:16 +00:00
f60312cbbc translate: Updates for file web/xliff/en.xlf in zh-Hans (#13622)
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-03-21 20:16:25 +00:00
7614b17a05 web: bump API Client version (#13623)
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-03-21 20:16:17 +00:00
8947376edb translate: Updates for file web/xliff/en.xlf in zh_CN (#13621)
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-03-21 20:16:12 +00:00
ce23209ae8 events: add configurable headers to webhooks (#13602)
* events: add configurable headers to webhooks

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

* make it a full thing

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

* fix migration

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-21 19:37:15 +00:00
0b806b7130 web: Client-side MDX rendering (#13610)
* web: Allow build errors to propagate.

* web: Refactor MDX for client-side rendering.

* Remove override

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

* revert css for links and tables

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

* web: Move Markdown specific styles.

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-03-21 19:32:52 +00:00
9538cf4690 website/docs: revert token_expiry format in example blueprint (#13582)
* revert token_expiry format in example blueprint

Signed-off-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>

* Revert blueprint change, use hard link to the previous version in the docs

---------

Signed-off-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
2025-03-21 19:13:35 +01:00
63da458fb3 website: update header to match goauthentik.io (#13616)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-21 17:33:44 +00:00
873dab29a9 translate: Updates for file web/xliff/en.xlf in fr (#13615)
Translate web/xliff/en.xlf in fr

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-03-21 16:28:58 +00:00
1e96c80593 core, web: update translations (#13608)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-03-21 17:14:08 +01:00
ee4a922234 core: bump astral-sh/uv from 0.6.8 to 0.6.9 (#13612)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.8 to 0.6.9.
- [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.6.8...0.6.9)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  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-03-21 17:11:54 +01:00
37a2eff716 website: components: add multilinecodeblock component (#13179)
* wip

* wip

* wip

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

wip

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

wip

* wip

* wip

* move css to same folder

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-03-21 10:08:24 -05:00
50e2f1c474 website/docs: add clarification about formatting URLs to Style Guide (#13601)
* a few additions

* codespell fixes??

* clarify URL formatting

* tweak

* Update website/docs/developer-docs/docs/style-guide.mdx

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

* Update website/docs/developer-docs/docs/style-guide.mdx

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

* conflict of course

* bump build

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-03-20 20:10:34 -05:00
ab7338b50e core: bump github.com/redis/go-redis/v9 from 9.7.1 to 9.7.3 (#13603)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.7.1 to 9.7.3.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.7.1...v9.7.3)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-20 19:41:12 +00:00
bcdc6fcd36 lib: set a default HTTP timeout on outgoing requests (#13599)
* lib: set a default HTTP timeout on outgoing requests

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

* add config

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-20 16:44:12 +00:00
98c3e0d68b website/integrations: add miniflux (#13559)
* website/integrations: add miniflux

* fixes authentik capitalisation

* Updated to match suggestions

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <chwshka@outlook.com>

* Updated to include <kbd> and <em> tags

* fixed codeblock

* Added explanatory text and removed extra EM tags

* fixed prettier issue

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

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dewi Roberts <chwshka@outlook.com>

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

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

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

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

---------

Signed-off-by: Dewi Roberts <chwshka@outlook.com>
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-03-20 08:52:49 -05:00
a2b82b6448 web: bump API Client version (#13585)
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-03-20 13:08:26 +00:00
0456ace646 core: bump goauthentik.io/api/v3 from 3.2025022.3 to 3.2025022.5 (#13594)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025022.3 to 3.2025022.5.
- [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.2025022.3...v3.2025022.5)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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-03-20 13:08:13 +00:00
d3a11ce810 website/docs: style guide & integration template: revamp (#12929)
* website/docs: style guide: revamp

* fix anchor

* Update style-guide.mdx

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

* Update style-guide.mdx

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

* Update style-guide.mdx

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

* Update website/docs/developer-docs/docs/style-guide.mdx

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

* Update website/docs/developer-docs/docs/style-guide.mdx

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

* Update website/docs/developer-docs/docs/style-guide.mdx

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

* Update website/docs/developer-docs/docs/style-guide.mdx

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

* Tana's suggested format 

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

* lint

* wip

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

* wip

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

* wip

lint

* Update website/docs/developer-docs/docs/style-guide.mdx

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

* tana

* fix

---------

Signed-off-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-03-20 07:47:00 -05:00
bfd1445c69 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#13592)
Translate django.po in zh-Hans

100% translated source file: 'django.po'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-03-20 07:58:17 +00:00
c2b3e9b05c translate: Updates for file web/xliff/en.xlf in fr (#13597)
Translate web/xliff/en.xlf in fr

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-03-20 07:57:31 +00:00
2c7d841e4a translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13596)
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-03-20 07:55:47 +00:00
c5d13c4a15 translate: Updates for file web/xliff/en.xlf in zh-Hans (#13593)
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-03-20 08:40:22 +01:00
079ef6e114 translate: Updates for file web/xliff/en.xlf in zh_CN (#13591)
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-03-20 08:40:02 +01:00
98bfca0b4d translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13590)
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-03-20 08:40:00 +01:00
a247bd5b9f core, web: update translations (#13584)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-03-20 01:07:24 +00:00
27856ec301 brands: add option to set global default flow background (#13079)
* brands: add option to set global default flow background

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

* test

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-20 01:07:05 +00:00
e4a8c05d25 web/admin: fix diff showing previous false as "-" (#13580)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-19 23:06:37 +00:00
cb2e0c6d54 web: bump API Client version (#13581)
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-03-19 23:04:21 +00:00
f37e1ca642 brands: migrate custom CSS to brands (#13172)
* brands: migrate custom CSS to brands

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

* fix missing default

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

* fix tests

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

* simpler migration

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

* add css to brand form

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

* fix

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-19 22:52:38 +00:00
70b1f05a84 website/integrations: jellyfin: update OIDC plugin installation (#13544)
Updated OIDC plugin installation

Signed-off-by: Махно Артём Сергеевич <Netoen@users.noreply.github.com>
2025-03-19 20:49:26 +01:00
192ed8f494 root: fix uv lock file on macOS (#13578)
* root: fix uv lock on macOS

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

* re-add make run

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-19 20:38:27 +01:00
b69d77d270 core: bump goauthentik.io/api/v3 from 3.2025022.2 to 3.2025022.3 (#13576)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025022.2 to 3.2025022.3.
- [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.2025022.2...v3.2025022.3)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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-03-19 19:23:42 +00:00
35b6801ba0 core: bump astral-sh/uv from 0.6.6 to 0.6.8 (#13577)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.6 to 0.6.8.
- [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.6.6...0.6.8)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  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-03-19 19:23:19 +00:00
f9e6f57aad lifecycle/aws: bump aws-cdk from 2.1004.0 to 2.1005.0 in /lifecycle/aws (#13574)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1004.0 to 2.1005.0.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1005.0/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  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-03-19 16:46:35 +00:00
868261c883 root: replace poetry with uv (#13388) 2025-03-19 16:29:18 +00:00
b6442c233d web: Fix inline documentation rendering (#13379)
web: Fix issues surrounding markdown rendering.

- Fix issue where Mermaid diagrams do not render.
- Fix link colors in dark mode.
- Fix anchored links triggering router.
- Fix issue where links occasionally link to missing page.
2025-03-19 17:09:47 +01:00
74292e6c23 web: bump API Client version (#13572)
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-03-19 15:02:17 +00:00
3e2cf4fd30 core: bump msgraph-sdk from 1.24.0 to 1.25.0 (#13570)
Bumps [msgraph-sdk](https://github.com/microsoftgraph/msgraph-sdk-python) from 1.24.0 to 1.25.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.24.0...v1.25.0)

---
updated-dependencies:
- dependency-name: msgraph-sdk
  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-03-19 15:02:06 +00:00
05cbb4ce0c core: bump goauthentik.io/api/v3 from 3.2025022.1 to 3.2025022.2 (#13569)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025022.1 to 3.2025022.2.
- [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.2025022.1...v3.2025022.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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-03-19 15:01:54 +00:00
c93d85731c providers/saml: configurable AuthnContextClassRef (#13566)
* providers/saml: make AuthnContextClassRef configurable

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

* providers/saml: fix incorrect AuthInstant

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

* add tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-19 14:42:55 +00:00
d163afe87c website/integrations: Beszel (#12905)
* initial release

* Ready for PR

* never changed this?

Used these commands after fresh git pull:

make lint-fix && npx prettier --write ./website/integrations/services/beszel/index.mdx && make website


Signed-off-by: NiceDevil <17103076+nicedevil007@users.noreply.github.com>

* reference to PocketBase

As @4d62 suggestet, here is the much simpler version as it uses 1:1 settings from PocketBase

* index.mdx aktualisieren

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: NiceDevil <17103076+nicedevil007@users.noreply.github.com>

* index.mdx aktualisieren

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: NiceDevil <17103076+nicedevil007@users.noreply.github.com>

* index.mdx aktualisieren

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: NiceDevil <17103076+nicedevil007@users.noreply.github.com>

* add full instructions

* add Beszel config

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

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

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

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

* correct redirect URI

Signed-off-by: NiceDevil <17103076+nicedevil007@users.noreply.github.com>

---------

Signed-off-by: NiceDevil <17103076+nicedevil007@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: nicedevil007 <nicedevil007@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
2025-03-18 17:34:28 -05:00
eac2c9a12b website/docs: Apple Business Manager Integration. (#13319)
website/docs: Flesh out Apple Business Manager integration.

- Fix missing required attribute.
- Adjust visible headers in table of contents.
- Fix Docusaurus warning for nested paragraphs.
2025-03-18 19:56:34 +00:00
c10e4a9063 website: package.json: copy over schema for npm run watch (#13543)
* root: Makefile: copy over schema for website-watch

`make website-watch` will fail with the following error if the schema.yml file is not present in the website's static directory. This was tested on a branch up to date with main with the schema file I copied over removed.
```
➜  authentik git:(sdko/integrations-all/migr-to-wizard) ✗ w
cd website && npm run watch

> @goauthentik/website-docs@0.0.0 watch
> docusaurus gen-api-docs all && docusaurus start

(node:102678) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
Loading of api failed for "/home/d/Code/authentik/website/static/schema.yml"

[ERROR] [Error: ENOENT: no such file or directory, lstat '/home/d/Code/authentik/website/static/schema.yml'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'lstat',
  path: '/home/d/Code/authentik/website/static/schema.yml'
}
[INFO] Docusaurus version: 3.7.0
Node version: v23.6.1
make: *** [Makefile:233: website-watch] Error 1
```

We should copy over the schema each time in case it changes. Adding it to this Makefile instruction as [official docs](https://docs.goauthentik.io/docs/developer-docs/setup/website-dev-environment) tell users to run `make website-install` which simply `npm ci`s, then this...

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

* tabs?

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

* Update Makefile

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

* Update package.json

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

* Update package.json

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

---------

Signed-off-by: Dominic R <dominic@sdko.org>
2025-03-18 16:02:52 +00:00
4e4adcc672 web: bump API Client version (#13565)
* web: bump API Client version

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix migration

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

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-03-18 14:48:55 +00:00
bb20576d84 providers/scim: save attributes returned from remote system like google workspace and entra ID (#13459)
providers/scim: save attributes returned from remote system like google workspace and entra

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-18 13:35:56 +00:00
5f315bddbd scripts: postgres: print statements (#13537)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-03-18 13:34:39 +00:00
9e0404646b core: bump goauthentik.io/api/v3 from 3.2025021.4 to 3.2025022.1 (#13556)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025021.4 to 3.2025022.1.
- [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.2025021.4...v3.2025022.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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-03-18 13:34:20 +00:00
45883ff86b core: bump sentry-sdk from 2.22.0 to 2.23.1 (#13557)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.22.0 to 2.23.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.22.0...2.23.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  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-03-18 13:34:13 +00:00
915f5689c6 website: bump the build group in /website with 6 updates (#13558)
Bumps the build group in /website with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@swc/core-darwin-arm64](https://github.com/swc-project/swc) | `1.11.9` | `1.11.11` |
| [@swc/core-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.11.9` | `1.11.11` |
| [@swc/core-linux-x64-gnu](https://github.com/swc-project/swc) | `1.11.9` | `1.11.11` |
| [@swc/html-darwin-arm64](https://github.com/swc-project/swc) | `1.11.9` | `1.11.11` |
| [@swc/html-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.11.9` | `1.11.11` |
| [@swc/html-linux-x64-gnu](https://github.com/swc-project/swc) | `1.11.9` | `1.11.11` |


Updates `@swc/core-darwin-arm64` from 1.11.9 to 1.11.11
- [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.11.9...v1.11.11)

Updates `@swc/core-linux-arm64-gnu` from 1.11.9 to 1.11.11
- [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.11.9...v1.11.11)

Updates `@swc/core-linux-x64-gnu` from 1.11.9 to 1.11.11
- [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.11.9...v1.11.11)

Updates `@swc/html-darwin-arm64` from 1.11.9 to 1.11.11
- [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.11.9...v1.11.11)

Updates `@swc/html-linux-arm64-gnu` from 1.11.9 to 1.11.11
- [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.11.9...v1.11.11)

Updates `@swc/html-linux-x64-gnu` from 1.11.9 to 1.11.11
- [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.11.9...v1.11.11)

---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 13:33:39 +00:00
ce1ea926f8 web: bump API Client version (#13555)
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-03-17 21:27:43 +00:00
2e3624ea82 release: 2025.2.2 (#13554) 2025-03-17 22:10:22 +01:00
4e52fb7e52 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#13541)
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-03-17 20:06:27 +00:00
7e36fb2153 website: Bump the build group in /website with 3 updates (#13549)
Bumps the build group in /website with 3 updates: [lightningcss-darwin-arm64](https://github.com/parcel-bundler/lightningcss), [lightningcss-linux-arm64-gnu](https://github.com/parcel-bundler/lightningcss) and [lightningcss-linux-x64-gnu](https://github.com/parcel-bundler/lightningcss).


Updates `lightningcss-darwin-arm64` from 1.29.2 to 1.29.3
- [Release notes](https://github.com/parcel-bundler/lightningcss/releases)
- [Commits](https://github.com/parcel-bundler/lightningcss/compare/v1.29.2...v1.29.3)

Updates `lightningcss-linux-arm64-gnu` from 1.29.2 to 1.29.3
- [Release notes](https://github.com/parcel-bundler/lightningcss/releases)
- [Commits](https://github.com/parcel-bundler/lightningcss/compare/v1.29.2...v1.29.3)

Updates `lightningcss-linux-x64-gnu` from 1.29.2 to 1.29.3
- [Release notes](https://github.com/parcel-bundler/lightningcss/releases)
- [Commits](https://github.com/parcel-bundler/lightningcss/compare/v1.29.2...v1.29.3)

---
updated-dependencies:
- dependency-name: lightningcss-darwin-arm64
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: lightningcss-linux-arm64-gnu
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: lightningcss-linux-x64-gnu
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 20:05:43 +00:00
2b00754324 website/docs: prepare for 2025.2.2 (#13552) 2025-03-17 18:53:39 +01:00
12a73ef306 core: Bump aws-cdk-lib from 2.184.0 to 2.184.1 (#13547)
Bumps [aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.184.0 to 2.184.1.
- [Release notes](https://github.com/aws/aws-cdk/releases)
- [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md)
- [Commits](https://github.com/aws/aws-cdk/compare/v2.184.0...v2.184.1)

---
updated-dependencies:
- dependency-name: aws-cdk-lib
  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-03-17 18:51:58 +01:00
4469db9b23 core: Bump coverage from 7.6.12 to 7.7.0 (#13548)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.12 to 7.7.0.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.6.12...7.7.0)

---
updated-dependencies:
- dependency-name: coverage
  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-03-17 18:50:48 +01:00
b7beac6795 stages/identification: check captcha after checking authentication (#13533) 2025-03-17 17:10:00 +00:00
580 changed files with 51343 additions and 12656 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2025.2.1
current_version = 2025.2.4
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*))?
@ -17,6 +17,8 @@ optional_value = final
[bumpversion:file:pyproject.toml]
[bumpversion:file:uv.lock]
[bumpversion:file:package.json]
[bumpversion:file:docker-compose.yml]

22
.github/ISSUE_TEMPLATE/docs_issue.md vendored Normal file
View File

@ -0,0 +1,22 @@
---
name: Documentation issue
about: Suggest an improvement or report a problem
title: ""
labels: documentation
assignees: ""
---
**Do you see an area that can be clarified or expanded, a technical inaccuracy, or a broken link? Please describe.**
A clear and concise description of what the problem is, or where the document can be improved. Ex. I believe we need more details about [...]
**Provide the URL or link to the exact page in the documentation to which you are referring.**
If there are multiple pages, list them all, and be sure to state the header or section where the content is.
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Additional context**
Add any other context or screenshots about the documentation issue here.
**Consider opening a PR!**
If the issue is one that you can fix, or even make a good pass at, we'd appreciate a PR. For more information about making a contribution to the docs, and using our Style Guide and our templates, refer to ["Writing documentation"](https://docs.goauthentik.io/docs/developer-docs/docs/writing-documentation).

View File

@ -44,7 +44,6 @@ if is_release:
]
if not prerelease:
image_tags += [
f"{name}:latest",
f"{name}:{version_family}",
]
else:

View File

@ -9,17 +9,22 @@ inputs:
runs:
using: "composite"
steps:
- name: Install poetry & deps
- name: Install apt deps
shell: bash
run: |
pipx install poetry || true
sudo apt-get update
sudo apt-get install --no-install-recommends -y libpq-dev openssl libxmlsec1-dev pkg-config gettext libkrb5-dev krb5-kdc krb5-user krb5-admin-server
- name: Setup python and restore poetry
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- name: Setup python
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
cache: "poetry"
- name: Install Python deps
shell: bash
run: uv sync --all-extras --dev --frozen
- name: Setup node
uses: actions/setup-node@v4
with:
@ -39,10 +44,9 @@ runs:
run: |
export PSQL_TAG=${{ inputs.postgresql_version }}
docker compose -f .github/actions/setup/docker-compose.yml up -d
poetry sync
cd web && npm ci
- name: Generate config
shell: poetry run python {0}
shell: uv run python {0}
run: |
from authentik.lib.generators import generate_id
from yaml import safe_dump

View File

@ -98,7 +98,7 @@ updates:
prefix: "lifecycle/aws:"
labels:
- dependencies
- package-ecosystem: pip
- package-ecosystem: uv
directory: "/"
schedule:
interval: daily

View File

@ -30,7 +30,6 @@ jobs:
uses: actions/setup-python@v5
with:
python-version-file: "pyproject.toml"
cache: "poetry"
- name: Generate API Client
run: make gen-client-py
- name: Publish package

View File

@ -33,7 +33,7 @@ jobs:
npm ci
- name: Check changes have been applied
run: |
poetry run make aws-cfn
uv run make aws-cfn
git diff --exit-code
ci-aws-cfn-mark:
if: always()

View File

@ -34,7 +34,7 @@ jobs:
- name: Setup authentik env
uses: ./.github/actions/setup
- name: run job
run: poetry run make ci-${{ matrix.job }}
run: uv run make ci-${{ matrix.job }}
test-migrations:
runs-on: ubuntu-latest
steps:
@ -42,7 +42,7 @@ jobs:
- name: Setup authentik env
uses: ./.github/actions/setup
- name: run migrations
run: poetry run python -m lifecycle.migrate
run: uv run python -m lifecycle.migrate
test-make-seed:
runs-on: ubuntu-latest
steps:
@ -69,19 +69,21 @@ jobs:
fetch-depth: 0
- name: checkout stable
run: |
# Delete all poetry envs
rm -rf /home/runner/.cache/pypoetry
# Copy current, latest config to local
# Temporarly comment the .github backup while migrating to uv
cp authentik/lib/default.yml local.env.yml
cp -R .github ..
# cp -R .github ..
cp -R scripts ..
git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1)
rm -rf .github/ scripts/
mv ../.github ../scripts .
# rm -rf .github/ scripts/
# mv ../.github ../scripts .
rm -rf scripts/
mv ../scripts .
- name: Setup authentik env (stable)
uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
continue-on-error: true
- name: run migrations to stable
run: poetry run python -m lifecycle.migrate
- name: checkout current code
@ -91,15 +93,13 @@ jobs:
git reset --hard HEAD
git clean -d -fx .
git checkout $GITHUB_SHA
# Delete previous poetry env
rm -rf /home/runner/.cache/pypoetry/virtualenvs/*
- name: Setup authentik env (ensure latest deps are installed)
uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
- name: migrate to latest
run: |
poetry run python -m lifecycle.migrate
uv run python -m lifecycle.migrate
- name: run tests
env:
# Test in the main database that we just migrated from the previous stable version
@ -108,7 +108,7 @@ jobs:
CI_RUN_ID: ${{ matrix.run_id }}
CI_TOTAL_RUNS: "5"
run: |
poetry run make ci-test
uv run make ci-test
test-unittest:
name: test-unittest - PostgreSQL ${{ matrix.psql }} - Run ${{ matrix.run_id }}/5
runs-on: ubuntu-latest
@ -133,7 +133,7 @@ jobs:
CI_RUN_ID: ${{ matrix.run_id }}
CI_TOTAL_RUNS: "5"
run: |
poetry run make ci-test
uv run make ci-test
- if: ${{ always() }}
uses: codecov/codecov-action@v5
with:
@ -156,8 +156,8 @@ jobs:
uses: helm/kind-action@v1.12.0
- name: run integration
run: |
poetry run coverage run manage.py test tests/integration
poetry run coverage xml
uv run coverage run manage.py test tests/integration
uv run coverage xml
- if: ${{ always() }}
uses: codecov/codecov-action@v5
with:
@ -214,8 +214,8 @@ jobs:
npm run build
- name: run e2e
run: |
poetry run coverage run manage.py test ${{ matrix.job.glob }}
poetry run coverage xml
uv run coverage run manage.py test ${{ matrix.job.glob }}
uv run coverage xml
- if: ${{ always() }}
uses: codecov/codecov-action@v5
with:

View File

@ -29,7 +29,7 @@ jobs:
- name: Generate API
run: make gen-client-go
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
uses: golangci/golangci-lint-action@v7
with:
version: latest
args: --timeout 5000s --verbose

View File

@ -2,7 +2,7 @@ name: authentik-gen-update-webauthn-mds
on:
workflow_dispatch:
schedule:
- cron: '30 1 1,15 * *'
- cron: "30 1 1,15 * *"
env:
POSTGRES_DB: authentik
@ -24,7 +24,7 @@ jobs:
token: ${{ steps.generate_token.outputs.token }}
- name: Setup authentik env
uses: ./.github/actions/setup
- run: poetry run ak update_webauthn_mds
- run: uv run ak update_webauthn_mds
- uses: peter-evans/create-pull-request@v7
id: cpr
with:

View File

@ -0,0 +1,45 @@
name: authentik-packages-npm-publish
on:
push:
branches: [main]
paths:
- packages/docusaurus-config
- packages/eslint-config
- packages/prettier-config
- packages/tsconfig
workflow_dispatch:
jobs:
publish:
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
package:
- docusaurus-config
- eslint-config
- prettier-config
- tsconfig
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: actions/setup-node@v4
with:
node-version-file: packages/${{ matrix.package }}/package.json
registry-url: "https://registry.npmjs.org"
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with:
files: |
packages/${{ matrix.package }}/package.json
- name: Publish package
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: packages/${{ matrix.package}}
run: |
npm ci
npm run build
npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

View File

@ -21,8 +21,8 @@ jobs:
uses: ./.github/actions/setup
- name: generate docs
run: |
poetry run make migrate
poetry run ak build_source_docs
uv run make migrate
uv run ak build_source_docs
- name: Publish
uses: netlify/actions/cli@master
with:

27
.github/workflows/semgrep.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: authentik-semgrep
on:
workflow_dispatch: {}
pull_request: {}
push:
branches:
- main
- master
paths:
- .github/workflows/semgrep.yml
schedule:
# random HH:MM to avoid a load spike on GitHub Actions at 00:00
- cron: '12 15 * * *'
jobs:
semgrep:
name: semgrep/ci
runs-on: ubuntu-latest
permissions:
contents: read
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
container:
image: semgrep/semgrep
if: (github.actor != 'dependabot[bot]')
steps:
- uses: actions/checkout@v4
- run: semgrep ci

View File

@ -36,10 +36,10 @@ jobs:
run: make gen-client-ts
- name: run extract
run: |
poetry run make i18n-extract
uv run make i18n-extract
- name: run compile
run: |
poetry run ak compilemessages
uv run ak compilemessages
make web-check-compile
- name: Create Pull Request
if: ${{ github.event_name != 'pull_request' }}

5
.gitignore vendored
View File

@ -11,6 +11,10 @@ local_settings.py
db.sqlite3
media
# Node
node_modules
# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
# in your Git repository. Update and uncomment the following line accordingly.
# <django-project-name>/staticfiles/
@ -33,6 +37,7 @@ eggs/
lib64/
parts/
dist/
out/
sdist/
var/
wheels/

47
.prettierignore Normal file
View File

@ -0,0 +1,47 @@
# Prettier Ignorefile
## Static Files
**/LICENSE
authentik/stages/**/*
## Build asset directories
coverage
dist
out
.docusaurus
website/docs/developer-docs/api/**/*
## Environment
*.env
## Secrets
*.secrets
## Yarn
.yarn/**/*
## Node
node_modules
coverage
## Configs
*.log
*.yaml
*.yml
# Templates
# TODO: Rename affected files to *.template.* or similar.
*.html
*.mdx
*.md
## Import order matters
poly.ts
src/locale-codes.ts
src/locales/
# Storybook
storybook-static/
.storybook/css-import-maps*

46
.vscode/tasks.json vendored
View File

@ -3,8 +3,13 @@
"tasks": [
{
"label": "authentik/core: make",
"command": "poetry",
"args": ["run", "make", "lint-fix", "lint"],
"command": "uv",
"args": [
"run",
"make",
"lint-fix",
"lint"
],
"presentation": {
"panel": "new"
},
@ -12,8 +17,12 @@
},
{
"label": "authentik/core: run",
"command": "poetry",
"args": ["run", "ak", "server"],
"command": "uv",
"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",
@ -60,8 +80,12 @@
},
{
"label": "authentik/api: generate",
"command": "poetry",
"args": ["run", "make", "gen"],
"command": "uv",
"args": [
"run",
"make",
"gen"
],
"group": "build"
}
]

View File

@ -10,7 +10,7 @@ schemas/ @goauthentik/backend
scripts/ @goauthentik/backend
tests/ @goauthentik/backend
pyproject.toml @goauthentik/backend
poetry.lock @goauthentik/backend
uv.lock @goauthentik/backend
go.mod @goauthentik/backend
go.sum @goauthentik/backend
# Infrastructure
@ -23,6 +23,8 @@ docker-compose.yml @goauthentik/infrastructure
Makefile @goauthentik/infrastructure
.editorconfig @goauthentik/infrastructure
CODEOWNERS @goauthentik/infrastructure
# Web packages
packages/ @goauthentik/frontend
# Web
web/ @goauthentik/frontend
tests/wdio/ @goauthentik/frontend

View File

@ -3,8 +3,7 @@
# Stage 1: Build website
FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS website-builder
ENV NODE_ENV=production \
GIT_UNAVAILABLE=true
ENV NODE_ENV=production
WORKDIR /work/website
@ -44,7 +43,7 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build
# Stage 3: Build go proxy
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-bookworm AS go-builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
ARG TARGETOS
ARG TARGETARCH
@ -77,7 +76,7 @@ COPY ./go.sum /go/src/goauthentik.io/go.sum
RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
--mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/authentik ./cmd/server
# Stage 4: MaxMind GeoIP
@ -94,53 +93,59 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
mkdir -p /usr/share/GeoIP && \
/bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 5: Python dependencies
FROM ghcr.io/goauthentik/fips-python:3.12.8-slim-bookworm-fips AS python-deps
# Stage 5: Download uv
FROM ghcr.io/astral-sh/uv:0.6.14 AS uv
# Stage 6: Base python image
FROM ghcr.io/goauthentik/fips-python:3.12.10-slim-bookworm-fips AS python-base
ENV VENV_PATH="/ak-root/.venv" \
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \
UV_NATIVE_TLS=1 \
UV_PYTHON_DOWNLOADS=0
WORKDIR /ak-root/
COPY --from=uv /uv /uvx /bin/
# Stage 7: Python dependencies
FROM python-base AS python-deps
ARG TARGETARCH
ARG TARGETVARIANT
WORKDIR /ak-root/poetry
ENV VENV_PATH="/ak-root/venv" \
POETRY_VIRTUALENVS_CREATE=false \
PATH="/ak-root/venv/bin:$PATH"
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
ENV PATH="/root/.cargo/bin:$PATH"
RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \
apt-get update && \
# Required for installing pip packages
apt-get install -y --no-install-recommends build-essential pkg-config libpq-dev libkrb5-dev
RUN --mount=type=bind,target=./pyproject.toml,src=./pyproject.toml \
--mount=type=bind,target=./poetry.lock,src=./poetry.lock \
--mount=type=cache,target=/root/.cache/pip \
--mount=type=cache,target=/root/.cache/pypoetry \
pip install --no-cache cffi && \
apt-get update && \
apt-get install -y --no-install-recommends \
build-essential libffi-dev \
# Required for cryptography
curl pkg-config \
# Required for lxml
libxslt-dev zlib1g-dev \
# Required for xmlsec
libltdl-dev \
# Required for kadmin
sccache clang && \
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
. "$HOME/.cargo/env" && \
python -m venv /ak-root/venv/ && \
bash -c "source ${VENV_PATH}/bin/activate && \
pip3 install --upgrade pip poetry && \
poetry config --local installer.no-binary cryptography,xmlsec,lxml,python-kadmin-rs && \
poetry install --only=main --no-ansi --no-interaction --no-root && \
pip uninstall cryptography -y && \
poetry install --only=main --no-ansi --no-interaction --no-root"
# Build essentials
build-essential pkg-config libffi-dev git \
# cryptography
curl \
# libxml
libxslt-dev zlib1g-dev \
# postgresql
libpq-dev \
# python-kadmin-rs
clang libkrb5-dev sccache \
# xmlsec
libltdl-dev && \
curl https://sh.rustup.rs -sSf | sh -s -- -y
# Stage 6: Run
FROM ghcr.io/goauthentik/fips-python:3.12.8-slim-bookworm-fips AS final-image
ENV UV_NO_BINARY_PACKAGE="cryptography lxml python-kadmin-rs xmlsec"
RUN --mount=type=bind,target=pyproject.toml,src=pyproject.toml \
--mount=type=bind,target=uv.lock,src=uv.lock \
--mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-dev
# Stage 8: Run
FROM python-base AS final-image
ARG VERSION
ARG GIT_BUILD_HASH
@ -172,7 +177,7 @@ RUN apt-get update && \
COPY ./authentik/ /authentik
COPY ./pyproject.toml /
COPY ./poetry.lock /
COPY ./uv.lock /
COPY ./schemas /schemas
COPY ./locale /locale
COPY ./tests /tests
@ -181,7 +186,7 @@ COPY ./blueprints /blueprints
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=python-deps /ak-root/.venv /ak-root/.venv
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/
@ -192,9 +197,6 @@ USER 1000
ENV TMPDIR=/dev/shm/ \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/ak-root/venv/bin:/lifecycle:$PATH" \
VENV_PATH="/ak-root/venv" \
POETRY_VIRTUALENVS_CREATE=false \
GOFIPS=1
HEALTHCHECK --interval=30s --timeout=30s --start-period=60s --retries=3 CMD [ "ak", "healthcheck" ]

View File

@ -12,9 +12,9 @@ GEN_API_TS = "gen-ts-api"
GEN_API_PY = "gen-py-api"
GEN_API_GO = "gen-go-api"
pg_user := $(shell poetry run python -m authentik.lib.config postgresql.user 2>/dev/null)
pg_host := $(shell poetry run python -m authentik.lib.config postgresql.host 2>/dev/null)
pg_name := $(shell poetry run python -m authentik.lib.config postgresql.name 2>/dev/null)
pg_user := $(shell uv run python -m authentik.lib.config postgresql.user 2>/dev/null)
pg_host := $(shell uv run python -m authentik.lib.config postgresql.host 2>/dev/null)
pg_name := $(shell uv run python -m authentik.lib.config postgresql.name 2>/dev/null)
all: lint-fix lint test gen web ## Lint, build, and test everything
@ -32,34 +32,37 @@ go-test:
go test -timeout 0 -v -race -cover ./...
test: ## Run the server tests and produce a coverage report (locally)
poetry run coverage run manage.py test --keepdb authentik
poetry run coverage html
poetry run coverage report
uv run coverage run manage.py test --keepdb authentik
uv run coverage html
uv run coverage report
lint-fix: lint-codespell ## Lint and automatically fix errors in the python source code. Reports spelling errors.
poetry run black $(PY_SOURCES)
poetry run ruff check --fix $(PY_SOURCES)
uv run black $(PY_SOURCES)
uv run ruff check --fix $(PY_SOURCES)
lint-codespell: ## Reports spelling errors.
poetry run codespell -w
uv run codespell -w
lint: ## Lint the python and golang sources
poetry run bandit -c pyproject.toml -r $(PY_SOURCES)
uv run bandit -c pyproject.toml -r $(PY_SOURCES)
golangci-lint run -v
core-install:
poetry install
uv sync --frozen
migrate: ## Run the Authentik Django server's migrations
poetry run python -m lifecycle.migrate
uv run python -m lifecycle.migrate
i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service
aws-cfn:
cd lifecycle/aws && npm run aws-cfn
run: ## Run the main authentik server process
uv run ak server
core-i18n-extract:
poetry run ak makemessages \
uv run ak makemessages \
--add-location file \
--no-obsolete \
--ignore web \
@ -90,11 +93,11 @@ gen-build: ## Extract the schema from the database
AUTHENTIK_DEBUG=true \
AUTHENTIK_TENANTS__ENABLED=true \
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
poetry run ak make_blueprint_schema > blueprints/schema.json
uv run ak make_blueprint_schema > blueprints/schema.json
AUTHENTIK_DEBUG=true \
AUTHENTIK_TENANTS__ENABLED=true \
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
poetry run ak spectacular --file schema.yml
uv run ak spectacular --file schema.yml
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md
@ -173,7 +176,7 @@ gen-client-go: gen-clean-go ## Build and install the authentik API for Golang
rm -rf ./${GEN_API_GO}/config.yaml ./${GEN_API_GO}/templates/
gen-dev-config: ## Generate a local development config file
poetry run scripts/generate_config.py
uv run scripts/generate_config.py
gen: gen-build gen-client-ts
@ -254,21 +257,21 @@ ci--meta-debug:
node --version
ci-black: ci--meta-debug
poetry run black --check $(PY_SOURCES)
uv run black --check $(PY_SOURCES)
ci-ruff: ci--meta-debug
poetry run ruff check $(PY_SOURCES)
uv run ruff check $(PY_SOURCES)
ci-codespell: ci--meta-debug
poetry run codespell -s
uv run codespell -s
ci-bandit: ci--meta-debug
poetry run bandit -r $(PY_SOURCES)
uv run bandit -r $(PY_SOURCES)
ci-pending-migrations: ci--meta-debug
poetry run ak makemigrations --check
uv run ak makemigrations --check
ci-test: ci--meta-debug
poetry run coverage run manage.py test --keepdb --randomly-seed ${CI_TEST_SEED} authentik
poetry run coverage report
poetry run coverage xml
uv run coverage run manage.py test --keepdb --randomly-seed ${CI_TEST_SEED} authentik
uv run coverage report
uv run coverage xml

View File

@ -2,7 +2,7 @@
from os import environ
__version__ = "2025.2.1"
__version__ = "2025.2.4"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -59,7 +59,7 @@ class SystemInfoSerializer(PassiveSerializer):
if not isinstance(value, str):
continue
actual_value = value
if raw_session in actual_value:
if raw_session is not None and raw_session in actual_value:
actual_value = actual_value.replace(
raw_session, SafeExceptionReporterFilter.cleansed_substitute
)

View File

@ -36,6 +36,7 @@ from authentik.core.models import (
GroupSourceConnection,
PropertyMapping,
Provider,
Session,
Source,
User,
UserSourceConnection,
@ -108,6 +109,7 @@ def excluded_models() -> list[type[Model]]:
Policy,
PolicyBindingModel,
# Classes that have other dependencies
Session,
AuthenticatedSession,
# Classes which are only internally managed
# FIXME: these shouldn't need to be explicitly listed, but rather based off of a mixin

View File

@ -49,6 +49,8 @@ class BrandSerializer(ModelSerializer):
"branding_title",
"branding_logo",
"branding_favicon",
"branding_custom_css",
"branding_default_flow_background",
"flow_authentication",
"flow_invalidation",
"flow_recovery",
@ -86,6 +88,7 @@ class CurrentBrandSerializer(PassiveSerializer):
branding_title = CharField()
branding_logo = CharField(source="branding_logo_url")
branding_favicon = CharField(source="branding_favicon_url")
branding_custom_css = CharField()
ui_footer_links = ListField(
child=FooterLinkSerializer(),
read_only=True,
@ -125,6 +128,7 @@ class BrandViewSet(UsedByMixin, ModelViewSet):
"branding_title",
"branding_logo",
"branding_favicon",
"branding_default_flow_background",
"flow_authentication",
"flow_invalidation",
"flow_recovery",

View File

@ -0,0 +1,35 @@
# Generated by Django 5.0.12 on 2025-02-22 01:51
from pathlib import Path
from django.db import migrations, models
from django.apps.registry import Apps
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def migrate_custom_css(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
Brand = apps.get_model("authentik_brands", "brand")
db_alias = schema_editor.connection.alias
path = Path("/web/dist/custom.css")
if not path.exists():
return
css = path.read_text()
Brand.objects.using(db_alias).update(branding_custom_css=css)
class Migration(migrations.Migration):
dependencies = [
("authentik_brands", "0007_brand_default_application"),
]
operations = [
migrations.AddField(
model_name="brand",
name="branding_custom_css",
field=models.TextField(blank=True, default=""),
),
migrations.RunPython(migrate_custom_css),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.13 on 2025-03-19 22:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_brands", "0008_brand_branding_custom_css"),
]
operations = [
migrations.AddField(
model_name="brand",
name="branding_default_flow_background",
field=models.TextField(default="/static/dist/assets/images/flow_background.jpg"),
),
]

View File

@ -33,6 +33,10 @@ class Brand(SerializerModel):
branding_logo = models.TextField(default="/static/dist/assets/icons/icon_left_brand.svg")
branding_favicon = models.TextField(default="/static/dist/assets/icons/icon.png")
branding_custom_css = models.TextField(default="", blank=True)
branding_default_flow_background = models.TextField(
default="/static/dist/assets/images/flow_background.jpg"
)
flow_authentication = models.ForeignKey(
Flow, null=True, on_delete=models.SET_NULL, related_name="brand_authentication"
@ -84,6 +88,12 @@ class Brand(SerializerModel):
return CONFIG.get("web.path", "/")[:-1] + self.branding_favicon
return self.branding_favicon
def branding_default_flow_background_url(self) -> str:
"""Get branding_default_flow_background with the correct prefix"""
if self.branding_default_flow_background.startswith("/static"):
return CONFIG.get("web.path", "/")[:-1] + self.branding_default_flow_background
return self.branding_default_flow_background
@property
def serializer(self) -> Serializer:
from authentik.brands.api import BrandSerializer

View File

@ -24,6 +24,7 @@ class TestBrands(APITestCase):
"branding_logo": "/static/dist/assets/icons/icon_left_brand.svg",
"branding_favicon": "/static/dist/assets/icons/icon.png",
"branding_title": "authentik",
"branding_custom_css": "",
"matched_domain": brand.domain,
"ui_footer_links": [],
"ui_theme": Themes.AUTOMATIC,
@ -43,6 +44,7 @@ class TestBrands(APITestCase):
"branding_logo": "/static/dist/assets/icons/icon_left_brand.svg",
"branding_favicon": "/static/dist/assets/icons/icon.png",
"branding_title": "custom",
"branding_custom_css": "",
"matched_domain": "bar.baz",
"ui_footer_links": [],
"ui_theme": Themes.AUTOMATIC,
@ -59,6 +61,7 @@ class TestBrands(APITestCase):
"branding_logo": "/static/dist/assets/icons/icon_left_brand.svg",
"branding_favicon": "/static/dist/assets/icons/icon.png",
"branding_title": "authentik",
"branding_custom_css": "",
"matched_domain": "fallback",
"ui_footer_links": [],
"ui_theme": Themes.AUTOMATIC,
@ -121,3 +124,27 @@ class TestBrands(APITestCase):
"subject": None,
},
)
def test_branding_url(self):
"""Test branding attributes return correct values"""
brand = create_test_brand()
brand.branding_default_flow_background = "https://goauthentik.io/img/icon.png"
brand.branding_favicon = "https://goauthentik.io/img/icon.png"
brand.branding_logo = "https://goauthentik.io/img/icon.png"
brand.save()
self.assertEqual(
brand.branding_default_flow_background_url(), "https://goauthentik.io/img/icon.png"
)
self.assertJSONEqual(
self.client.get(reverse("authentik_api:brand-current")).content.decode(),
{
"branding_logo": "https://goauthentik.io/img/icon.png",
"branding_favicon": "https://goauthentik.io/img/icon.png",
"branding_title": "authentik",
"branding_custom_css": "",
"matched_domain": brand.domain,
"ui_footer_links": [],
"ui_theme": Themes.AUTOMATIC,
"default_locale": "",
},
)

View File

@ -46,7 +46,7 @@ LOGGER = get_logger()
def user_app_cache_key(user_pk: str, page_number: int | None = None) -> str:
"""Cache key where application list for user is saved"""
key = f"{CACHE_PREFIX}/app_access/{user_pk}"
key = f"{CACHE_PREFIX}app_access/{user_pk}"
if page_number:
key += f"/{page_number}"
return key

View File

@ -5,6 +5,7 @@ from typing import TypedDict
from rest_framework import mixins
from rest_framework.fields import SerializerMethodField
from rest_framework.request import Request
from rest_framework.serializers import CharField, DateTimeField, IPAddressField
from rest_framework.viewsets import GenericViewSet
from ua_parser import user_agent_parser
@ -54,6 +55,11 @@ class UserAgentDict(TypedDict):
class AuthenticatedSessionSerializer(ModelSerializer):
"""AuthenticatedSession Serializer"""
expires = DateTimeField(source="session.expires", read_only=True)
last_ip = IPAddressField(source="session.last_ip", read_only=True)
last_user_agent = CharField(source="session.last_user_agent", read_only=True)
last_used = DateTimeField(source="session.last_used", read_only=True)
current = SerializerMethodField()
user_agent = SerializerMethodField()
geo_ip = SerializerMethodField()
@ -62,19 +68,19 @@ class AuthenticatedSessionSerializer(ModelSerializer):
def get_current(self, instance: AuthenticatedSession) -> bool:
"""Check if session is currently active session"""
request: Request = self.context["request"]
return request._request.session.session_key == instance.session_key
return request._request.session.session_key == instance.session.session_key
def get_user_agent(self, instance: AuthenticatedSession) -> UserAgentDict:
"""Get parsed user agent"""
return user_agent_parser.Parse(instance.last_user_agent)
return user_agent_parser.Parse(instance.session.last_user_agent)
def get_geo_ip(self, instance: AuthenticatedSession) -> GeoIPDict | None: # pragma: no cover
"""Get GeoIP Data"""
return GEOIP_CONTEXT_PROCESSOR.city_dict(instance.last_ip)
return GEOIP_CONTEXT_PROCESSOR.city_dict(instance.session.last_ip)
def get_asn(self, instance: AuthenticatedSession) -> ASNDict | None: # pragma: no cover
"""Get ASN Data"""
return ASN_CONTEXT_PROCESSOR.asn_dict(instance.last_ip)
return ASN_CONTEXT_PROCESSOR.asn_dict(instance.session.last_ip)
class Meta:
model = AuthenticatedSession
@ -90,6 +96,7 @@ class AuthenticatedSessionSerializer(ModelSerializer):
"last_used",
"expires",
]
extra_args = {"uuid": {"read_only": True}}
class AuthenticatedSessionViewSet(
@ -101,9 +108,10 @@ class AuthenticatedSessionViewSet(
):
"""AuthenticatedSession Viewset"""
queryset = AuthenticatedSession.objects.all()
lookup_field = "uuid"
queryset = AuthenticatedSession.objects.select_related("session").all()
serializer_class = AuthenticatedSessionSerializer
search_fields = ["user__username", "last_ip", "last_user_agent"]
filterset_fields = ["user__username", "last_ip", "last_user_agent"]
search_fields = ["user__username", "session__last_ip", "session__last_user_agent"]
filterset_fields = ["user__username", "session__last_ip", "session__last_user_agent"]
ordering = ["user__username"]
owner_field = "user"

View File

@ -179,10 +179,13 @@ class UserSourceConnectionSerializer(SourceSerializer):
"user",
"source",
"source_obj",
"identifier",
"created",
"last_updated",
]
extra_kwargs = {
"created": {"read_only": True},
"last_updated": {"read_only": True},
}
@ -199,7 +202,7 @@ class UserSourceConnectionViewSet(
queryset = UserSourceConnection.objects.all()
serializer_class = UserSourceConnectionSerializer
filterset_fields = ["user", "source__slug"]
search_fields = ["source__slug"]
search_fields = ["user__username", "source__slug", "identifier"]
ordering = ["source__slug", "pk"]
owner_field = "user"
@ -218,9 +221,11 @@ class GroupSourceConnectionSerializer(SourceSerializer):
"source_obj",
"identifier",
"created",
"last_updated",
]
extra_kwargs = {
"created": {"read_only": True},
"last_updated": {"read_only": True},
}
@ -237,6 +242,5 @@ class GroupSourceConnectionViewSet(
queryset = GroupSourceConnection.objects.all()
serializer_class = GroupSourceConnectionSerializer
filterset_fields = ["group", "source__slug"]
search_fields = ["source__slug"]
search_fields = ["group__name", "source__slug", "identifier"]
ordering = ["source__slug", "pk"]
owner_field = "user"

View File

@ -6,8 +6,6 @@ from typing import Any
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.models import Permission
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core.cache import cache
from django.db.models.functions import ExtractHour
from django.db.transaction import atomic
from django.db.utils import IntegrityError
@ -71,8 +69,8 @@ from authentik.core.middleware import (
from authentik.core.models import (
USER_ATTRIBUTE_TOKEN_EXPIRING,
USER_PATH_SERVICE_ACCOUNT,
AuthenticatedSession,
Group,
Session,
Token,
TokenIntents,
User,
@ -226,6 +224,7 @@ class UserSerializer(ModelSerializer):
"name",
"is_active",
"last_login",
"date_joined",
"is_superuser",
"groups",
"groups_obj",
@ -240,6 +239,7 @@ class UserSerializer(ModelSerializer):
]
extra_kwargs = {
"name": {"allow_blank": True},
"date_joined": {"read_only": True},
"password_change_date": {"read_only": True},
}
@ -373,7 +373,7 @@ class UsersFilter(FilterSet):
method="filter_attributes",
)
is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser")
is_superuser = BooleanFilter(field_name="ak_groups", method="filter_is_superuser")
uuid = UUIDFilter(field_name="uuid")
path = CharFilter(field_name="path")
@ -391,6 +391,11 @@ class UsersFilter(FilterSet):
queryset=Group.objects.all().order_by("name"),
)
def filter_is_superuser(self, queryset, name, value):
if value:
return queryset.filter(ak_groups__is_superuser=True).distinct()
return queryset.exclude(ak_groups__is_superuser=True).distinct()
def filter_attributes(self, queryset, name, value):
"""Filter attributes by query args"""
try:
@ -767,9 +772,6 @@ class UserViewSet(UsedByMixin, ModelViewSet):
response = super().partial_update(request, *args, **kwargs)
instance: User = self.get_object()
if not instance.is_active:
sessions = AuthenticatedSession.objects.filter(user=instance)
session_ids = sessions.values_list("session_key", flat=True)
cache.delete_many(f"{KEY_PREFIX}{session}" for session in session_ids)
sessions.delete()
Session.objects.filter(authenticatedsession__user=instance).delete()
LOGGER.debug("Deleted user's sessions", user=instance.username)
return response

View File

@ -24,6 +24,15 @@ class InbuiltBackend(ModelBackend):
self.set_method("password", request)
return user
async def aauthenticate(
self, request: HttpRequest, username: str | None, password: str | None, **kwargs: Any
) -> User | None:
user = await super().aauthenticate(request, username=username, password=password, **kwargs)
if not user:
return None
self.set_method("password", request)
return user
def set_method(self, method: str, request: HttpRequest | None, **kwargs):
"""Set method data on current flow, if possbiel"""
if not request:

View File

@ -0,0 +1,15 @@
"""Change user type"""
from importlib import import_module
from django.conf import settings
from authentik.tenants.management import TenantCommand
class Command(TenantCommand):
"""Delete all sessions"""
def handle_per_tenant(self, **options):
engine = import_module(settings.SESSION_ENGINE)
engine.SessionStore.clear_expired()

View File

@ -2,9 +2,14 @@
from collections.abc import Callable
from contextvars import ContextVar
from functools import partial
from uuid import uuid4
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpRequest, HttpResponse
from django.utils.deprecation import MiddlewareMixin
from django.utils.functional import SimpleLazyObject
from django.utils.translation import override
from sentry_sdk.api import set_tag
from structlog.contextvars import STRUCTLOG_KEY_PREFIX
@ -20,6 +25,40 @@ CTX_HOST = ContextVar[str | None](STRUCTLOG_KEY_PREFIX + "host", default=None)
CTX_AUTH_VIA = ContextVar[str | None](STRUCTLOG_KEY_PREFIX + KEY_AUTH_VIA, default=None)
def get_user(request):
if not hasattr(request, "_cached_user"):
user = None
if (authenticated_session := request.session.get("authenticatedsession", None)) is not None:
user = authenticated_session.user
request._cached_user = user or AnonymousUser()
return request._cached_user
async def aget_user(request):
if not hasattr(request, "_cached_user"):
user = None
if (
authenticated_session := await request.session.aget("authenticatedsession", None)
) is not None:
user = authenticated_session.user
request._cached_user = user or AnonymousUser()
return request._cached_user
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
if not hasattr(request, "session"):
raise ImproperlyConfigured(
"The Django authentication middleware requires session "
"middleware to be installed. Edit your MIDDLEWARE setting to "
"insert "
"'authentik.root.middleware.SessionMiddleware' before "
"'authentik.core.middleware.AuthenticationMiddleware'."
)
request.user = SimpleLazyObject(lambda: get_user(request))
request.auser = partial(aget_user, request)
class ImpersonateMiddleware:
"""Middleware to impersonate users"""

View File

@ -0,0 +1,19 @@
# Generated by Django 5.0.13 on 2025-04-07 14:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0043_alter_group_options"),
]
operations = [
migrations.AddField(
model_name="usersourceconnection",
name="new_identifier",
field=models.TextField(default=""),
preserve_default=False,
),
]

View File

@ -0,0 +1,30 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0044_usersourceconnection_new_identifier"),
("authentik_sources_kerberos", "0003_migrate_userkerberossourceconnection_identifier"),
("authentik_sources_oauth", "0009_migrate_useroauthsourceconnection_identifier"),
("authentik_sources_plex", "0005_migrate_userplexsourceconnection_identifier"),
("authentik_sources_saml", "0019_migrate_usersamlsourceconnection_identifier"),
]
operations = [
migrations.RenameField(
model_name="usersourceconnection",
old_name="new_identifier",
new_name="identifier",
),
migrations.AddIndex(
model_name="usersourceconnection",
index=models.Index(fields=["identifier"], name="authentik_c_identif_59226f_idx"),
),
migrations.AddIndex(
model_name="usersourceconnection",
index=models.Index(
fields=["source", "identifier"], name="authentik_c_source__649e04_idx"
),
),
]

View File

@ -0,0 +1,238 @@
# Generated by Django 5.0.11 on 2025-01-27 12:58
import uuid
import pickle # nosec
from django.core import signing
from django.contrib.auth import BACKEND_SESSION_KEY, HASH_SESSION_KEY, SESSION_KEY
from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.utils.timezone import now, timedelta
from authentik.lib.migrations import progress_bar
from authentik.root.middleware import ClientIPMiddleware
SESSION_CACHE_ALIAS = "default"
class PickleSerializer:
"""
Simple wrapper around pickle to be used in signing.dumps()/loads() and
cache backends.
"""
def __init__(self, protocol=None):
self.protocol = pickle.HIGHEST_PROTOCOL if protocol is None else protocol
def dumps(self, obj):
"""Pickle data to be stored in redis"""
return pickle.dumps(obj, self.protocol)
def loads(self, data):
"""Unpickle data to be loaded from redis"""
return pickle.loads(data) # nosec
def _migrate_session(
apps,
db_alias,
session_key,
session_data,
expires,
):
Session = apps.get_model("authentik_core", "Session")
OldAuthenticatedSession = apps.get_model("authentik_core", "OldAuthenticatedSession")
AuthenticatedSession = apps.get_model("authentik_core", "AuthenticatedSession")
old_auth_session = (
OldAuthenticatedSession.objects.using(db_alias).filter(session_key=session_key).first()
)
args = {
"session_key": session_key,
"expires": expires,
"last_ip": ClientIPMiddleware.default_ip,
"last_user_agent": "",
"session_data": {},
}
for k, v in session_data.items():
if k == "authentik/stages/user_login/last_ip":
args["last_ip"] = v
elif k in ["last_user_agent", "last_used"]:
args[k] = v
elif args in [SESSION_KEY, BACKEND_SESSION_KEY, HASH_SESSION_KEY]:
pass
else:
args["session_data"][k] = v
if old_auth_session:
args["last_user_agent"] = old_auth_session.last_user_agent
args["last_used"] = old_auth_session.last_used
args["session_data"] = pickle.dumps(args["session_data"])
session = Session.objects.using(db_alias).create(**args)
if old_auth_session:
AuthenticatedSession.objects.using(db_alias).create(
session=session,
user=old_auth_session.user,
)
def migrate_redis_sessions(apps, schema_editor):
from django.core.cache import caches
db_alias = schema_editor.connection.alias
cache = caches[SESSION_CACHE_ALIAS]
# Not a redis cache, skipping
if not hasattr(cache, "keys"):
return
print("\nMigrating Redis sessions to database, this might take a couple of minutes...")
for key, session_data in progress_bar(cache.get_many(cache.keys(f"{KEY_PREFIX}*")).items()):
_migrate_session(
apps=apps,
db_alias=db_alias,
session_key=key.removeprefix(KEY_PREFIX),
session_data=session_data,
expires=now() + timedelta(seconds=cache.ttl(key)),
)
def migrate_database_sessions(apps, schema_editor):
DjangoSession = apps.get_model("sessions", "Session")
db_alias = schema_editor.connection.alias
print("\nMigration database sessions, this might take a couple of minutes...")
for django_session in progress_bar(DjangoSession.objects.using(db_alias).all()):
session_data = signing.loads(
django_session.session_data,
salt="django.contrib.sessions.SessionStore",
serializer=PickleSerializer,
)
_migrate_session(
apps=apps,
db_alias=db_alias,
session_key=django_session.session_key,
session_data=session_data,
expires=django_session.expire_date,
)
class Migration(migrations.Migration):
dependencies = [
("sessions", "0001_initial"),
("authentik_core", "0045_rename_new_identifier_usersourceconnection_identifier_and_more"),
("authentik_providers_oauth2", "0027_accesstoken_authentik_p_expires_9f24a5_idx_and_more"),
("authentik_providers_rac", "0006_connectiontoken_authentik_p_expires_91f148_idx_and_more"),
]
operations = [
# Rename AuthenticatedSession to OldAuthenticatedSession
migrations.RenameModel(
old_name="AuthenticatedSession",
new_name="OldAuthenticatedSession",
),
migrations.RenameIndex(
model_name="oldauthenticatedsession",
new_name="authentik_c_expires_cf4f72_idx",
old_name="authentik_c_expires_08251d_idx",
),
migrations.RenameIndex(
model_name="oldauthenticatedsession",
new_name="authentik_c_expirin_c1f17f_idx",
old_name="authentik_c_expirin_9cd839_idx",
),
migrations.RenameIndex(
model_name="oldauthenticatedsession",
new_name="authentik_c_expirin_e04f5d_idx",
old_name="authentik_c_expirin_195a84_idx",
),
migrations.RenameIndex(
model_name="oldauthenticatedsession",
new_name="authentik_c_session_a44819_idx",
old_name="authentik_c_session_d0f005_idx",
),
migrations.RunSQL(
sql="ALTER INDEX authentik_core_authenticatedsession_user_id_5055b6cf RENAME TO authentik_core_oldauthenticatedsession_user_id_5055b6cf",
reverse_sql="ALTER INDEX authentik_core_oldauthenticatedsession_user_id_5055b6cf RENAME TO authentik_core_authenticatedsession_user_id_5055b6cf",
),
# Create new Session and AuthenticatedSession models
migrations.CreateModel(
name="Session",
fields=[
(
"session_key",
models.CharField(
max_length=40, primary_key=True, serialize=False, verbose_name="session key"
),
),
("expires", models.DateTimeField(default=None, null=True)),
("expiring", models.BooleanField(default=True)),
("session_data", models.BinaryField(verbose_name="session data")),
("last_ip", models.GenericIPAddressField()),
("last_user_agent", models.TextField(blank=True)),
("last_used", models.DateTimeField(auto_now=True)),
],
options={
"default_permissions": [],
"verbose_name": "Session",
"verbose_name_plural": "Sessions",
},
),
migrations.AddIndex(
model_name="session",
index=models.Index(fields=["expires"], name="authentik_c_expires_d2f607_idx"),
),
migrations.AddIndex(
model_name="session",
index=models.Index(fields=["expiring"], name="authentik_c_expirin_7c2cfb_idx"),
),
migrations.AddIndex(
model_name="session",
index=models.Index(
fields=["expiring", "expires"], name="authentik_c_expirin_1ab2e4_idx"
),
),
migrations.AddIndex(
model_name="session",
index=models.Index(
fields=["expires", "session_key"], name="authentik_c_expires_c49143_idx"
),
),
migrations.CreateModel(
name="AuthenticatedSession",
fields=[
(
"session",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
serialize=False,
to="authentik_core.session",
),
),
("uuid", models.UUIDField(default=uuid.uuid4, unique=True)),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
options={
"verbose_name": "Authenticated Session",
"verbose_name_plural": "Authenticated Sessions",
},
),
migrations.RunPython(
code=migrate_redis_sessions,
reverse_code=migrations.RunPython.noop,
),
migrations.RunPython(
code=migrate_database_sessions,
reverse_code=migrations.RunPython.noop,
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.11 on 2025-01-27 13:02
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0046_session_and_more"),
("authentik_providers_rac", "0007_migrate_session"),
("authentik_providers_oauth2", "0028_migrate_session"),
]
operations = [
migrations.DeleteModel(
name="OldAuthenticatedSession",
),
]

View File

@ -1,6 +1,7 @@
"""authentik core models"""
from datetime import datetime
from enum import StrEnum
from hashlib import sha256
from typing import Any, Optional, Self
from uuid import uuid4
@ -9,6 +10,7 @@ from deepmerge import always_merger
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import UserManager as DjangoUserManager
from django.contrib.sessions.base_session import AbstractBaseSession
from django.db import models
from django.db.models import Q, QuerySet, options
from django.db.models.constants import LOOKUP_SEP
@ -646,19 +648,30 @@ class SourceUserMatchingModes(models.TextChoices):
"""Different modes a source can handle new/returning users"""
IDENTIFIER = "identifier", _("Use the source-specific identifier")
EMAIL_LINK = "email_link", _(
"Link to a user with identical email address. Can have security implications "
"when a source doesn't validate email addresses."
EMAIL_LINK = (
"email_link",
_(
"Link to a user with identical email address. Can have security implications "
"when a source doesn't validate email addresses."
),
)
EMAIL_DENY = "email_deny", _(
"Use the user's email address, but deny enrollment when the email address already exists."
EMAIL_DENY = (
"email_deny",
_(
"Use the user's email address, but deny enrollment when the email address already "
"exists."
),
)
USERNAME_LINK = "username_link", _(
"Link to a user with identical username. Can have security implications "
"when a username is used with another source."
USERNAME_LINK = (
"username_link",
_(
"Link to a user with identical username. Can have security implications "
"when a username is used with another source."
),
)
USERNAME_DENY = "username_deny", _(
"Use the user's username, but deny enrollment when the username already exists."
USERNAME_DENY = (
"username_deny",
_("Use the user's username, but deny enrollment when the username already exists."),
)
@ -666,12 +679,16 @@ class SourceGroupMatchingModes(models.TextChoices):
"""Different modes a source can handle new/returning groups"""
IDENTIFIER = "identifier", _("Use the source-specific identifier")
NAME_LINK = "name_link", _(
"Link to a group with identical name. Can have security implications "
"when a group name is used with another source."
NAME_LINK = (
"name_link",
_(
"Link to a group with identical name. Can have security implications "
"when a group name is used with another source."
),
)
NAME_DENY = "name_deny", _(
"Use the group name, but deny enrollment when the name already exists."
NAME_DENY = (
"name_deny",
_("Use the group name, but deny enrollment when the name already exists."),
)
@ -730,8 +747,7 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
choices=SourceGroupMatchingModes.choices,
default=SourceGroupMatchingModes.IDENTIFIER,
help_text=_(
"How the source determines if an existing group should be used or "
"a new group created."
"How the source determines if an existing group should be used or a new group created."
),
)
@ -761,11 +777,17 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
@property
def component(self) -> str:
"""Return component used to edit this object"""
if self.managed == self.MANAGED_INBUILT:
return ""
raise NotImplementedError
@property
def property_mapping_type(self) -> "type[PropertyMapping]":
"""Return property mapping type used by this object"""
if self.managed == self.MANAGED_INBUILT:
from authentik.core.models import PropertyMapping
return PropertyMapping
raise NotImplementedError
def ui_login_button(self, request: HttpRequest) -> UILoginButton | None:
@ -780,10 +802,14 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
def get_base_user_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
"""Get base properties for a user to build final properties upon."""
if self.managed == self.MANAGED_INBUILT:
return {}
raise NotImplementedError
def get_base_group_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
"""Get base properties for a group to build final properties upon."""
if self.managed == self.MANAGED_INBUILT:
return {}
raise NotImplementedError
def __str__(self):
@ -814,6 +840,7 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
user = models.ForeignKey(User, on_delete=models.CASCADE)
source = models.ForeignKey(Source, on_delete=models.CASCADE)
identifier = models.TextField()
objects = InheritanceManager()
@ -827,6 +854,10 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
class Meta:
unique_together = (("user", "source"),)
indexes = (
models.Index(fields=("identifier",)),
models.Index(fields=("source", "identifier")),
)
class GroupSourceConnection(SerializerModel, CreatedUpdatedModel):
@ -997,45 +1028,75 @@ class PropertyMapping(SerializerModel, ManagedModel):
verbose_name_plural = _("Property Mappings")
class AuthenticatedSession(ExpiringModel):
"""Additional session class for authenticated users. Augments the standard django session
to achieve the following:
- Make it queryable by user
- Have a direct connection to user objects
- Allow users to view their own sessions and terminate them
- Save structured and well-defined information.
"""
class Session(ExpiringModel, AbstractBaseSession):
"""User session with extra fields for fast access"""
uuid = models.UUIDField(default=uuid4, primary_key=True)
# Remove upstream field because we're using our own ExpiringModel
expire_date = None
session_data = models.BinaryField(_("session data"))
session_key = models.CharField(max_length=40)
user = models.ForeignKey(User, on_delete=models.CASCADE)
last_ip = models.TextField()
# Keep in sync with Session.Keys
last_ip = models.GenericIPAddressField()
last_user_agent = models.TextField(blank=True)
last_used = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = _("Session")
verbose_name_plural = _("Sessions")
indexes = ExpiringModel.Meta.indexes + [
models.Index(fields=["expires", "session_key"]),
]
default_permissions = []
def __str__(self):
return self.session_key
class Keys(StrEnum):
"""
Keys to be set with the session interface for the fields above to be updated.
If a field is added here that needs to be initialized when the session is initialized,
it must also be reflected in authentik.root.middleware.SessionMiddleware.process_request
and in authentik.core.sessions.SessionStore.__init__
"""
LAST_IP = "last_ip"
LAST_USER_AGENT = "last_user_agent"
LAST_USED = "last_used"
@classmethod
def get_session_store_class(cls):
from authentik.core.sessions import SessionStore
return SessionStore
def get_decoded(self):
raise NotImplementedError
class AuthenticatedSession(SerializerModel):
session = models.OneToOneField(Session, on_delete=models.CASCADE, primary_key=True)
# We use the session as primary key, but we need the API to be able to reference
# this object uniquely without exposing the session key
uuid = models.UUIDField(default=uuid4, unique=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
verbose_name = _("Authenticated Session")
verbose_name_plural = _("Authenticated Sessions")
indexes = ExpiringModel.Meta.indexes + [
models.Index(fields=["session_key"]),
]
def __str__(self) -> str:
return f"Authenticated Session {self.session_key[:10]}"
return f"Authenticated Session {str(self.pk)[:10]}"
@staticmethod
def from_request(request: HttpRequest, user: User) -> Optional["AuthenticatedSession"]:
"""Create a new session from a http request"""
from authentik.root.middleware import ClientIPMiddleware
if not hasattr(request, "session") or not request.session.session_key:
if not hasattr(request, "session") or not request.session.exists(
request.session.session_key
):
return None
return AuthenticatedSession(
session_key=request.session.session_key,
session=Session.objects.filter(session_key=request.session.session_key).first(),
user=user,
last_ip=ClientIPMiddleware.get_client_ip(request),
last_user_agent=request.META.get("HTTP_USER_AGENT", ""),
expires=request.session.get_expiry_date(),
)

168
authentik/core/sessions.py Normal file
View File

@ -0,0 +1,168 @@
"""authentik sessions engine"""
import pickle # nosec
from django.contrib.auth import BACKEND_SESSION_KEY, HASH_SESSION_KEY, SESSION_KEY
from django.contrib.sessions.backends.db import SessionStore as SessionBase
from django.core.exceptions import SuspiciousOperation
from django.utils import timezone
from django.utils.functional import cached_property
from structlog.stdlib import get_logger
from authentik.root.middleware import ClientIPMiddleware
LOGGER = get_logger()
class SessionStore(SessionBase):
def __init__(self, session_key=None, last_ip=None, last_user_agent=""):
super().__init__(session_key)
self._create_kwargs = {
"last_ip": last_ip or ClientIPMiddleware.default_ip,
"last_user_agent": last_user_agent,
}
@classmethod
def get_model_class(cls):
from authentik.core.models import Session
return Session
@cached_property
def model_fields(self):
return [k.value for k in self.model.Keys]
def _get_session_from_db(self):
try:
return (
self.model.objects.select_related(
"authenticatedsession",
"authenticatedsession__user",
)
.prefetch_related(
"authenticatedsession__user__groups",
"authenticatedsession__user__user_permissions",
)
.get(
session_key=self.session_key,
expires__gt=timezone.now(),
)
)
except (self.model.DoesNotExist, SuspiciousOperation) as exc:
if isinstance(exc, SuspiciousOperation):
LOGGER.warning(str(exc))
self._session_key = None
async def _aget_session_from_db(self):
try:
return (
await self.model.objects.select_related(
"authenticatedsession",
"authenticatedsession__user",
)
.prefetch_related(
"authenticatedsession__user__groups",
"authenticatedsession__user__user_permissions",
)
.aget(
session_key=self.session_key,
expires__gt=timezone.now(),
)
)
except (self.model.DoesNotExist, SuspiciousOperation) as exc:
if isinstance(exc, SuspiciousOperation):
LOGGER.warning(str(exc))
self._session_key = None
def encode(self, session_dict):
return pickle.dumps(session_dict, protocol=pickle.HIGHEST_PROTOCOL)
def decode(self, session_data):
try:
return pickle.loads(session_data) # nosec
except pickle.PickleError:
# ValueError, unpickling exceptions. If any of these happen, just return an empty
# dictionary (an empty session)
pass
return {}
def load(self):
s = self._get_session_from_db()
if s:
return {
"authenticatedsession": getattr(s, "authenticatedsession", None),
**{k: getattr(s, k) for k in self.model_fields},
**self.decode(s.session_data),
}
else:
return {}
async def aload(self):
s = await self._aget_session_from_db()
if s:
return {
"authenticatedsession": getattr(s, "authenticatedsession", None),
**{k: getattr(s, k) for k in self.model_fields},
**self.decode(s.session_data),
}
else:
return {}
def create_model_instance(self, data):
args = {
"session_key": self._get_or_create_session_key(),
"expires": self.get_expiry_date(),
"session_data": {},
**self._create_kwargs,
}
for k, v in data.items():
# Don't save:
# - unused auth data
# - related models
if k in [SESSION_KEY, BACKEND_SESSION_KEY, HASH_SESSION_KEY, "authenticatedsession"]:
pass
elif k in self.model_fields:
args[k] = v
else:
args["session_data"][k] = v
args["session_data"] = self.encode(args["session_data"])
return self.model(**args)
async def acreate_model_instance(self, data):
args = {
"session_key": await self._aget_or_create_session_key(),
"expires": await self.aget_expiry_date(),
"session_data": {},
**self._create_kwargs,
}
for k, v in data.items():
# Don't save:
# - unused auth data
# - related models
if k in [SESSION_KEY, BACKEND_SESSION_KEY, HASH_SESSION_KEY, "authenticatedsession"]:
pass
elif k in self.model_fields:
args[k] = v
else:
args["session_data"][k] = v
args["session_data"] = self.encode(args["session_data"])
return self.model(**args)
@classmethod
def clear_expired(cls):
cls.get_model_class().objects.filter(expires__lt=timezone.now()).delete()
@classmethod
async def aclear_expired(cls):
await cls.get_model_class().objects.filter(expires__lt=timezone.now()).adelete()
def cycle_key(self):
data = self._session
key = self.session_key
self.create()
self._session_cache = data
if key:
self.delete(key)
if (authenticated_session := data.get("authenticatedsession")) is not None:
authenticated_session.session_id = self.session_key
authenticated_session.save(force_insert=True)

View File

@ -1,11 +1,10 @@
"""authentik core signals"""
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.contrib.auth.signals import user_logged_in
from django.core.cache import cache
from django.core.signals import Signal
from django.db.models import Model
from django.db.models.signals import post_save, pre_delete, pre_save
from django.db.models.signals import post_delete, post_save, pre_save
from django.dispatch import receiver
from django.http.request import HttpRequest
from structlog.stdlib import get_logger
@ -15,6 +14,7 @@ from authentik.core.models import (
AuthenticatedSession,
BackchannelProvider,
ExpiringModel,
Session,
User,
default_token_duration,
)
@ -49,19 +49,10 @@ def user_logged_in_session(sender, request: HttpRequest, user: User, **_):
session.save()
@receiver(user_logged_out)
def user_logged_out_session(sender, request: HttpRequest, user: User, **_):
"""Delete AuthenticatedSession if it exists"""
if not request.session or not request.session.session_key:
return
AuthenticatedSession.objects.filter(session_key=request.session.session_key).delete()
@receiver(pre_delete, sender=AuthenticatedSession)
@receiver(post_delete, sender=AuthenticatedSession)
def authenticated_session_delete(sender: type[Model], instance: "AuthenticatedSession", **_):
"""Delete session when authenticated session is deleted"""
cache_key = f"{KEY_PREFIX}{instance.session_key}"
cache.delete(cache_key)
Session.objects.filter(session_key=instance.pk).delete()
@receiver(pre_save)

View File

@ -48,6 +48,7 @@ LOGGER = get_logger()
PLAN_CONTEXT_SOURCE_GROUPS = "source_groups"
SESSION_KEY_SOURCE_FLOW_STAGES = "authentik/flows/source_flow_stages"
SESSION_KEY_SOURCE_FLOW_CONTEXT = "authentik/flows/source_flow_context"
SESSION_KEY_OVERRIDE_FLOW_TOKEN = "authentik/flows/source_override_flow_token" # nosec
@ -261,6 +262,7 @@ class SourceFlowManager:
plan.append_stage(stage)
for stage in self.request.session.get(SESSION_KEY_SOURCE_FLOW_STAGES, []):
plan.append_stage(stage)
plan.context.update(self.request.session.get(SESSION_KEY_SOURCE_FLOW_CONTEXT, {}))
return plan.to_redirect(self.request, flow)
def handle_auth(

View File

@ -2,22 +2,16 @@
from datetime import datetime, timedelta
from django.conf import ImproperlyConfigured
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.contrib.sessions.backends.db import SessionStore as DBSessionStore
from django.core.cache import cache
from django.utils.timezone import now
from structlog.stdlib import get_logger
from authentik.core.models import (
USER_ATTRIBUTE_EXPIRES,
USER_ATTRIBUTE_GENERATED,
AuthenticatedSession,
ExpiringModel,
User,
)
from authentik.events.system_tasks import SystemTask, TaskStatus, prefill_task
from authentik.lib.config import CONFIG
from authentik.root.celery import CELERY_APP
LOGGER = get_logger()
@ -38,40 +32,6 @@ def clean_expired_models(self: SystemTask):
obj.expire_action()
LOGGER.debug("Expired models", model=cls, amount=amount)
messages.append(f"Expired {amount} {cls._meta.verbose_name_plural}")
# Special case
amount = 0
for session in AuthenticatedSession.objects.all():
match CONFIG.get("session_storage", "cache"):
case "cache":
cache_key = f"{KEY_PREFIX}{session.session_key}"
value = None
try:
value = cache.get(cache_key)
except Exception as exc:
LOGGER.debug("Failed to get session from cache", exc=exc)
if not value:
session.delete()
amount += 1
case "db":
if not (
DBSessionStore.get_model_class()
.objects.filter(session_key=session.session_key, expire_date__gt=now())
.exists()
):
session.delete()
amount += 1
case _:
# Should never happen, as we check for other values in authentik/root/settings.py
raise ImproperlyConfigured(
"Invalid session_storage setting, allowed values are db and cache"
)
if CONFIG.get("session_storage", "cache") == "db":
DBSessionStore.clear_expired()
LOGGER.debug("Expired sessions", model=AuthenticatedSession, amount=amount)
messages.append(f"Expired {amount} {AuthenticatedSession._meta.verbose_name_plural}")
self.set_status(TaskStatus.SUCCESSFUL, *messages)

View File

@ -16,7 +16,7 @@
{% block head_before %}
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
<style>{{ brand.branding_custom_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

@ -4,7 +4,7 @@
{% load i18n %}
{% block head_before %}
<link rel="prefetch" href="{% static 'dist/assets/images/flow_background.jpg' %}" />
<link rel="prefetch" href="{{ request.brand.branding_default_flow_background_url }}" />
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/theme-dark.css' %}" media="(prefers-color-scheme: dark)">
{% include "base/header_js.html" %}
@ -13,7 +13,7 @@
{% block head %}
<style>
:root {
--ak-flow-background: url("{% static 'dist/assets/images/flow_background.jpg' %}");
--ak-flow-background: url("{{ request.brand.branding_default_flow_background_url }}");
--pf-c-background-image--BackgroundImage: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage-2x: var(--ak-flow-background);
--pf-c-background-image--BackgroundImage--sm: var(--ak-flow-background);

View File

@ -5,7 +5,7 @@ from json import loads
from django.urls.base import reverse
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.core.models import AuthenticatedSession, Session, User
from authentik.core.tests.utils import create_test_admin_user
@ -30,3 +30,18 @@ class TestAuthenticatedSessionsAPI(APITestCase):
self.assertEqual(response.status_code, 200)
body = loads(response.content.decode())
self.assertEqual(body["pagination"]["count"], 1)
def test_delete(self):
"""Test deletion"""
self.client.force_login(self.user)
self.assertEqual(AuthenticatedSession.objects.all().count(), 1)
self.assertEqual(Session.objects.all().count(), 1)
response = self.client.delete(
reverse(
"authentik_api:authenticatedsession-detail",
kwargs={"uuid": AuthenticatedSession.objects.first().uuid},
)
)
self.assertEqual(response.status_code, 204)
self.assertEqual(AuthenticatedSession.objects.all().count(), 0)
self.assertEqual(Session.objects.all().count(), 0)

View File

@ -0,0 +1,19 @@
from django.apps import apps
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_admin_user
class TestSourceAPI(APITestCase):
def setUp(self) -> None:
self.user = create_test_admin_user()
self.client.force_login(self.user)
def test_builtin_source_used_by(self):
"""Test Providers's types endpoint"""
apps.get_app_config("authentik_core").source_inbuilt()
response = self.client.get(
reverse("authentik_api:source-used-by", kwargs={"slug": "authentik-built-in"}),
)
self.assertEqual(response.status_code, 200)

View File

@ -1,9 +1,8 @@
"""Test Users API"""
from datetime import datetime
from json import loads
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core.cache import cache
from django.urls.base import reverse
from rest_framework.test import APITestCase
@ -11,11 +10,17 @@ from authentik.brands.models import Brand
from authentik.core.models import (
USER_ATTRIBUTE_TOKEN_EXPIRING,
AuthenticatedSession,
Session,
Token,
User,
UserTypes,
)
from authentik.core.tests.utils import create_test_admin_user, create_test_brand, create_test_flow
from authentik.core.tests.utils import (
create_test_admin_user,
create_test_brand,
create_test_flow,
create_test_user,
)
from authentik.flows.models import FlowDesignation
from authentik.lib.generators import generate_id, generate_key
from authentik.stages.email.models import EmailStage
@ -26,7 +31,7 @@ class TestUsersAPI(APITestCase):
def setUp(self) -> None:
self.admin = create_test_admin_user()
self.user = User.objects.create(username="test-user")
self.user = create_test_user()
def test_filter_type(self):
"""Test API filtering by type"""
@ -41,6 +46,35 @@ class TestUsersAPI(APITestCase):
)
self.assertEqual(response.status_code, 200)
def test_filter_is_superuser(self):
"""Test API filtering by superuser status"""
User.objects.all().delete()
admin = create_test_admin_user()
self.client.force_login(admin)
# Test superuser
response = self.client.get(
reverse("authentik_api:user-list"),
data={
"is_superuser": True,
},
)
self.assertEqual(response.status_code, 200)
body = loads(response.content)
self.assertEqual(len(body["results"]), 1)
self.assertEqual(body["results"][0]["username"], admin.username)
# Test non-superuser
user = create_test_user()
response = self.client.get(
reverse("authentik_api:user-list"),
data={
"is_superuser": False,
},
)
self.assertEqual(response.status_code, 200)
body = loads(response.content)
self.assertEqual(len(body["results"]), 1, body)
self.assertEqual(body["results"][0]["username"], user.username)
def test_list_with_groups(self):
"""Test listing with groups"""
self.client.force_login(self.admin)
@ -99,6 +133,8 @@ class TestUsersAPI(APITestCase):
def test_recovery_email_no_flow(self):
"""Test user recovery link (no recovery flow set)"""
self.client.force_login(self.admin)
self.user.email = ""
self.user.save()
response = self.client.post(
reverse("authentik_api:user-recovery-email", kwargs={"pk": self.user.pk})
)
@ -344,12 +380,15 @@ class TestUsersAPI(APITestCase):
"""Ensure sessions are deleted when a user is deactivated"""
user = create_test_admin_user()
session_id = generate_id()
AuthenticatedSession.objects.create(
user=user,
session = Session.objects.create(
session_key=session_id,
last_ip="",
last_ip="255.255.255.255",
last_user_agent="",
)
AuthenticatedSession.objects.create(
session=session,
user=user,
)
cache.set(KEY_PREFIX + session_id, "foo")
self.client.force_login(self.admin)
response = self.client.patch(
@ -360,5 +399,7 @@ class TestUsersAPI(APITestCase):
)
self.assertEqual(response.status_code, 200)
self.assertIsNone(cache.get(KEY_PREFIX + session_id))
self.assertFalse(AuthenticatedSession.objects.filter(session_key=session_id).exists())
self.assertFalse(Session.objects.filter(session_key=session_id).exists())
self.assertFalse(
AuthenticatedSession.objects.filter(session__session_key=session_id).exists()
)

View File

@ -1,7 +1,5 @@
"""authentik URL Configuration"""
from channels.auth import AuthMiddleware
from channels.sessions import CookieMiddleware
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.urls import path
@ -13,7 +11,11 @@ from authentik.core.api.devices import AdminDeviceViewSet, DeviceViewSet
from authentik.core.api.groups import GroupViewSet
from authentik.core.api.property_mappings import PropertyMappingViewSet
from authentik.core.api.providers import ProviderViewSet
from authentik.core.api.sources import SourceViewSet, UserSourceConnectionViewSet
from authentik.core.api.sources import (
GroupSourceConnectionViewSet,
SourceViewSet,
UserSourceConnectionViewSet,
)
from authentik.core.api.tokens import TokenViewSet
from authentik.core.api.transactional_applications import TransactionalApplicationView
from authentik.core.api.users import UserViewSet
@ -25,7 +27,7 @@ from authentik.core.views.interface import (
RootRedirectView,
)
from authentik.flows.views.interface import FlowInterfaceView
from authentik.root.asgi_middleware import SessionMiddleware
from authentik.root.asgi_middleware import AuthMiddlewareStack
from authentik.root.messages.consumer import MessageConsumer
from authentik.root.middleware import ChannelsLoggingMiddleware
@ -81,6 +83,7 @@ api_urlpatterns = [
("core/tokens", TokenViewSet),
("sources/all", SourceViewSet),
("sources/user_connections/all", UserSourceConnectionViewSet),
("sources/group_connections/all", GroupSourceConnectionViewSet),
("providers/all", ProviderViewSet),
("propertymappings/all", PropertyMappingViewSet),
("authenticators/all", DeviceViewSet, "device"),
@ -94,9 +97,7 @@ api_urlpatterns = [
websocket_urlpatterns = [
path(
"ws/client/",
ChannelsLoggingMiddleware(
CookieMiddleware(SessionMiddleware(AuthMiddleware(MessageConsumer.as_asgi())))
),
ChannelsLoggingMiddleware(AuthMiddlewareStack(MessageConsumer.as_asgi())),
),
]

View File

@ -102,7 +102,7 @@ def ssf_user_session_delete_session_revoked(sender, instance: AuthenticatedSessi
"format": "complex",
"session": {
"format": "opaque",
"id": sha256(instance.session_key.encode("ascii")).hexdigest(),
"id": sha256(instance.session.session_key.encode("ascii")).hexdigest(),
},
"user": {
"format": "email",

View File

@ -11,13 +11,14 @@ from guardian.shortcuts import get_anonymous_user
from authentik.core.models import Source, User
from authentik.core.sources.flow_manager import (
SESSION_KEY_OVERRIDE_FLOW_TOKEN,
SESSION_KEY_SOURCE_FLOW_CONTEXT,
SESSION_KEY_SOURCE_FLOW_STAGES,
)
from authentik.core.types import UILoginButton
from authentik.enterprise.stages.source.models import SourceStage
from authentik.flows.challenge import Challenge, ChallengeResponse
from authentik.flows.models import FlowToken, in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED
from authentik.flows.planner import PLAN_CONTEXT_IS_REDIRECTED, PLAN_CONTEXT_IS_RESTORED
from authentik.flows.stage import ChallengeStageView, StageView
from authentik.lib.utils.time import timedelta_from_string
@ -53,6 +54,9 @@ class SourceStageView(ChallengeStageView):
resume_token = self.create_flow_token()
self.request.session[SESSION_KEY_OVERRIDE_FLOW_TOKEN] = resume_token
self.request.session[SESSION_KEY_SOURCE_FLOW_STAGES] = [in_memory_stage(SourceStageFinal)]
self.request.session[SESSION_KEY_SOURCE_FLOW_CONTEXT] = {
PLAN_CONTEXT_IS_REDIRECTED: self.executor.flow,
}
return self.login_button.challenge
def create_flow_token(self) -> FlowToken:

View File

@ -50,7 +50,8 @@ class NotificationTransportSerializer(ModelSerializer):
"mode",
"mode_verbose",
"webhook_url",
"webhook_mapping",
"webhook_mapping_body",
"webhook_mapping_headers",
"send_once",
]

View File

@ -0,0 +1,43 @@
# Generated by Django 5.0.13 on 2025-03-20 19:54
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_events", "0008_event_authentik_e_expires_8c73a8_idx_and_more"),
]
operations = [
migrations.RenameField(
model_name="notificationtransport",
old_name="webhook_mapping",
new_name="webhook_mapping_body",
),
migrations.AlterField(
model_name="notificationtransport",
name="webhook_mapping_body",
field=models.ForeignKey(
default=None,
help_text="Customize the body of the request. Mapping should return data that is JSON-serializable.",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
related_name="+",
to="authentik_events.notificationwebhookmapping",
),
),
migrations.AddField(
model_name="notificationtransport",
name="webhook_mapping_headers",
field=models.ForeignKey(
default=None,
help_text="Configure additional headers to be sent. Mapping should return a dictionary of key-value pairs",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
related_name="+",
to="authentik_events.notificationwebhookmapping",
),
),
]

View File

@ -336,8 +336,27 @@ class NotificationTransport(SerializerModel):
mode = models.TextField(choices=TransportMode.choices, default=TransportMode.LOCAL)
webhook_url = models.TextField(blank=True, validators=[DomainlessURLValidator()])
webhook_mapping = models.ForeignKey(
"NotificationWebhookMapping", on_delete=models.SET_DEFAULT, null=True, default=None
webhook_mapping_body = models.ForeignKey(
"NotificationWebhookMapping",
on_delete=models.SET_DEFAULT,
null=True,
default=None,
related_name="+",
help_text=_(
"Customize the body of the request. "
"Mapping should return data that is JSON-serializable."
),
)
webhook_mapping_headers = models.ForeignKey(
"NotificationWebhookMapping",
on_delete=models.SET_DEFAULT,
null=True,
default=None,
related_name="+",
help_text=_(
"Configure additional headers to be sent. "
"Mapping should return a dictionary of key-value pairs"
),
)
send_once = models.BooleanField(
default=False,
@ -360,8 +379,8 @@ class NotificationTransport(SerializerModel):
def send_local(self, notification: "Notification") -> list[str]:
"""Local notification delivery"""
if self.webhook_mapping:
self.webhook_mapping.evaluate(
if self.webhook_mapping_body:
self.webhook_mapping_body.evaluate(
user=notification.user,
request=None,
notification=notification,
@ -380,9 +399,18 @@ class NotificationTransport(SerializerModel):
if notification.event and notification.event.user:
default_body["event_user_email"] = notification.event.user.get("email", None)
default_body["event_user_username"] = notification.event.user.get("username", None)
if self.webhook_mapping:
headers = {}
if self.webhook_mapping_body:
default_body = sanitize_item(
self.webhook_mapping.evaluate(
self.webhook_mapping_body.evaluate(
user=notification.user,
request=None,
notification=notification,
)
)
if self.webhook_mapping_headers:
headers = sanitize_item(
self.webhook_mapping_headers.evaluate(
user=notification.user,
request=None,
notification=notification,
@ -392,6 +420,7 @@ class NotificationTransport(SerializerModel):
response = get_http_session().post(
self.webhook_url,
json=default_body,
headers=headers,
)
response.raise_for_status()
except RequestException as exc:

View File

@ -59,7 +59,7 @@ def get_login_event(request_or_session: HttpRequest | AuthenticatedSession | Non
session = request_or_session.session
if isinstance(request_or_session, AuthenticatedSession):
SessionStore = _session_engine.SessionStore
session = SessionStore(request_or_session.session_key)
session = SessionStore(request_or_session.session.session_key)
return session.get(SESSION_LOGIN_EVENT, None)

View File

@ -120,7 +120,7 @@ class TestEventsNotifications(APITestCase):
)
transport = NotificationTransport.objects.create(
name=generate_id(), webhook_mapping=mapping, mode=TransportMode.LOCAL
name=generate_id(), webhook_mapping_body=mapping, mode=TransportMode.LOCAL
)
NotificationRule.objects.filter(name__startswith="default").delete()
trigger = NotificationRule.objects.create(name=generate_id(), group=self.group)

View File

@ -60,20 +60,25 @@ class TestEventTransports(TestCase):
def test_transport_webhook_mapping(self):
"""Test webhook transport with custom mapping"""
mapping = NotificationWebhookMapping.objects.create(
mapping_body = NotificationWebhookMapping.objects.create(
name=generate_id(), expression="return request.user"
)
mapping_headers = NotificationWebhookMapping.objects.create(
name=generate_id(), expression="""return {"foo": "bar"}"""
)
transport: NotificationTransport = NotificationTransport.objects.create(
name=generate_id(),
mode=TransportMode.WEBHOOK,
webhook_url="http://localhost:1234/test",
webhook_mapping=mapping,
webhook_mapping_body=mapping_body,
webhook_mapping_headers=mapping_headers,
)
with Mocker() as mocker:
mocker.post("http://localhost:1234/test")
transport.send(self.notification)
self.assertEqual(mocker.call_count, 1)
self.assertEqual(mocker.request_history[0].method, "POST")
self.assertEqual(mocker.request_history[0].headers["foo"], "bar")
self.assertJSONEqual(
mocker.request_history[0].body.decode(),
{"email": self.user.email, "pk": self.user.pk, "username": self.user.username},

View File

@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
from uuid import uuid4
from django.db import models
from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _
from model_utils.managers import InheritanceManager
from rest_framework.serializers import BaseSerializer
@ -178,11 +179,12 @@ class Flow(SerializerModel, PolicyBindingModel):
help_text=_("Required level of authentication and authorization to access a flow."),
)
@property
def background_url(self) -> str:
def background_url(self, request: HttpRequest | None = None) -> str:
"""Get the URL to the background image. If the name is /static or starts with http
it is returned as-is"""
if not self.background:
if request:
return request.brand.branding_default_flow_background_url()
return (
CONFIG.get("web.path", "/")[:-1] + "/static/dist/assets/images/flow_background.jpg"
)

View File

@ -184,7 +184,7 @@ class ChallengeStageView(StageView):
flow_info = ContextualFlowInfo(
data={
"title": self.format_title(),
"background": self.executor.flow.background_url,
"background": self.executor.flow.background_url(self.request),
"cancel_url": reverse("authentik_flows:cancel"),
"layout": self.executor.flow.layout,
}

View File

@ -27,7 +27,6 @@ class FlowTestCase(APITestCase):
self.assertIsNotNone(raw_response["component"])
if flow:
self.assertIn("flow_info", raw_response)
self.assertEqual(raw_response["flow_info"]["background"], flow.background_url)
self.assertEqual(
raw_response["flow_info"]["cancel_url"], reverse("authentik_flows:cancel")
)

View File

@ -1,9 +1,11 @@
"""API flow tests"""
from json import loads
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_admin_user
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.flows.api.stages import StageSerializer, StageViewSet
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, Stage
from authentik.lib.generators import generate_id
@ -77,6 +79,22 @@ class TestFlowsAPI(APITestCase):
self.assertEqual(response.status_code, 200)
self.assertJSONEqual(response.content, {"diagram": DIAGRAM_EXPECTED})
def test_api_background(self):
"""Test custom background"""
user = create_test_admin_user()
self.client.force_login(user)
flow = create_test_flow()
response = self.client.get(reverse("authentik_api:flow-detail", kwargs={"slug": flow.slug}))
body = loads(response.content.decode())
self.assertEqual(body["background"], "/static/dist/assets/images/flow_background.jpg")
flow.background = "https://goauthentik.io/img/icon.png"
flow.save()
response = self.client.get(reverse("authentik_api:flow-detail", kwargs={"slug": flow.slug}))
body = loads(response.content.decode())
self.assertEqual(body["background"], "https://goauthentik.io/img/icon.png")
def test_api_diagram_no_stages(self):
"""Test flow diagram with no stages."""
user = create_test_admin_user()

View File

@ -49,7 +49,7 @@ class TestFlowInspector(APITestCase):
"captcha_stage": None,
"component": "ak-stage-identification",
"flow_info": {
"background": flow.background_url,
"background": "/static/dist/assets/images/flow_background.jpg",
"cancel_url": reverse("authentik_flows:cancel"),
"title": flow.title,
"layout": "stacked",

View File

@ -69,6 +69,7 @@ SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre"
SESSION_KEY_GET = "authentik/flows/get"
SESSION_KEY_POST = "authentik/flows/post"
SESSION_KEY_HISTORY = "authentik/flows/history"
SESSION_KEY_AUTH_STARTED = "authentik/flows/auth_started"
QS_KEY_TOKEN = "flow_token" # nosec
QS_QUERY = "query"
@ -453,6 +454,7 @@ class FlowExecutorView(APIView):
SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_PLAN,
SESSION_KEY_GET,
SESSION_KEY_AUTH_STARTED,
# We might need the initial POST payloads for later requests
# SESSION_KEY_POST,
# We don't delete the history on purpose, as a user might

View File

@ -6,14 +6,22 @@ from django.shortcuts import get_object_or_404
from ua_parser.user_agent_parser import Parse
from authentik.core.views.interface import InterfaceView
from authentik.flows.models import Flow
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.views.executor import SESSION_KEY_AUTH_STARTED
class FlowInterfaceView(InterfaceView):
"""Flow interface"""
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
kwargs["flow"] = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
kwargs["flow"] = flow
if (
not self.request.user.is_authenticated
and flow.designation == FlowDesignation.AUTHENTICATION
):
self.request.session[SESSION_KEY_AUTH_STARTED] = True
self.request.session.save()
kwargs["inspector"] = "inspector" in self.request.GET
return super().get_context_data(**kwargs)

View File

@ -1,5 +1,20 @@
# update website/docs/install-config/configuration/configuration.mdx
# This is the default configuration file
# authentik configuration
#
# https://docs.goauthentik.io/docs/install-config/configuration/
#
# To override the settings in this file, run the following command from the repository root:
#
# ```shell
# make gen-dev-config
# ```
#
# You may edit the generated file to override the configuration below.
#
# When making modifying the default configuration file,
# ensure that the corresponding documentation is updated to match.
#
# @see {@link ../../website/docs/install-config/configuration/configuration.mdx Configuration documentation} for more information.
postgresql:
host: localhost
name: authentik
@ -45,6 +60,8 @@ redis:
# url: ""
# transport_options: ""
http_timeout: 30
cache:
# url: ""
timeout: 300

View File

@ -18,7 +18,7 @@ from sentry_sdk import start_span
from sentry_sdk.tracing import Span
from structlog.stdlib import get_logger
from authentik.core.models import AuthenticatedSession, User
from authentik.core.models import User
from authentik.events.models import Event
from authentik.lib.expression.exceptions import ControlFlowException
from authentik.lib.utils.http import get_http_session
@ -203,9 +203,7 @@ class BaseEvaluator:
provider = OAuth2Provider.objects.get(name=provider)
session = None
if hasattr(request, "session") and request.session.session_key:
session = AuthenticatedSession.objects.filter(
session_key=request.session.session_key
).first()
session = request.session["authenticatedsession"]
access_token = AccessToken(
provider=provider,
user=user,

View File

@ -18,6 +18,15 @@ class SerializerModel(models.Model):
@property
def serializer(self) -> type[BaseSerializer]:
"""Get serializer for this model"""
# Special handling for built-in source
if (
hasattr(self, "managed")
and hasattr(self, "MANAGED_INBUILT")
and self.managed == self.MANAGED_INBUILT
):
from authentik.core.api.sources import SourceSerializer
return SourceSerializer
raise NotImplementedError

View File

@ -16,7 +16,40 @@ def authentik_user_agent() -> str:
return f"authentik@{get_full_version()}"
class DebugSession(Session):
class TimeoutSession(Session):
"""Always set a default HTTP request timeout"""
def __init__(self, default_timeout=None):
super().__init__()
self.timeout = default_timeout
def send(
self,
request,
*,
stream=...,
verify=...,
proxies=...,
cert=...,
timeout=...,
allow_redirects=...,
**kwargs,
):
if not timeout and self.timeout:
timeout = self.timeout
return super().send(
request,
stream=stream,
verify=verify,
proxies=proxies,
cert=cert,
timeout=timeout,
allow_redirects=allow_redirects,
**kwargs,
)
class DebugSession(TimeoutSession):
"""requests session which logs http requests and responses"""
def send(self, req: PreparedRequest, *args, **kwargs):
@ -42,8 +75,9 @@ class DebugSession(Session):
def get_http_session() -> Session:
"""Get a requests session with common headers"""
session = Session()
session = TimeoutSession()
if CONFIG.get_bool("debug") or CONFIG.get("log_level") == "trace":
session = DebugSession()
session.headers["User-Agent"] = authentik_user_agent()
session.timeout = CONFIG.get_optional_int("http_timeout")
return session

View File

@ -13,6 +13,7 @@ from paramiko.ssh_exception import SSHException
from structlog.stdlib import get_logger
from yaml import safe_dump
from authentik import __version__
from authentik.outposts.apps import MANAGED_OUTPOST
from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException
from authentik.outposts.docker_ssh import DockerInlineSSH, SSHManagedExternallyException
@ -184,7 +185,7 @@ class DockerController(BaseController):
try:
self.client.images.pull(image)
except DockerException: # pragma: no cover
image = f"ghcr.io/goauthentik/{self.outpost.type}:latest"
image = f"ghcr.io/goauthentik/{self.outpost.type}:{__version__}"
self.client.images.pull(image)
return image

View File

@ -35,3 +35,4 @@ class AuthentikPoliciesConfig(ManagedAppConfig):
label = "authentik_policies"
verbose_name = "authentik Policies"
default = True
mountpoint = "policy/"

View File

@ -2,7 +2,6 @@
from django.contrib.auth.signals import user_logged_in
from django.db import transaction
from django.db.models import F
from django.dispatch import receiver
from django.http import HttpRequest
from structlog.stdlib import get_logger
@ -13,20 +12,29 @@ from authentik.events.context_processors.geoip import GEOIP_CONTEXT_PROCESSOR
from authentik.policies.reputation.models import Reputation, reputation_expiry
from authentik.root.middleware import ClientIPMiddleware
from authentik.stages.identification.signals import identification_failed
from authentik.tenants.utils import get_current_tenant
LOGGER = get_logger()
def clamp(value, min, max):
return sorted([min, value, max])[1]
def update_score(request: HttpRequest, identifier: str, amount: int):
"""Update score for IP and User"""
remote_ip = ClientIPMiddleware.get_client_ip(request)
tenant = get_current_tenant()
new_score = clamp(amount, tenant.reputation_lower_limit, tenant.reputation_upper_limit)
with transaction.atomic():
reputation, created = Reputation.objects.select_for_update().get_or_create(
ip=remote_ip,
identifier=identifier,
defaults={
"score": amount,
"score": clamp(
amount, tenant.reputation_lower_limit, tenant.reputation_upper_limit
),
"ip_geo_data": GEOIP_CONTEXT_PROCESSOR.city_dict(remote_ip) or {},
"ip_asn_data": ASN_CONTEXT_PROCESSOR.asn_dict(remote_ip) or {},
"expires": reputation_expiry(),
@ -34,9 +42,15 @@ def update_score(request: HttpRequest, identifier: str, amount: int):
)
if not created:
reputation.score = F("score") + amount
new_score = clamp(
reputation.score + amount,
tenant.reputation_lower_limit,
tenant.reputation_upper_limit,
)
reputation.score = new_score
reputation.save()
LOGGER.info("Updated score", amount=amount, for_user=identifier, for_ip=remote_ip)
LOGGER.info("Updated score", amount=new_score, for_user=identifier, for_ip=remote_ip)
@receiver(login_failed)

View File

@ -6,9 +6,11 @@ from authentik.core.models import User
from authentik.lib.generators import generate_id
from authentik.policies.reputation.api import ReputationPolicySerializer
from authentik.policies.reputation.models import Reputation, ReputationPolicy
from authentik.policies.reputation.signals import update_score
from authentik.policies.types import PolicyRequest
from authentik.stages.password import BACKEND_INBUILT
from authentik.stages.password.stage import authenticate
from authentik.tenants.models import DEFAULT_REPUTATION_LOWER_LIMIT, DEFAULT_REPUTATION_UPPER_LIMIT
class TestReputationPolicy(TestCase):
@ -17,36 +19,48 @@ class TestReputationPolicy(TestCase):
def setUp(self):
self.request_factory = RequestFactory()
self.request = self.request_factory.get("/")
self.test_ip = "127.0.0.1"
self.test_username = "test"
self.ip = "127.0.0.1"
self.username = "username"
self.password = generate_id()
# We need a user for the one-to-one in userreputation
self.user = User.objects.create(username=self.test_username)
self.user = User.objects.create(username=self.username)
self.user.set_password(self.password)
self.backends = [BACKEND_INBUILT]
def test_ip_reputation(self):
"""test IP reputation"""
# Trigger negative reputation
authenticate(
self.request, self.backends, username=self.test_username, password=self.test_username
)
self.assertEqual(Reputation.objects.get(ip=self.test_ip).score, -1)
authenticate(self.request, self.backends, username=self.username, password=self.username)
self.assertEqual(Reputation.objects.get(ip=self.ip).score, -1)
def test_user_reputation(self):
"""test User reputation"""
# Trigger negative reputation
authenticate(
self.request, self.backends, username=self.test_username, password=self.test_username
)
self.assertEqual(Reputation.objects.get(identifier=self.test_username).score, -1)
authenticate(self.request, self.backends, username=self.username, password=self.username)
self.assertEqual(Reputation.objects.get(identifier=self.username).score, -1)
def test_update_reputation(self):
"""test reputation update"""
Reputation.objects.create(identifier=self.test_username, ip=self.test_ip, score=43)
Reputation.objects.create(identifier=self.username, ip=self.ip, score=4)
# Trigger negative reputation
authenticate(
self.request, self.backends, username=self.test_username, password=self.test_username
authenticate(self.request, self.backends, username=self.username, password=self.username)
self.assertEqual(Reputation.objects.get(identifier=self.username).score, 3)
def test_reputation_lower_limit(self):
"""test reputation lower limit"""
Reputation.objects.create(identifier=self.username, ip=self.ip)
update_score(self.request, identifier=self.username, amount=-1000)
self.assertEqual(
Reputation.objects.get(identifier=self.username).score, DEFAULT_REPUTATION_LOWER_LIMIT
)
def test_reputation_upper_limit(self):
"""test reputation upper limit"""
Reputation.objects.create(identifier=self.username, ip=self.ip)
update_score(self.request, identifier=self.username, amount=1000)
self.assertEqual(
Reputation.objects.get(identifier=self.username).score, DEFAULT_REPUTATION_UPPER_LIMIT
)
self.assertEqual(Reputation.objects.get(identifier=self.test_username).score, 42)
def test_policy(self):
"""Test Policy"""

View File

@ -0,0 +1,89 @@
{% extends 'login/base_full.html' %}
{% load static %}
{% load i18n %}
{% block head %}
{{ block.super }}
<script>
let redirecting = false;
const checkAuth = async () => {
if (redirecting) return true;
const url = "{{ check_auth_url }}";
console.debug("authentik/policies/buffer: Checking authentication...");
try {
const result = await fetch(url, {
method: "HEAD",
});
if (result.status >= 400) {
return false
}
console.debug("authentik/policies/buffer: Continuing");
redirecting = true;
if ("{{ auth_req_method }}" === "post") {
document.querySelector("form").submit();
} else {
window.location.assign("{{ continue_url|escapejs }}");
}
} catch {
return false;
}
};
let timeout = 100;
let offset = 20;
let attempt = 0;
const main = async () => {
attempt += 1;
await checkAuth();
console.debug(`authentik/policies/buffer: Waiting ${timeout}ms...`);
setTimeout(main, timeout);
timeout += (offset * attempt);
if (timeout >= 2000) {
timeout = 2000;
}
}
document.addEventListener("visibilitychange", async () => {
if (document.hidden) return;
console.debug("authentik/policies/buffer: Checking authentication on tab activate...");
await checkAuth();
});
main();
</script>
{% endblock %}
{% block title %}
{% trans 'Waiting for authentication...' %} - {{ brand.branding_title }}
{% endblock %}
{% block card_title %}
{% trans 'Waiting for authentication...' %}
{% endblock %}
{% block card %}
<form class="pf-c-form" method="{{ auth_req_method }}" action="{{ continue_url }}">
{% if auth_req_method == "post" %}
{% for key, value in auth_req_body.items %}
<input type="hidden" name="{{ key }}" value="{{ value }}" />
{% endfor %}
{% endif %}
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<div class="pf-c-empty-state__icon">
<span class="pf-c-spinner pf-m-xl" role="progressbar">
<span class="pf-c-spinner__clipper"></span>
<span class="pf-c-spinner__lead-ball"></span>
<span class="pf-c-spinner__tail-ball"></span>
</span>
</div>
<h1 class="pf-c-title pf-m-lg">
{% trans "You're already authenticating in another tab. This page will refresh once authentication is completed." %}
</h1>
</div>
</div>
<div class="pf-c-form__group pf-m-action">
<a href="{{ auth_req_url }}" class="pf-c-button pf-m-primary pf-m-block">
{% trans "Authenticate in this tab" %}
</a>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,121 @@
from django.contrib.auth.models import AnonymousUser
from django.contrib.sessions.middleware import SessionMiddleware
from django.http import HttpResponse
from django.test import RequestFactory, TestCase
from django.urls import reverse
from authentik.core.models import Application, Provider
from authentik.core.tests.utils import create_test_flow, create_test_user
from authentik.flows.models import FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import dummy_get_response
from authentik.policies.views import (
QS_BUFFER_ID,
SESSION_KEY_BUFFER,
BufferedPolicyAccessView,
BufferView,
PolicyAccessView,
)
class TestPolicyViews(TestCase):
"""Test PolicyAccessView"""
def setUp(self):
super().setUp()
self.factory = RequestFactory()
self.user = create_test_user()
def test_pav(self):
"""Test simple policy access view"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
class TestView(PolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/")
req.user = self.user
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.content, b"foo")
def test_pav_buffer(self):
"""Test simple policy access view"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
class TestView(BufferedPolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
req.session.save()
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 302)
self.assertTrue(res.url.startswith(reverse("authentik_policies:buffer")))
def test_pav_buffer_skip(self):
"""Test simple policy access view (skip buffer)"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
class TestView(BufferedPolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/?skip_buffer=true")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
req.session.save()
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 302)
self.assertTrue(res.url.startswith(reverse("authentik_flows:default-authentication")))
def test_buffer(self):
"""Test buffer view"""
uid = generate_id()
req = self.factory.get(f"/?{QS_BUFFER_ID}={uid}")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
ts = generate_id()
req.session[SESSION_KEY_BUFFER % uid] = {
"method": "get",
"body": {},
"url": f"/{ts}",
}
req.session.save()
res = BufferView.as_view()(req)
self.assertEqual(res.status_code, 200)
self.assertIn(ts, res.render().content.decode())

View File

@ -1,7 +1,14 @@
"""API URLs"""
from django.urls import path
from authentik.policies.api.bindings import PolicyBindingViewSet
from authentik.policies.api.policies import PolicyViewSet
from authentik.policies.views import BufferView
urlpatterns = [
path("buffer", BufferView.as_view(), name="buffer"),
]
api_urlpatterns = [
("policies/all", PolicyViewSet),

View File

@ -1,23 +1,37 @@
"""authentik access helper classes"""
from typing import Any
from uuid import uuid4
from django.contrib import messages
from django.contrib.auth.mixins import AccessMixin
from django.contrib.auth.views import redirect_to_login
from django.http import HttpRequest, HttpResponse
from django.http import HttpRequest, HttpResponse, QueryDict
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.http import urlencode
from django.utils.translation import gettext as _
from django.views.generic.base import View
from django.views.generic.base import TemplateView, View
from structlog.stdlib import get_logger
from authentik.core.models import Application, Provider, User
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_POST
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import (
SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_AUTH_STARTED,
SESSION_KEY_PLAN,
SESSION_KEY_POST,
)
from authentik.lib.sentry import SentryIgnoredException
from authentik.policies.denied import AccessDeniedResponse
from authentik.policies.engine import PolicyEngine
from authentik.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger()
QS_BUFFER_ID = "af_bf_id"
QS_SKIP_BUFFER = "skip_buffer"
SESSION_KEY_BUFFER = "authentik/policies/pav_buffer/%s"
class RequestValidationError(SentryIgnoredException):
@ -125,3 +139,65 @@ class PolicyAccessView(AccessMixin, View):
for message in result.messages:
messages.error(self.request, _(message))
return result
def url_with_qs(url: str, **kwargs):
"""Update/set querystring of `url` with the parameters in `kwargs`. Original query string
parameters are retained"""
if "?" not in url:
return url + f"?{urlencode(kwargs)}"
url, _, qs = url.partition("?")
qs = QueryDict(qs, mutable=True)
qs.update(kwargs)
return url + f"?{urlencode(qs.items())}"
class BufferView(TemplateView):
"""Buffer view"""
template_name = "policies/buffer.html"
def get_context_data(self, **kwargs):
buf_id = self.request.GET.get(QS_BUFFER_ID)
buffer: dict = self.request.session.get(SESSION_KEY_BUFFER % buf_id)
kwargs["auth_req_method"] = buffer["method"]
kwargs["auth_req_body"] = buffer["body"]
kwargs["auth_req_url"] = url_with_qs(buffer["url"], **{QS_SKIP_BUFFER: True})
kwargs["check_auth_url"] = reverse("authentik_api:user-me")
kwargs["continue_url"] = url_with_qs(buffer["url"], **{QS_BUFFER_ID: buf_id})
return super().get_context_data(**kwargs)
class BufferedPolicyAccessView(PolicyAccessView):
"""PolicyAccessView which buffers access requests in case the user is not logged in"""
def handle_no_permission(self):
plan: FlowPlan | None = self.request.session.get(SESSION_KEY_PLAN)
authenticating = self.request.session.get(SESSION_KEY_AUTH_STARTED)
if plan:
flow = Flow.objects.filter(pk=plan.flow_pk).first()
if not flow or flow.designation != FlowDesignation.AUTHENTICATION:
LOGGER.debug("Not buffering request, no flow or flow not for authentication")
return super().handle_no_permission()
if not plan and authenticating is None:
LOGGER.debug("Not buffering request, no flow plan active")
return super().handle_no_permission()
if self.request.GET.get(QS_SKIP_BUFFER):
LOGGER.debug("Not buffering request, explicit skip")
return super().handle_no_permission()
buffer_id = str(uuid4())
LOGGER.debug("Buffering access request", bf_id=buffer_id)
self.request.session[SESSION_KEY_BUFFER % buffer_id] = {
"body": self.request.POST,
"url": self.request.build_absolute_uri(self.request.get_full_path()),
"method": self.request.method.lower(),
}
return redirect(
url_with_qs(reverse("authentik_policies:buffer"), **{QS_BUFFER_ID: buffer_id})
)
def dispatch(self, request, *args, **kwargs):
response = super().dispatch(request, *args, **kwargs)
if QS_BUFFER_ID in self.request.GET:
self.request.session.pop(SESSION_KEY_BUFFER % self.request.GET[QS_BUFFER_ID], None)
return response

View File

@ -126,7 +126,7 @@ class IDToken:
id_token.iat = int(now.timestamp())
id_token.auth_time = int(token.auth_time.timestamp())
if token.session:
id_token.sid = hash_session_key(token.session.session_key)
id_token.sid = hash_session_key(token.session.session.session_key)
# We use the timestamp of the user's last successful login (EventAction.LOGIN) for auth_time
auth_event = get_login_event(token.session)

View File

@ -0,0 +1,116 @@
# Generated by Django 5.0.11 on 2025-01-27 13:00
from django.db import migrations
import django.db.models.deletion
from django.db import migrations, models
from functools import partial
def migrate_sessions(apps, schema_editor, model):
Model = apps.get_model("authentik_providers_oauth2", model)
AuthenticatedSession = apps.get_model("authentik_core", "AuthenticatedSession")
db_alias = schema_editor.connection.alias
for obj in Model.objects.using(db_alias).all():
if not obj.old_session:
continue
obj.session = (
AuthenticatedSession.objects.using(db_alias)
.filter(session__session_key=obj.old_session.session_key)
.first()
)
if obj.session:
obj.save()
else:
obj.delete()
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_oauth2", "0027_accesstoken_authentik_p_expires_9f24a5_idx_and_more"),
("authentik_core", "0046_session_and_more"),
]
operations = [
migrations.RenameField(
model_name="accesstoken",
old_name="session",
new_name="old_session",
),
migrations.RenameField(
model_name="authorizationcode",
old_name="session",
new_name="old_session",
),
migrations.RenameField(
model_name="devicetoken",
old_name="session",
new_name="old_session",
),
migrations.RenameField(
model_name="refreshtoken",
old_name="session",
new_name="old_session",
),
migrations.AddField(
model_name="accesstoken",
name="session",
field=models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="authentik_core.authenticatedsession",
),
),
migrations.AddField(
model_name="authorizationcode",
name="session",
field=models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="authentik_core.authenticatedsession",
),
),
migrations.AddField(
model_name="devicetoken",
name="session",
field=models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
to="authentik_core.authenticatedsession",
),
),
migrations.AddField(
model_name="refreshtoken",
name="session",
field=models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
to="authentik_core.authenticatedsession",
),
),
migrations.RunPython(code=partial(migrate_sessions, model="AccessToken")),
migrations.RunPython(code=partial(migrate_sessions, model="AuthorizationCode")),
migrations.RunPython(code=partial(migrate_sessions, model="DeviceToken")),
migrations.RunPython(code=partial(migrate_sessions, model="RefreshToken")),
migrations.RemoveField(
model_name="accesstoken",
name="old_session",
),
migrations.RemoveField(
model_name="authorizationcode",
name="old_session",
),
migrations.RemoveField(
model_name="devicetoken",
name="old_session",
),
migrations.RemoveField(
model_name="refreshtoken",
name="old_session",
),
]

View File

@ -1,18 +1,30 @@
from django.contrib.auth.signals import user_logged_out
from django.db.models.signals import post_save
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from django.http import HttpRequest
from authentik.core.models import User
from authentik.core.models import AuthenticatedSession, User
from authentik.providers.oauth2.models import AccessToken, DeviceToken, RefreshToken
@receiver(user_logged_out)
def user_logged_out_oauth_access_token(sender, request: HttpRequest, user: User, **_):
"""Revoke access tokens upon user logout"""
def user_logged_out_oauth_tokens_removal(sender, request: HttpRequest, user: User, **_):
"""Revoke tokens upon user logout"""
if not request.session or not request.session.session_key:
return
AccessToken.objects.filter(user=user, session__session_key=request.session.session_key).delete()
AccessToken.objects.filter(
user=user,
session__session__session_key=request.session.session_key,
).delete()
@receiver(pre_delete, sender=AuthenticatedSession)
def user_session_deleted_oauth_tokens_removal(sender, instance: AuthenticatedSession, **_):
"""Revoke tokens upon user logout"""
AccessToken.objects.filter(
user=instance.user,
session__session__session_key=instance.session.session_key,
).delete()
@receiver(post_save, sender=User)
@ -20,6 +32,6 @@ def user_deactivated(sender, instance: User, **_):
"""Remove user tokens when deactivated"""
if instance.is_active:
return
AccessToken.objects.filter(session__user=instance).delete()
RefreshToken.objects.filter(session__user=instance).delete()
DeviceToken.objects.filter(session__user=instance).delete()
AccessToken.objects.filter(user=instance).delete()
RefreshToken.objects.filter(user=instance).delete()
DeviceToken.objects.filter(user=instance).delete()

View File

@ -7,12 +7,13 @@ from dataclasses import asdict
from django.urls import reverse
from django.utils import timezone
from authentik.core.models import Application
from authentik.core.models import Application, AuthenticatedSession, Session
from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import (
AccessToken,
ClientTypes,
DeviceToken,
IDToken,
OAuth2Provider,
RedirectURI,
@ -20,6 +21,7 @@ from authentik.providers.oauth2.models import (
RefreshToken,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
from authentik.root.middleware import ClientIPMiddleware
class TesOAuth2Revoke(OAuthTestCase):
@ -135,3 +137,86 @@ class TesOAuth2Revoke(OAuthTestCase):
},
)
self.assertEqual(res.status_code, 200)
def test_revoke_logout(self):
"""Test revoke on logout"""
self.client.force_login(self.user)
AccessToken.objects.create(
provider=self.provider,
user=self.user,
session=self.client.session["authenticatedsession"],
token=generate_id(),
auth_time=timezone.now(),
_scope="openid user profile",
_id_token=json.dumps(
asdict(
IDToken("foo", "bar"),
)
),
)
self.client.logout()
self.assertEqual(AccessToken.objects.all().count(), 0)
def test_revoke_session_delete(self):
"""Test revoke on logout"""
session = AuthenticatedSession.objects.create(
session=Session.objects.create(
session_key=generate_id(),
last_ip=ClientIPMiddleware.default_ip,
),
user=self.user,
)
AccessToken.objects.create(
provider=self.provider,
user=self.user,
session=session,
token=generate_id(),
auth_time=timezone.now(),
_scope="openid user profile",
_id_token=json.dumps(
asdict(
IDToken("foo", "bar"),
)
),
)
session.delete()
self.assertEqual(AccessToken.objects.all().count(), 0)
def test_revoke_user_deactivated(self):
"""Test revoke on logout"""
AccessToken.objects.create(
provider=self.provider,
user=self.user,
token=generate_id(),
auth_time=timezone.now(),
_scope="openid user profile",
_id_token=json.dumps(
asdict(
IDToken("foo", "bar"),
)
),
)
RefreshToken.objects.create(
provider=self.provider,
user=self.user,
token=generate_id(),
auth_time=timezone.now(),
_scope="openid user profile",
_id_token=json.dumps(
asdict(
IDToken("foo", "bar"),
)
),
)
DeviceToken.objects.create(
provider=self.provider,
user=self.user,
_scope="openid user profile",
)
self.user.is_active = False
self.user.save()
self.assertEqual(AccessToken.objects.all().count(), 0)
self.assertEqual(RefreshToken.objects.all().count(), 0)
self.assertEqual(DeviceToken.objects.all().count(), 0)

View File

@ -15,7 +15,7 @@ from django.utils import timezone
from django.utils.translation import gettext as _
from structlog.stdlib import get_logger
from authentik.core.models import Application, AuthenticatedSession
from authentik.core.models import Application
from authentik.events.models import Event, EventAction
from authentik.events.signals import get_login_event
from authentik.flows.challenge import (
@ -30,7 +30,7 @@ from authentik.flows.stage import StageView
from authentik.lib.utils.time import timedelta_from_string
from authentik.lib.views import bad_request_message
from authentik.policies.types import PolicyRequest
from authentik.policies.views import PolicyAccessView, RequestValidationError
from authentik.policies.views import BufferedPolicyAccessView, RequestValidationError
from authentik.providers.oauth2.constants import (
PKCE_METHOD_PLAIN,
PKCE_METHOD_S256,
@ -316,9 +316,7 @@ class OAuthAuthorizationParams:
expires=now + timedelta_from_string(self.provider.access_code_validity),
scope=self.scope,
nonce=self.nonce,
session=AuthenticatedSession.objects.filter(
session_key=request.session.session_key
).first(),
session=request.session["authenticatedsession"],
)
if self.code_challenge and self.code_challenge_method:
@ -328,7 +326,7 @@ class OAuthAuthorizationParams:
return code
class AuthorizationFlowInitView(PolicyAccessView):
class AuthorizationFlowInitView(BufferedPolicyAccessView):
"""OAuth2 Flow initializer, checks access to application and starts flow"""
params: OAuthAuthorizationParams
@ -615,9 +613,7 @@ class OAuthFulfillmentStage(StageView):
expires=access_token_expiry,
provider=self.provider,
auth_time=auth_event.created if auth_event else now,
session=AuthenticatedSession.objects.filter(
session_key=self.request.session.session_key
).first(),
session=self.request.session["authenticatedsession"],
)
id_token = IDToken.new(self.provider, token, self.request)

View File

@ -20,4 +20,4 @@ def logout_proxy_revoke_direct(sender: type[User], request: HttpRequest, **_):
@receiver(pre_delete, sender=AuthenticatedSession)
def logout_proxy_revoke(sender: type[AuthenticatedSession], instance: AuthenticatedSession, **_):
"""Catch logout by expiring sessions being deleted"""
proxy_on_logout.delay(instance.session_key)
proxy_on_logout.delay(instance.session.session_key)

View File

@ -0,0 +1,60 @@
# Generated by Django 5.0.11 on 2025-01-27 12:59
from django.db import migrations
import django.db.models.deletion
from django.db import migrations, models
def migrate_sessions(apps, schema_editor):
ConnectionToken = apps.get_model("authentik_providers_rac", "ConnectionToken")
AuthenticatedSession = apps.get_model("authentik_core", "AuthenticatedSession")
db_alias = schema_editor.connection.alias
for token in ConnectionToken.objects.using(db_alias).all():
token.session = (
AuthenticatedSession.objects.using(db_alias)
.filter(session_key=token.old_session.session_key)
.first()
)
if token.session:
token.save()
else:
token.delete()
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_rac", "0006_connectiontoken_authentik_p_expires_91f148_idx_and_more"),
("authentik_core", "0046_session_and_more"),
]
operations = [
migrations.RenameField(
model_name="connectiontoken",
old_name="session",
new_name="old_session",
),
migrations.AddField(
model_name="connectiontoken",
name="session",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="authentik_core.authenticatedsession",
),
),
migrations.RunPython(code=migrate_sessions),
migrations.AlterField(
model_name="connectiontoken",
name="session",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="authentik_core.authenticatedsession",
),
),
migrations.RemoveField(
model_name="connectiontoken",
name="old_session",
),
]

View File

@ -8,7 +8,7 @@ from django.db.models.signals import post_delete, post_save, pre_delete
from django.dispatch import receiver
from django.http import HttpRequest
from authentik.core.models import User
from authentik.core.models import AuthenticatedSession, User
from authentik.providers.rac.api.endpoints import user_endpoint_cache_key
from authentik.providers.rac.consumer_client import (
RAC_CLIENT_GROUP_SESSION,
@ -32,6 +32,18 @@ def user_logged_out_session(sender, request: HttpRequest, user: User, **_):
)
@receiver(pre_delete, sender=AuthenticatedSession)
def user_session_deleted(sender, instance: AuthenticatedSession, **_):
layer = get_channel_layer()
async_to_sync(layer.group_send)(
RAC_CLIENT_GROUP_SESSION
% {
"session": instance.session.session_key,
},
{"type": "event.disconnect", "reason": "session_logout"},
)
@receiver(pre_delete, sender=ConnectionToken)
def pre_delete_connection_token_disconnect(sender, instance: ConnectionToken, **_):
"""Disconnect session when connection token is deleted"""

View File

@ -2,7 +2,7 @@
from django.test import TransactionTestCase
from authentik.core.models import Application, AuthenticatedSession
from authentik.core.models import Application, AuthenticatedSession, Session
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.generators import generate_id
from authentik.providers.rac.models import (
@ -36,13 +36,15 @@ class TestModels(TransactionTestCase):
def test_settings_merge(self):
"""Test settings merge"""
session = Session.objects.create(
session_key=generate_id(),
last_ip="255.255.255.255",
)
auth_session = AuthenticatedSession.objects.create(session=session, user=self.user)
token = ConnectionToken.objects.create(
provider=self.provider,
endpoint=self.endpoint,
session=AuthenticatedSession.objects.create(
user=self.user,
session_key=generate_id(),
),
session=auth_session,
)
path = f"/tmp/connection/{token.token}" # nosec
self.assertEqual(

View File

@ -1,7 +1,5 @@
"""rac urls"""
from channels.auth import AuthMiddleware
from channels.sessions import CookieMiddleware
from django.urls import path
from authentik.outposts.channels import TokenOutpostMiddleware
@ -12,7 +10,7 @@ from authentik.providers.rac.api.providers import RACProviderViewSet
from authentik.providers.rac.consumer_client import RACClientConsumer
from authentik.providers.rac.consumer_outpost import RACOutpostConsumer
from authentik.providers.rac.views import RACInterface, RACStartView
from authentik.root.asgi_middleware import SessionMiddleware
from authentik.root.asgi_middleware import AuthMiddlewareStack
from authentik.root.middleware import ChannelsLoggingMiddleware
urlpatterns = [
@ -31,9 +29,7 @@ urlpatterns = [
websocket_urlpatterns = [
path(
"ws/rac/<str:token>/",
ChannelsLoggingMiddleware(
CookieMiddleware(SessionMiddleware(AuthMiddleware(RACClientConsumer.as_asgi())))
),
ChannelsLoggingMiddleware(AuthMiddlewareStack(RACClientConsumer.as_asgi())),
),
path(
"ws/outpost_rac/<str:channel>/",

View File

@ -8,7 +8,7 @@ from django.urls import reverse
from django.utils.timezone import now
from django.utils.translation import gettext as _
from authentik.core.models import Application, AuthenticatedSession
from authentik.core.models import Application
from authentik.core.views.interface import InterfaceView
from authentik.events.models import Event, EventAction
from authentik.flows.challenge import RedirectChallenge
@ -18,11 +18,11 @@ from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner
from authentik.flows.stage import RedirectStage
from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.engine import PolicyEngine
from authentik.policies.views import PolicyAccessView
from authentik.policies.views import BufferedPolicyAccessView
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
class RACStartView(PolicyAccessView):
class RACStartView(BufferedPolicyAccessView):
"""Start a RAC connection by checking access and creating a connection token"""
endpoint: Endpoint
@ -113,9 +113,7 @@ class RACFinalStage(RedirectStage):
provider=self.provider,
endpoint=self.endpoint,
settings=self.executor.plan.context.get("connection_settings", {}),
session=AuthenticatedSession.objects.filter(
session_key=self.request.session.session_key
).first(),
session=self.request.session["authenticatedsession"],
expires=now() + timedelta_from_string(self.provider.connection_expiry),
expiring=True,
)

View File

@ -180,6 +180,7 @@ class SAMLProviderSerializer(ProviderSerializer):
"session_valid_not_on_or_after",
"property_mappings",
"name_id_mapping",
"authn_context_class_ref_mapping",
"digest_algorithm",
"signature_algorithm",
"signing_kp",

View File

@ -0,0 +1,28 @@
# Generated by Django 5.0.13 on 2025-03-18 17:41
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_saml", "0016_samlprovider_encryption_kp_and_more"),
]
operations = [
migrations.AddField(
model_name="samlprovider",
name="authn_context_class_ref_mapping",
field=models.ForeignKey(
blank=True,
default=None,
help_text="Configure how the AuthnContextClassRef value will be created. When left empty, the AuthnContextClassRef will be set based on which authentication methods the user used to authenticate.",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
related_name="+",
to="authentik_providers_saml.samlpropertymapping",
verbose_name="AuthnContextClassRef Property Mapping",
),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 5.0.13 on 2025-03-31 13:50
import authentik.lib.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_saml", "0017_samlprovider_authn_context_class_ref_mapping"),
]
operations = [
migrations.AlterField(
model_name="samlprovider",
name="acs_url",
field=models.TextField(
validators=[authentik.lib.models.DomainlessURLValidator(schemes=("http", "https"))],
verbose_name="ACS URL",
),
),
]

View File

@ -10,6 +10,7 @@ from structlog.stdlib import get_logger
from authentik.core.api.object_types import CreatableType
from authentik.core.models import PropertyMapping, Provider
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import (
DSA_SHA1,
@ -40,7 +41,9 @@ class SAMLBindings(models.TextChoices):
class SAMLProvider(Provider):
"""SAML 2.0 Endpoint for applications which support SAML."""
acs_url = models.URLField(verbose_name=_("ACS URL"))
acs_url = models.TextField(
validators=[DomainlessURLValidator(schemes=("http", "https"))], verbose_name=_("ACS URL")
)
audience = models.TextField(
default="",
blank=True,
@ -71,6 +74,20 @@ class SAMLProvider(Provider):
"the NameIDPolicy of the incoming request will be considered"
),
)
authn_context_class_ref_mapping = models.ForeignKey(
"SAMLPropertyMapping",
default=None,
blank=True,
null=True,
on_delete=models.SET_DEFAULT,
verbose_name=_("AuthnContextClassRef Property Mapping"),
related_name="+",
help_text=_(
"Configure how the AuthnContextClassRef value will be created. When left empty, "
"the AuthnContextClassRef will be set based on which authentication methods the user "
"used to authenticate."
),
)
assertion_valid_not_before = models.TextField(
default="minutes=-5",
@ -170,7 +187,6 @@ class SAMLProvider(Provider):
def launch_url(self) -> str | None:
"""Use IDP-Initiated SAML flow as launch URL"""
try:
return reverse(
"authentik_providers_saml:sso-init",
kwargs={"application_slug": self.application.slug},

View File

@ -1,5 +1,6 @@
"""SAML Assertion generator"""
from datetime import datetime
from hashlib import sha256
from types import GeneratorType
@ -52,6 +53,7 @@ class AssertionProcessor:
_assertion_id: str
_response_id: str
_auth_instant: str
_valid_not_before: str
_session_not_on_or_after: str
_valid_not_on_or_after: str
@ -65,6 +67,11 @@ class AssertionProcessor:
self._assertion_id = get_random_id()
self._response_id = get_random_id()
_login_event = get_login_event(self.http_request)
_login_time = datetime.now()
if _login_event:
_login_time = _login_event.created
self._auth_instant = get_time_string(_login_time)
self._valid_not_before = get_time_string(
timedelta_from_string(self.provider.assertion_valid_not_before)
)
@ -131,7 +138,7 @@ class AssertionProcessor:
def get_assertion_auth_n_statement(self) -> Element:
"""Generate AuthnStatement with AuthnContext and ContextClassRef Elements."""
auth_n_statement = Element(f"{{{NS_SAML_ASSERTION}}}AuthnStatement")
auth_n_statement.attrib["AuthnInstant"] = self._valid_not_before
auth_n_statement.attrib["AuthnInstant"] = self._auth_instant
auth_n_statement.attrib["SessionIndex"] = sha256(
self.http_request.session.session_key.encode("ascii")
).hexdigest()
@ -158,6 +165,28 @@ class AssertionProcessor:
auth_n_context_class_ref.text = (
"urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract"
)
if self.provider.authn_context_class_ref_mapping:
try:
value = self.provider.authn_context_class_ref_mapping.evaluate(
user=self.http_request.user,
request=self.http_request,
provider=self.provider,
)
if value is not None:
auth_n_context_class_ref.text = str(value)
return auth_n_statement
except PropertyMappingExpressionException as exc:
Event.new(
EventAction.CONFIGURATION_ERROR,
message=(
"Failed to evaluate property-mapping: "
f"'{self.provider.authn_context_class_ref_mapping.name}'"
),
provider=self.provider,
mapping=self.provider.authn_context_class_ref_mapping,
).from_http(self.http_request)
LOGGER.warning("Failed to evaluate property mapping", exc=exc)
return auth_n_statement
return auth_n_statement
def get_assertion_conditions(self) -> Element:

View File

@ -294,6 +294,61 @@ class TestAuthNRequest(TestCase):
self.assertEqual(parsed_request.id, "aws_LDxLGeubpc5lx12gxCgS6uPbix1yd5re")
self.assertEqual(parsed_request.name_id_policy, SAML_NAME_ID_FORMAT_EMAIL)
def test_authn_context_class_ref_mapping(self):
"""Test custom authn_context_class_ref"""
authn_context_class_ref = generate_id()
mapping = SAMLPropertyMapping.objects.create(
name=generate_id(), expression=f"""return '{authn_context_class_ref}'"""
)
self.provider.authn_context_class_ref_mapping = mapping
self.provider.save()
user = create_test_admin_user()
http_request = get_request("/", user=user)
# First create an AuthNRequest
request_proc = RequestProcessor(self.source, http_request, "test_state")
request = request_proc.build_auth_n()
# To get an assertion we need a parsed request (parsed by provider)
parsed_request = AuthNRequestParser(self.provider).parse(
b64encode(request.encode()).decode(), "test_state"
)
# Now create a response and convert it to string (provider)
response_proc = AssertionProcessor(self.provider, http_request, parsed_request)
response = response_proc.build_response()
self.assertIn(user.username, response)
self.assertIn(authn_context_class_ref, response)
def test_authn_context_class_ref_mapping_invalid(self):
"""Test custom authn_context_class_ref (invalid)"""
mapping = SAMLPropertyMapping.objects.create(name=generate_id(), expression="q")
self.provider.authn_context_class_ref_mapping = mapping
self.provider.save()
user = create_test_admin_user()
http_request = get_request("/", user=user)
# First create an AuthNRequest
request_proc = RequestProcessor(self.source, http_request, "test_state")
request = request_proc.build_auth_n()
# To get an assertion we need a parsed request (parsed by provider)
parsed_request = AuthNRequestParser(self.provider).parse(
b64encode(request.encode()).decode(), "test_state"
)
# Now create a response and convert it to string (provider)
response_proc = AssertionProcessor(self.provider, http_request, parsed_request)
response = response_proc.build_response()
self.assertIn(user.username, response)
events = Event.objects.filter(
action=EventAction.CONFIGURATION_ERROR,
)
self.assertTrue(events.exists())
self.assertEqual(
events.first().context["message"],
f"Failed to evaluate property-mapping: '{mapping.name}'",
)
def test_request_attributes(self):
"""Test full SAML Request/Response flow, fully signed"""
user = create_test_admin_user()
@ -321,8 +376,10 @@ class TestAuthNRequest(TestCase):
request = request_proc.build_auth_n()
# Create invalid PropertyMapping
scope = SAMLPropertyMapping.objects.create(name="test", saml_name="test", expression="q")
self.provider.property_mappings.add(scope)
mapping = SAMLPropertyMapping.objects.create(
name=generate_id(), saml_name="test", expression="q"
)
self.provider.property_mappings.add(mapping)
# To get an assertion we need a parsed request (parsed by provider)
parsed_request = AuthNRequestParser(self.provider).parse(
@ -338,7 +395,7 @@ class TestAuthNRequest(TestCase):
self.assertTrue(events.exists())
self.assertEqual(
events.first().context["message"],
"Failed to evaluate property-mapping: 'test'",
f"Failed to evaluate property-mapping: '{mapping.name}'",
)
def test_idp_initiated(self):

View File

@ -1,12 +1,16 @@
"""Time utilities"""
import datetime
from datetime import datetime, timedelta
from django.utils.timezone import now
def get_time_string(delta: datetime.timedelta | None = None) -> str:
def get_time_string(delta: timedelta | datetime | None = None) -> str:
"""Get Data formatted in SAML format"""
if delta is None:
delta = datetime.timedelta()
now = datetime.datetime.now()
final = now + delta
delta = timedelta()
if isinstance(delta, timedelta):
final = now() + delta
else:
final = delta
return final.strftime("%Y-%m-%dT%H:%M:%SZ")

View File

@ -15,7 +15,7 @@ from authentik.flows.models import in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner
from authentik.flows.views.executor import SESSION_KEY_POST
from authentik.lib.views import bad_request_message
from authentik.policies.views import PolicyAccessView
from authentik.policies.views import BufferedPolicyAccessView
from authentik.providers.saml.exceptions import CannotHandleAssertion
from authentik.providers.saml.models import SAMLBindings, SAMLProvider
from authentik.providers.saml.processors.authn_request_parser import AuthNRequestParser
@ -35,7 +35,7 @@ from authentik.stages.consent.stage import (
LOGGER = get_logger()
class SAMLSSOView(PolicyAccessView):
class SAMLSSOView(BufferedPolicyAccessView):
"""SAML SSO Base View, which plans a flow and injects our final stage.
Calls get/post handler."""
@ -83,7 +83,7 @@ class SAMLSSOView(PolicyAccessView):
def post(self, request: HttpRequest, application_slug: str) -> HttpResponse:
"""GET and POST use the same handler, but we can't
override .dispatch easily because PolicyAccessView's dispatch"""
override .dispatch easily because BufferedPolicyAccessView's dispatch"""
return self.get(request, application_slug)

View File

@ -24,7 +24,9 @@ class SCIMProviderGroupSerializer(ModelSerializer):
"group",
"group_obj",
"provider",
"attributes",
]
extra_kwargs = {"attributes": {"read_only": True}}
class SCIMProviderGroupViewSet(

View File

@ -24,7 +24,9 @@ class SCIMProviderUserSerializer(ModelSerializer):
"user",
"user_obj",
"provider",
"attributes",
]
extra_kwargs = {"attributes": {"read_only": True}}
class SCIMProviderUserViewSet(

View File

@ -102,7 +102,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMProviderGroup, SCIMGroupSchema]):
if not scim_id or scim_id == "":
raise StopSync("SCIM Response with missing or invalid `id`")
connection = SCIMProviderGroup.objects.create(
provider=self.provider, group=group, scim_id=scim_id
provider=self.provider, group=group, scim_id=scim_id, attributes=response
)
users = list(group.users.order_by("id").values_list("id", flat=True))
self._patch_add_users(connection, users)
@ -243,9 +243,10 @@ class SCIMGroupClient(SCIMClient[Group, SCIMProviderGroup, SCIMGroupSchema]):
if user.value not in users_should:
users_to_remove.append(user.value)
# Check users that should be in the group and add them
for user in users_should:
if len([x for x in current_group.members if x.value == user]) < 1:
users_to_add.append(user)
if current_group.members is not None:
for user in users_should:
if len([x for x in current_group.members if x.value == user]) < 1:
users_to_add.append(user)
# Only send request if we need to make changes
if len(users_to_add) < 1 and len(users_to_remove) < 1:
return

View File

@ -77,21 +77,24 @@ class SCIMUserClient(SCIMClient[User, SCIMProviderUser, SCIMUserSchema]):
if len(users_res) < 1:
raise exc
return SCIMProviderUser.objects.create(
provider=self.provider, user=user, scim_id=users_res[0]["id"]
provider=self.provider,
user=user,
scim_id=users_res[0]["id"],
attributes=users_res[0],
)
else:
scim_id = response.get("id")
if not scim_id or scim_id == "":
raise StopSync("SCIM Response with missing or invalid `id`")
return SCIMProviderUser.objects.create(
provider=self.provider, user=user, scim_id=scim_id
provider=self.provider, user=user, scim_id=scim_id, attributes=response
)
def update(self, user: User, connection: SCIMProviderUser):
"""Update existing user"""
scim_user = self.to_schema(user, connection)
scim_user.id = connection.scim_id
self._request(
response = self._request(
"PUT",
f"/Users/{connection.scim_id}",
json=scim_user.model_dump(
@ -99,3 +102,5 @@ class SCIMUserClient(SCIMClient[User, SCIMProviderUser, SCIMUserSchema]):
exclude_unset=True,
),
)
connection.attributes = response
connection.save()

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