Compare commits

..

300 Commits

Author SHA1 Message Date
Tana M Berry
eab28d0ad6 rebase 2025-07-24 13:03:19 -05:00
Marc 'risson' Schmitt
a1ee3ca278 Update website/docs/install-config/configuration/configuration.mdx
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-07-24 12:59:17 -05:00
Marc 'risson' Schmitt
d9db8ac044 Update website/docs/install-config/configuration/configuration.mdx
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-07-24 12:59:17 -05:00
Marc 'risson' Schmitt
c9c0674711 Update website/docs/install-config/configuration/configuration.mdx
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-07-24 12:59:17 -05:00
Marc 'risson' Schmitt
93c2bb7e9f add tests
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-07-24 12:59:17 -05:00
Marc 'risson' Schmitt
0bbadf3194 rework a bit
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-07-24 12:59:17 -05:00
Duncan Tasker
9f97a65094 ran make lint, updated documentation 2025-07-24 12:59:17 -05:00
Duncan Tasker
c2a41940bc fix order of option parsing, allowed user to add options to replicas not specified in the default config 2025-07-24 12:59:17 -05:00
Duncan Tasker
f30120e88a searches both default replica path and replica conn opts path when assigning replica specific options 2025-07-24 12:59:17 -05:00
Duncan Tasker
4582183da4 added global replica options and per replica options 2025-07-24 12:59:17 -05:00
Staz M
d8cf464f3c config: Allow for setting custom SQL connection string options.
This allows for setting additional settings on the PostgresSQL
connection string, such as `host`, and  `target_session_attrs`.
2025-07-24 12:59:17 -05:00
Teffen Ellis
4a933b814f web: Update dependencies. Fix categories. (#15748)
* web: Update deps. Avoid devDependencies.

* web: Replace deprecated package with our own.

* web: Clean up dev deps.

* web: Clean up root packages.

* web: Dedupe plugin.
2025-07-24 18:11:32 +02:00
Teffen Ellis
236a6e0176 web: Clean up WebSocket lifecycle. (#15480) 2025-07-24 15:51:20 +00:00
Teffen Ellis
f00772faf1 web: Font fixes (#15581)
* add base element

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

* web: Rewrite relative CSS asset paths. Update fonts.

Update web/bundler/css-assets-plugin/node.js

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-07-24 15:40:38 +00:00
Teffen Ellis
068bd34392 website: Flesh out package structure. (#15773)
* website: Flesh out package structure.

* Apply suggestions from code review

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-07-24 11:01:27 -04:00
Teffen Ellis
4161a678b8 root: Update spellcheck ignore list. (#15772)
core: Update ignore list.
2025-07-24 11:00:45 -04:00
Marc 'risson' Schmitt
bafe8a5104 blueprints: add FindObject tag (#12415) 2025-07-24 13:30:47 +00:00
dependabot[bot]
f4079a9e0d core: bump google-api-python-client from 2.176.0 to 2.177.0 (#15765)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.176.0 to 2.177.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.176.0...v2.177.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 15:02:57 +02:00
dependabot[bot]
62a6101ecb web: bump @fortawesome/fontawesome-free from 6.7.2 to 7.0.0 in /web (#15766)
Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 6.7.2 to 7.0.0.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/7.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.7.2...7.0.0)

---
updated-dependencies:
- dependency-name: "@fortawesome/fontawesome-free"
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 14:29:47 +02:00
dependabot[bot]
0820e34301 web: bump chromedriver from 136.0.3 to 138.0.3 in /web (#15767)
* web: bump chromedriver from 136.0.3 to 138.0.3 in /web

Bumps [chromedriver](https://github.com/giggio/node-chromedriver) from 136.0.3 to 138.0.3.
- [Commits](https://github.com/giggio/node-chromedriver/compare/136.0.3...138.0.3)

---
updated-dependencies:
- dependency-name: chromedriver
  dependency-version: 138.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

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

* only netlify deploy when token available

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-07-24 14:29:31 +02:00
Marc 'risson' Schmitt
25ee8b8b5f sources/plex: add missing group connection type to flow manager (#15750) 2025-07-24 12:27:46 +00:00
Marc 'risson' Schmitt
c876b28fff providers/oauth2: add support for OAuth 2.0 Authorization Server Metadata endpoint (RFC 8414) (#12383) 2025-07-24 14:11:20 +02:00
authentik-automation[bot]
7b3b9901a0 core, web: update translations (#15764)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-07-24 13:28:56 +02:00
dependabot[bot]
6c56d612cf website: bump the eslint group in /website with 3 updates (#15705)
---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-version: 8.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 00:38:17 +02:00
Marcelo Elizeche Landó
cc11daa7fa core: bump microsoft-kiota-serialization-text from 1.9.4 to v1.9.5 (#15760) 2025-07-24 00:19:12 +02:00
Marcelo Elizeche Landó
6ea8eb84a2 core: bump s3transfer from 0.13.0 to v0.13.1 (#15762) 2025-07-24 00:19:09 +02:00
Marcelo Elizeche Landó
c21e920a3f core: bump microsoft-kiota-serialization-json from 1.9.4 to v1.9.5 (#15758) 2025-07-23 22:01:19 +02:00
Marcelo Elizeche Landó
872704c2ab core: bump microsoft-kiota-serialization-multipart from 1.9.4 to v1.9.5 (#15759) 2025-07-23 22:00:59 +02:00
Marcelo Elizeche Landó
05a6238741 core: bump microsoft-kiota-abstractions from 1.9.4 to v1.9.5 (#15756) 2025-07-23 22:00:33 +02:00
Marcelo Elizeche Landó
8a125d5ee8 core: bump msal from 1.32.3 to v1.33.0 (#15761) 2025-07-23 22:00:12 +02:00
Marcelo Elizeche Landó
902d1dd9a1 core: bump microsoft-kiota-serialization-form from 1.9.4 to v1.9.5 (#15757) 2025-07-23 21:59:28 +02:00
Marcelo Elizeche Landó
87ab3ed8a4 core: bump boto3 from 1.39.7 to v1.39.11 (#15754)
core: bump boto3 from 1.39.11 to v1.39.11
2025-07-23 21:58:30 +02:00
Marcelo Elizeche Landó
ae7261b75e core: bump jsonschema from 4.24.0 to v4.25.0 (#15755) 2025-07-23 21:57:55 +02:00
Germán Martín
0d60b2830c website/integrations: Update Node-RED configuration (#15488)
* Update Node-RED configuration

After playing around it for a couple days I found that Node-red uses 4 parameters in verify function. This configuration is working for me.

https://discourse.nodered.org/t/setting-up-oidc-with-authentik-gives-syntaxerror-unexpected-token-not-valid-json/97981

Signed-off-by: Germán Martín <github@gmartin.net>

* Fix format

Signed-off-by: Germán Martín <github@gmartin.net>

* rebased, tweaked to bump build

* Update website/integrations/development/node-red/index.md

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

* Update website/integrations/development/node-red/index.md

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

---------

Signed-off-by: Germán Martín <github@gmartin.net>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-07-23 12:45:36 -05:00
Teffen Ellis
8766191d67 website: Docusaurus 3.8 Follow-up - API Docs (#15751)
* website: Update API build directory.

* website: Update header paths. Use separate build paths.
2025-07-23 15:54:21 +00:00
dependabot[bot]
df3ae0d1da website: bump @types/node from 24.0.15 to 24.1.0 in /website (#15743)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.0.15 to 24.1.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 17:17:01 +02:00
Teffen Ellis
e280159946 website: Docusaurus 3.8 (#15097)
website: Upgrade Docusaurus. Split API build.
2025-07-23 16:42:01 +02:00
Connor Peshek
35de683959 website/docs: update command formattings for easier dev usage (#15430)
* website/docs update command formattings for easier dev usage.

* website/docs update command formattings and step wordings.

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Connor Peshek <connor@connorpeshek.me>

* website/docs remove comments from commands and improve surrounding wordings.

* website/docs run make website.

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Connor Peshek <connor@connorpeshek.me>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Connor Peshek <connor@connorpeshek.me>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Connor Peshek <connor@connorpeshek.me>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Connor Peshek <connor@connorpeshek.me>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Connor Peshek <connor@connorpeshek.me>

* website/docs Rework full-dev-environment page for easier dev onboarding.

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

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/developer-docs/setup/full-dev-environment.mdx

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/developer-docs/setup/full-dev-environment.mdx

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/developer-docs/setup/full-dev-environment.mdx

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

---------

Signed-off-by: Connor Peshek <connor@connorpeshek.me>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: connor <connor@connors-MacBook-Pro.local>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-07-23 09:40:09 -05:00
Dominic R
7d82fb7069 website/integrations: headscale (#14500)
* headscale

* test

* Update website/integrations/networking/headscale/index.md

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

---------

Signed-off-by: Dominic R <dominic@sdko.org>
2025-07-23 08:32:24 +01:00
dependabot[bot]
06d4f17743 core: bump astral-sh/uv from 0.8.0 to 0.8.2 (#15731)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.8.0 to 0.8.2.
- [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.8.0...0.8.2)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.8.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-07-23 08:24:28 +02:00
dependabot[bot]
9153cfe83c web: bump @types/node from 24.0.15 to 24.1.0 in /packages/esbuild-plugin-live-reload (#15734)
web: bump @types/node in /packages/esbuild-plugin-live-reload

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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.1.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-07-23 08:24:15 +02:00
dependabot[bot]
709cf785a9 web: bump @types/node from 24.0.15 to 24.1.0 in /packages/prettier-config (#15735)
web: bump @types/node in /packages/prettier-config

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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.1.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-07-23 08:24:06 +02:00
dependabot[bot]
db70211754 web: bump webcomponent-qr-code from 1.2.0 to 1.3.0 in /web (#15736)
Bumps [webcomponent-qr-code](https://github.com/educastellano/qr-code) from 1.2.0 to 1.3.0.
- [Commits](https://github.com/educastellano/qr-code/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: webcomponent-qr-code
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 08:23:48 +02:00
dependabot[bot]
31510bb276 web: bump the swc group across 1 directory with 11 updates (#15733)
Bumps the swc group with 1 update in the /web directory: [@swc/core](https://github.com/swc-project/swc).


Updates `@swc/core` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-darwin-arm64` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-darwin-x64` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-linux-arm-gnueabihf` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-linux-arm64-gnu` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-linux-arm64-musl` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-linux-x64-gnu` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-linux-x64-musl` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-win32-arm64-msvc` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-win32-ia32-msvc` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-win32-x64-msvc` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 08:23:29 +02:00
dependabot[bot]
4bc6ba3dbe web: bump @lit/context from 1.1.5 to 1.1.6 in /web (#15739)
Bumps [@lit/context](https://github.com/lit/lit/tree/HEAD/packages/context) from 1.1.5 to 1.1.6.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit/context@1.1.6/packages/context)

---
updated-dependencies:
- dependency-name: "@lit/context"
  dependency-version: 1.1.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 08:23:12 +02:00
dependabot[bot]
125af7daf5 web: bump the storybook group across 1 directory with 5 updates (#15732)
Bumps the storybook group with 4 updates in the /web directory: [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/docs), [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links), [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) and [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite).


Updates `@storybook/addon-docs` from 9.0.17 to 9.0.18
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.18/code/addons/docs)

Updates `@storybook/addon-links` from 9.0.17 to 9.0.18
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.18/code/addons/links)

Updates `@storybook/web-components` from 9.0.17 to 9.0.18
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.18/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 9.0.17 to 9.0.18
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.18/code/frameworks/web-components-vite)

Updates `storybook` from 9.0.17 to 9.0.18
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.18/code/core)

---
updated-dependencies:
- dependency-name: "@storybook/addon-docs"
  dependency-version: 9.0.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-version: 9.0.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-version: 9.0.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-version: 9.0.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-version: 9.0.18
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 08:23:01 +02:00
dependabot[bot]
130d0235d4 web: bump lit from 3.3.0 to 3.3.1 in /web (#15737)
Bumps [lit](https://github.com/lit/lit/tree/HEAD/packages/lit) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/lit/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/lit@3.3.1/packages/lit)

---
updated-dependencies:
- dependency-name: lit
  dependency-version: 3.3.1
  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-07-23 08:22:44 +02:00
dependabot[bot]
6ba97cba5a web: bump @types/node from 22.15.19 to 24.1.0 in /web (#15740)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.15.19 to 24.1.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 08:22:30 +02:00
dependabot[bot]
7aac9dea53 core: bump goauthentik.io/api/v3 from 3.2025063.6 to 3.2025064.1 (#15741)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025063.6 to 3.2025064.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.2025063.6...v3.2025064.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-version: 3.2025064.1
  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-07-23 08:22:05 +02:00
dependabot[bot]
3f41588dc9 core: bump msgraph-sdk from 1.38.0 to 1.39.0 (#15744)
Bumps [msgraph-sdk](https://github.com/microsoftgraph/msgraph-sdk-python) from 1.38.0 to 1.39.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.38.0...v1.39.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 08:21:05 +02:00
dependabot[bot]
9caf08637e core: bump sentry-sdk from 2.33.1 to 2.33.2 (#15745)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.33.1 to 2.33.2.
- [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.33.1...2.33.2)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.33.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-07-23 08:19:41 +02:00
dependabot[bot]
3f2f5ba31a core: bump channels-redis from 4.2.1 to 4.3.0 (#15746)
Bumps [channels-redis](https://github.com/django/channels_redis) from 4.2.1 to 4.3.0.
- [Changelog](https://github.com/django/channels_redis/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels_redis/compare/4.2.1...4.3.0)

---
updated-dependencies:
- dependency-name: channels-redis
  dependency-version: 4.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-23 08:19:13 +02:00
dependabot[bot]
ca48a6de48 website: bump the build group in /website with 9 updates (#15742)
Bumps the build group in /website with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@rspack/binding-darwin-arm64](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack) | `1.4.8` | `1.4.9` |
| [@rspack/binding-linux-arm64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack) | `1.4.8` | `1.4.9` |
| [@rspack/binding-linux-x64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack) | `1.4.8` | `1.4.9` |
| [@swc/core-darwin-arm64](https://github.com/swc-project/swc) | `1.13.1` | `1.13.2` |
| [@swc/core-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.13.1` | `1.13.2` |
| [@swc/core-linux-x64-gnu](https://github.com/swc-project/swc) | `1.13.1` | `1.13.2` |
| [@swc/html-darwin-arm64](https://github.com/swc-project/swc) | `1.13.1` | `1.13.2` |
| [@swc/html-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.13.1` | `1.13.2` |
| [@swc/html-linux-x64-gnu](https://github.com/swc-project/swc) | `1.13.1` | `1.13.2` |


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

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

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

Updates `@swc/core-darwin-arm64` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-linux-arm64-gnu` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/core-linux-x64-gnu` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/html-darwin-arm64` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/html-linux-arm64-gnu` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

Updates `@swc/html-linux-x64-gnu` from 1.13.1 to 1.13.2
- [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.13.1...v1.13.2)

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-version: 1.4.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-version: 1.4.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-version: 1.4.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-version: 1.13.2
  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-07-23 08:17:29 +02:00
Vee Bäck
6c951efd61 website/integrations: Update Stripe docs (#15729)
website/docs: Update Stripe docs
2025-07-22 21:53:03 +01:00
Marc 'risson' Schmitt
6b5da70673 blueprints: add File tag (#15727)
Co-authored-by: Guillaume Chauveau <guillaumejchauveau.ops.gecu@outlook.com>
2025-07-22 20:09:25 +00:00
Teffen Ellis
32501266d5 web: Fix issue where base render method is not preferred. (#15726) 2025-07-22 10:44:39 -07:00
Michael Uray
5d6a2d27eb website/integrations: fix netbird integration (#15660)
* Update index.md

NETBIRD_AUTH_AUDIENCE was set to <Cour Client Secret> instead of <Your Client ID>

Added:
NETBIRD_MGMT_IDP="authentik"
NETBIRD_IDP_MGMT_CLIENT_ID="<PROVIDER_CLIENT_ID>"
NETBIRD_IDP_MGMT_EXTRA_USERNAME="Netbird"
NETBIRD_IDP_MGMT_EXTRA_PASSWORD="<SERVICE_ACCOUNT_PASSWORD>"

Signed-off-by: Michael Uray <michael.uray@gmail.com>

* Update index.md

Removed duplicates
NETBIRD_IDP_MGMT_EXTRA_USERNAME
NETBIRD_IDP_MGMT_EXTRA_PASSWORD
from pull request.

Signed-off-by: Michael Uray <michael.uray@gmail.com>

* Update website/integrations/networking/netbird/index.md

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

---------

Signed-off-by: Michael Uray <michael.uray@gmail.com>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-07-22 12:22:40 -05:00
dependabot[bot]
7b8426b292 web: bump @lit/reactive-element from 2.1.0 to 2.1.1 in /web (#15711)
---
updated-dependencies:
- dependency-name: "@lit/reactive-element"
  dependency-version: 2.1.1
  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-07-22 18:02:30 +02:00
Teffen Ellis
fd8d5952d5 web: a11y -- ak-form-group part 2: type clean up, Chrome warnings (#15721)
* web: Fix elements after replacement.

* web: Clarify type.

* web: Fix alignment, browser warnings about IDs.

* web: Clean up types.
2025-07-22 17:10:09 +02:00
authentik-automation[bot]
bb1e16a3f8 web: bump API Client version (#15724)
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-07-22 15:42:03 +02:00
dependabot[bot]
09a4f2c9b6 web: bump knip from 5.61.3 to 5.62.0 in /web (#15709)
Bumps [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) from 5.61.3 to 5.62.0.
- [Release notes](https://github.com/webpro-nl/knip/releases)
- [Changelog](https://github.com/webpro-nl/knip/blob/main/packages/knip/.release-it.json)
- [Commits](https://github.com/webpro-nl/knip/commits/5.62.0/packages/knip)

---
updated-dependencies:
- dependency-name: knip
  dependency-version: 5.62.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-07-22 15:40:18 +02:00
dependabot[bot]
ac2873e6f4 web: bump the eslint group across 2 directories with 3 updates (#15706)
Bumps the eslint group with 1 update in the /packages/eslint-config directory: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).
Bumps the eslint group with 1 update in the /web directory: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `typescript-eslint` from 8.37.0 to 8.38.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.38.0/packages/typescript-eslint)

Updates `@typescript-eslint/eslint-plugin` from 8.37.0 to 8.38.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.38.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.37.0 to 8.38.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.38.0/packages/parser)

Updates `typescript-eslint` from 8.37.0 to 8.38.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.38.0/packages/typescript-eslint)

Updates `@typescript-eslint/eslint-plugin` from 8.37.0 to 8.38.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.38.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.37.0 to 8.38.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.38.0/packages/parser)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.38.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.38.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-version: 8.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.38.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 15:40:07 +02:00
Jens L.
6d68844270 root: backport release 2025.6.4 (#15723)
release: 2025.6.4
2025-07-22 15:38:16 +02:00
dependabot[bot]
2a65579182 web: bump remark-mdx-frontmatter from 5.0.0 to 5.2.0 in /web (#15707)
Bumps [remark-mdx-frontmatter](https://github.com/remcohaszing/remark-mdx-frontmatter) from 5.0.0 to 5.2.0.
- [Release notes](https://github.com/remcohaszing/remark-mdx-frontmatter/releases)
- [Commits](https://github.com/remcohaszing/remark-mdx-frontmatter/compare/v5.0.0...v5.2.0)

---
updated-dependencies:
- dependency-name: remark-mdx-frontmatter
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 14:33:15 +02:00
dependabot[bot]
11203f79d1 web: bump @types/codemirror from 5.60.15 to 5.60.16 in /web (#15708)
Bumps [@types/codemirror](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/codemirror) from 5.60.15 to 5.60.16.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/codemirror)

---
updated-dependencies:
- dependency-name: "@types/codemirror"
  dependency-version: 5.60.16
  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-07-22 14:33:07 +02:00
dependabot[bot]
b670362168 web: bump @floating-ui/dom from 1.6.11 to 1.7.2 in /web (#15710)
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.6.11 to 1.7.2.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Changelog](https://github.com/floating-ui/floating-ui/blob/master/packages/dom/CHANGELOG.md)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.7.2/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-version: 1.7.2
  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-07-22 14:32:59 +02:00
dependabot[bot]
24ae1c8b03 web: bump vite-plugin-lit-css from 2.0.0 to 2.1.0 in /web (#15712)
---
updated-dependencies:
- dependency-name: vite-plugin-lit-css
  dependency-version: 2.1.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-07-22 14:32:44 +02:00
Jens L.
7a4c6b9b50 security: fix CVE-2025-53942 (#15719)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-22 14:21:05 +02:00
dependabot[bot]
f1684882c5 web: bump globals from 15.10.0 to 16.3.0 in /web (#15713)
---
updated-dependencies:
- dependency-name: globals
  dependency-version: 16.3.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 14:20:47 +02:00
dependabot[bot]
615cb4f9fb core: bump sentry-sdk from 2.33.0 to 2.33.1 (#15714)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.33.0 to 2.33.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.33.0...2.33.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.33.1
  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-07-22 14:20:34 +02:00
dependabot[bot]
bbfee74cd2 website: bump the build group in /website with 6 updates (#15673)
Bumps the build group in /website with 6 updates:

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


Updates `@swc/core-darwin-arm64` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-linux-arm64-gnu` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-linux-x64-gnu` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/html-darwin-arm64` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/html-linux-arm64-gnu` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/html-linux-x64-gnu` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-version: 1.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-version: 1.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-version: 1.13.1
  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-07-22 14:20:21 +02:00
Rahammetoela Toekiman
af2885ab12 Bitwarden integration requires a bitwarden subscription (#15692)
Bitwarden integration requires an subscription

Signed-off-by: Rahammetoela Toekiman <fusekai@outlook.com>
2025-07-22 09:47:17 +00:00
dependabot[bot]
29799e95ce web: bump form-data from 4.0.0 to 4.0.4 in /web (#15703)
Bumps [form-data](https://github.com/form-data/form-data) from 4.0.0 to 4.0.4.
- [Release notes](https://github.com/form-data/form-data/releases)
- [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md)
- [Commits](https://github.com/form-data/form-data/compare/v4.0.0...v4.0.4)

---
updated-dependencies:
- dependency-name: form-data
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 02:20:56 +02:00
authentik-automation[bot]
b6568f322b core, web: update translations (#15704)
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-07-22 02:20:45 +02:00
transifex-integration[bot]
d9bad736b5 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#15695)
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-07-22 00:35:17 +02:00
transifex-integration[bot]
1d57307891 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#15697)
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-07-22 00:35:00 +02:00
transifex-integration[bot]
be27635788 translate: Updates for file web/xliff/en.xlf in zh-Hans (#15698)
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-07-22 00:34:47 +02:00
Ken Sternberg
8373072654 web: remove mdx and fix references to @goauthentik/elements (#15694)
* web: Add InvalidationFlow to Radius Provider dialogues

## What

- Bugfix: adds the InvalidationFlow to the Radius Provider dialogues
  - Repairs: `{"invalidation_flow":["This field is required."]}` message, which was *not* propagated
    to the Notification.
- Nitpick: Pretties `?foo=${true}` expressions: `s/\?([^=]+)=\$\{true\}/\1/`

## Note

Yes, I know I'm going to have to do more magic when we harmonize the forms, and no, I didn't add the
Property Mappings to the wizard, and yes, I know I'm going to have pain with the *new* version of
the wizard. But this is a serious bug; you can't make Radius servers with *either* of the current
dialogues at the moment.

* This (temporary) change is needed to prevent the unit tests from failing.

\# What

\# Why

\# How

\# Designs

\# Test Steps

\# Other Notes

* Revert "This (temporary) change is needed to prevent the unit tests from failing."

This reverts commit dddde09be5.

* web: fix storybook references to 'elements', remove as much MDX as possible.

# WHAT

Remove all storybook references to '@goauthentik/elements' or '@goauthentik/web/elements'. Most of
these were in MDX, which we don't need anymore.

The ApplicationEmptyState element needed a bit of updated to be more compliant with our standards,
just to storybook it at all.

* Prettier had opinions.

* Replacing empty html call with 'nothing'

* Added pragmas to help VSCode users.
2025-07-21 13:30:04 -07:00
Tana M Berry
b6c05f6852 root: update Makefile with new commands for docs and integrations (#15689)
update commands for docs and integrations

Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-07-21 16:34:00 -03:00
Teffen Ellis
26766360d5 web: a11y -- ak-sidebar, ak-modal, cards (#15690)
* web: a11y -- ak-sidebar

* web: Fix paths, nesting. Allow for skipping.

* web: a11y Modal button.

* web: a11y -- alert, message

* web: Add utils.

* web: Fix types.

* web: Tidy types. Fix alignment.
2025-07-21 14:20:16 -04:00
Teffen Ellis
9d7c733024 web: a11y -- ak-form-group (#15688)
web: a11y <ak-form-group />
2025-07-21 14:19:53 -04:00
Dewi Roberts
caecf5961d website/docs: add notification rule expression policy examples (#15333)
* WIP

* Typo fix

* Added mention of new doc in notification rules doc

* Update website/docs/sys-mgmt/events/notifications.md

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

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
2025-07-21 16:32:41 +01:00
Dewi Roberts
4b211190b6 website/docs: add force password reset guide (#15654)
* Adds doc

* Improved code blocks

* Wording fix

* Move location and apply suggestions

* Typos

* Wording change

* Typo

* Wording improvements and typos

* Apply suggestions

* Apply suggestion from Tana

* Typo

* Update sidebar and fix relative link

* Prettier fix

* Link fix

* Added sidebar label
2025-07-21 16:31:52 +01:00
dependabot[bot]
2f22012f0f website: bump prettier-plugin-packagejson from 2.5.18 to 2.5.19 in /website (#15672)
website: bump prettier-plugin-packagejson in /website

Bumps [prettier-plugin-packagejson](https://github.com/matzkoh/prettier-plugin-packagejson) from 2.5.18 to 2.5.19.
- [Release notes](https://github.com/matzkoh/prettier-plugin-packagejson/releases)
- [Commits](https://github.com/matzkoh/prettier-plugin-packagejson/compare/v2.5.18...v2.5.19)

---
updated-dependencies:
- dependency-name: prettier-plugin-packagejson
  dependency-version: 2.5.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 17:31:23 +02:00
Teffen Ellis
10dffd8d13 website: Flesh out Makefile commands, usage. (#15576)
* website: Flesh out command behavior.

* restructure

* rearranged

---------

Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-07-21 10:29:58 -05:00
rattencreep
21a73fe58c website/integrations: fix duplicate guacamole section (#15684)
Update index.mdx

Removed doubled Self Signed Certificates section.

Signed-off-by: rattencreep <62957151+rattencreep@users.noreply.github.com>
2025-07-21 12:49:53 +01:00
dependabot[bot]
b0b915061e core: bump goauthentik.io/api/v3 from 3.2025063.5 to 3.2025063.6 (#15671)
---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-version: 3.2025063.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 13:37:38 +02:00
dependabot[bot]
6bcb758daa web: bump typedoc-plugin-markdown from 4.7.0 to 4.7.1 in /packages/esbuild-plugin-live-reload (#15681)
web: bump typedoc-plugin-markdown

Bumps [typedoc-plugin-markdown](https://github.com/typedoc2md/typedoc-plugin-markdown/tree/HEAD/packages/typedoc-plugin-markdown) from 4.7.0 to 4.7.1.
- [Release notes](https://github.com/typedoc2md/typedoc-plugin-markdown/releases)
- [Changelog](https://github.com/typedoc2md/typedoc-plugin-markdown/blob/main/packages/typedoc-plugin-markdown/CHANGELOG.md)
- [Commits](https://github.com/typedoc2md/typedoc-plugin-markdown/commits/typedoc-plugin-markdown@4.7.1/packages/typedoc-plugin-markdown)

---
updated-dependencies:
- dependency-name: typedoc-plugin-markdown
  dependency-version: 4.7.1
  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-07-21 13:36:32 +02:00
dependabot[bot]
b051c59ec4 web: bump the esbuild group across 2 directories with 4 updates (#15674)
Bumps the esbuild group with 1 update in the /packages/esbuild-plugin-live-reload directory: [esbuild](https://github.com/evanw/esbuild).
Bumps the esbuild group with 1 update in the /web directory: [esbuild](https://github.com/evanw/esbuild).


Updates `esbuild` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

Updates `@esbuild/darwin-arm64` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

Updates `@esbuild/linux-arm64` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

Updates `@esbuild/linux-x64` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

Updates `esbuild` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

Updates `@esbuild/darwin-arm64` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

Updates `@esbuild/linux-arm64` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

Updates `@esbuild/linux-x64` from 0.25.6 to 0.25.8
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.6...v0.25.8)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/darwin-arm64"
  dependency-version: 0.25.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-arm64"
  dependency-version: 0.25.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-x64"
  dependency-version: 0.25.8
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: esbuild
  dependency-version: 0.25.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/darwin-arm64"
  dependency-version: 0.25.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-arm64"
  dependency-version: 0.25.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-x64"
  dependency-version: 0.25.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 13:36:21 +02:00
dependabot[bot]
35df455e3a web: bump @types/node from 24.0.14 to 24.0.15 in /packages/prettier-config (#15676)
web: bump @types/node in /packages/prettier-config

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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.15
  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-07-21 13:35:58 +02:00
dependabot[bot]
eb19e53bf3 website: bump @types/node from 24.0.14 to 24.0.15 in /website (#15675)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.0.14 to 24.0.15.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.15
  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-07-21 13:35:50 +02:00
dependabot[bot]
3badf80295 web: bump @types/node from 24.0.14 to 24.0.15 in /packages/esbuild-plugin-live-reload (#15677)
web: bump @types/node in /packages/esbuild-plugin-live-reload

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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.15
  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-07-21 13:35:41 +02:00
dependabot[bot]
b038e479e2 web: bump prettier-plugin-packagejson from 2.5.18 to 2.5.19 in /packages/prettier-config (#15678)
web: bump prettier-plugin-packagejson in /packages/prettier-config

Bumps [prettier-plugin-packagejson](https://github.com/matzkoh/prettier-plugin-packagejson) from 2.5.18 to 2.5.19.
- [Release notes](https://github.com/matzkoh/prettier-plugin-packagejson/releases)
- [Commits](https://github.com/matzkoh/prettier-plugin-packagejson/compare/v2.5.18...v2.5.19)

---
updated-dependencies:
- dependency-name: prettier-plugin-packagejson
  dependency-version: 2.5.19
  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-07-21 13:35:31 +02:00
dependabot[bot]
faaf4842a5 web: bump chart.js and @types/chart.js in /web (#15679)
Bumps [chart.js](https://github.com/chartjs/Chart.js) and [@types/chart.js](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chart.js). These dependencies needed to be updated together.

Updates `chart.js` from 4.4.9 to 4.5.0
- [Release notes](https://github.com/chartjs/Chart.js/releases)
- [Commits](https://github.com/chartjs/Chart.js/compare/v4.4.9...v4.5.0)

Updates `@types/chart.js` from 2.9.41 to 4.0.1
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chart.js)

---
updated-dependencies:
- dependency-name: chart.js
  dependency-version: 4.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: "@types/chart.js"
  dependency-version: 4.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 13:35:17 +02:00
dependabot[bot]
89ef57c68d web: bump the swc group across 1 directory with 11 updates (#15680)
Bumps the swc group with 1 update in the /web directory: [@swc/core](https://github.com/swc-project/swc).


Updates `@swc/core` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-darwin-arm64` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-darwin-x64` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-linux-arm-gnueabihf` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-linux-arm64-gnu` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-linux-arm64-musl` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-linux-x64-gnu` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-linux-x64-musl` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-win32-arm64-msvc` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-win32-ia32-msvc` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

Updates `@swc/core-win32-x64-msvc` from 1.13.0 to 1.13.1
- [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.13.0...v1.13.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 13:34:53 +02:00
dependabot[bot]
c3515299d1 web: bump prettier-plugin-packagejson from 2.5.18 to 2.5.19 in /packages/esbuild-plugin-live-reload (#15682)
web: bump prettier-plugin-packagejson

Bumps [prettier-plugin-packagejson](https://github.com/matzkoh/prettier-plugin-packagejson) from 2.5.18 to 2.5.19.
- [Release notes](https://github.com/matzkoh/prettier-plugin-packagejson/releases)
- [Commits](https://github.com/matzkoh/prettier-plugin-packagejson/compare/v2.5.18...v2.5.19)

---
updated-dependencies:
- dependency-name: prettier-plugin-packagejson
  dependency-version: 2.5.19
  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-07-21 13:32:59 +02:00
dependabot[bot]
f8ff48fed9 web: bump @types/node from 22.15.19 to 24.0.15 in /web (#15683)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.15.19 to 24.0.15.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 13:32:41 +02:00
Dominic R
dcf40690e9 website/dev docs: FDE e2e: fix useless markdown lini (#15658)
It renders the same and was a mishap on my part when I copied the link in a previous pr

Signed-off-by: Dominic R <dominic@sdko.org>
2025-07-21 11:44:20 +01:00
Jens L.
4b37829f67 providers/radius: set message authenticator (#15635)
* core: fix flow planner checking against wrong user when creating recovery link

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

* validate incoming message authenticator

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-19 22:08:58 +02:00
dependabot[bot]
bf050e19b0 web: bump @eslint/plugin-kit from 0.3.1 to 0.3.3 in /packages/eslint-config (#15661) 2025-07-19 16:54:29 +02:00
Dewi Roberts
8eedfe5c4e website/docs: add e2e testing steps (#15656)
* Add e2e testing steps.

* Apply suggestion
2025-07-18 13:07:45 -05:00
Dewi Roberts
33f83bec46 website/docs: fix user ref typos (#15653)
Fixed typos
2025-07-18 13:05:51 -05:00
Teffen Ellis
b93a450b38 web: Update license mixing types to anticipate load state. (#15634)
web: Update types to anticipate load state.
2025-07-18 11:15:10 -04:00
dependabot[bot]
6c169ce6a6 web: bump on-headers and compression in /packages/docusaurus-config (#15638)
---
updated-dependencies:
- dependency-name: on-headers
  dependency-version: 1.1.0
  dependency-type: indirect
- dependency-name: compression
  dependency-version: 1.8.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 12:45:46 +02:00
dependabot[bot]
d53bb73c91 website: bump the build group in /website with 6 updates (#15640)
---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-version: 1.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-version: 1.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-version: 1.13.0
  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-07-18 12:45:43 +02:00
dependabot[bot]
a182d7671e core: bump github.com/grafana/pyroscope-go from 1.2.3 to 1.2.4 (#15641)
Bumps [github.com/grafana/pyroscope-go](https://github.com/grafana/pyroscope-go) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/grafana/pyroscope-go/releases)
- [Commits](https://github.com/grafana/pyroscope-go/compare/v1.2.3...v1.2.4)

---
updated-dependencies:
- dependency-name: github.com/grafana/pyroscope-go
  dependency-version: 1.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 12:45:40 +02:00
dependabot[bot]
9941cec71f web: bump @sentry/browser from 9.39.0 to 9.40.0 in /web in the sentry group across 1 directory (#15642)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 9.39.0 to 9.40.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/9.39.0...9.40.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 12:45:37 +02:00
dependabot[bot]
458344638f web: bump the swc group across 1 directory with 11 updates (#15643)
Bumps the swc group with 1 update in the /web directory: [@swc/core](https://github.com/swc-project/swc).


Updates `@swc/core` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-darwin-arm64` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-darwin-x64` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-linux-arm-gnueabihf` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-linux-arm64-gnu` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-linux-arm64-musl` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-linux-x64-gnu` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-linux-x64-musl` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-win32-arm64-msvc` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-win32-ia32-msvc` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

Updates `@swc/core-win32-x64-msvc` from 1.12.14 to 1.13.0
- [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.12.14...v1.13.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 12:45:34 +02:00
dependabot[bot]
11ffd672ca web: bump @lit/task from 1.0.2 to 1.0.3 in /web (#15644)
Bumps [@lit/task](https://github.com/lit/lit/tree/HEAD/packages/task) from 1.0.2 to 1.0.3.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/task/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit/task@1.0.3/packages/task)

---
updated-dependencies:
- dependency-name: "@lit/task"
  dependency-version: 1.0.3
  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-07-18 12:45:31 +02:00
dependabot[bot]
4ebbf5b097 web: bump core-js from 3.42.0 to 3.44.0 in /web (#15645)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.42.0 to 3.44.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.44.0/packages/core-js)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 12:45:28 +02:00
dependabot[bot]
1bf5688ec6 web: bump bootstrap from 4.6.2 to 5.3.7 in /web (#15646)
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 4.6.2 to 5.3.7.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v4.6.2...v5.3.7)

---
updated-dependencies:
- dependency-name: bootstrap
  dependency-version: 5.3.7
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 12:45:25 +02:00
dependabot[bot]
9f1e6b3ba4 web: bump codemirror from 6.0.1 to 6.0.2 in /web (#15647)
Bumps [codemirror](https://github.com/codemirror/basic-setup) from 6.0.1 to 6.0.2.
- [Changelog](https://github.com/codemirror/basic-setup/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/basic-setup/compare/6.0.1...6.0.2)

---
updated-dependencies:
- dependency-name: codemirror
  dependency-version: 6.0.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-07-18 12:45:22 +02:00
dependabot[bot]
93ec4b3c17 web: bump knip from 5.58.0 to 5.61.3 in /web (#15648)
Bumps [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) from 5.58.0 to 5.61.3.
- [Release notes](https://github.com/webpro-nl/knip/releases)
- [Changelog](https://github.com/webpro-nl/knip/blob/main/packages/knip/.release-it.json)
- [Commits](https://github.com/webpro-nl/knip/commits/5.61.3/packages/knip)

---
updated-dependencies:
- dependency-name: knip
  dependency-version: 5.61.3
  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-07-18 12:45:19 +02:00
dependabot[bot]
477fc11148 core: bump astral-sh/uv from 0.7.21 to 0.8.0 (#15649)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.7.21 to 0.8.0.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.7.21...0.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-18 12:45:17 +02:00
authentik-automation[bot]
4265e7b0af core, web: update translations (#15639)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-07-18 05:32:15 +02:00
Jens L.
41df11d5dc stages/authenticator_sms: allow custom message for twilio provider, pass request (#15629)
* stages/authenticator_sms: allow custom message for twilio provider, pass request

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

* remove old version

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

* Update web/src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts

Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Jens L. <jens@beryju.org>

* Update web/src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts

Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Jens L. <jens@beryju.org>

* redo headers

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

* Apply suggestions from code review

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

* format

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-07-18 01:21:23 +02:00
Fuad
f9fd1bbf09 website/integrations: fix typo in seafile doc (#15633)
Typo: fix OAUTH_PROVIDER_DOMAIN url

Signed-off-by: Fuad <26776550+fuad00@users.noreply.github.com>
2025-07-17 15:44:48 +00:00
Dominic R
3ba3b11a76 root: Ignore ./media for codespell (#15632)
Closes https://github.com/goauthentik/authentik/issues/15631

Signed-off-by: Dominic R <dominic@sdko.org>
2025-07-17 17:41:55 +02:00
Teffen Ellis
19e558e916 website: Prep for workspaces. Clean up shared deps. (#15602)
website: Prepare NPM Workspaces.
2025-07-17 10:06:05 -04:00
dependabot[bot]
e15fadfedd web: bump prettier-plugin-packagejson from 2.5.16 to 2.5.18 in /packages/prettier-config (#15615)
web: bump prettier-plugin-packagejson in /packages/prettier-config

Bumps [prettier-plugin-packagejson](https://github.com/matzkoh/prettier-plugin-packagejson) from 2.5.16 to 2.5.18.
- [Release notes](https://github.com/matzkoh/prettier-plugin-packagejson/releases)
- [Commits](https://github.com/matzkoh/prettier-plugin-packagejson/compare/v2.5.16...v2.5.18)

---
updated-dependencies:
- dependency-name: prettier-plugin-packagejson
  dependency-version: 2.5.18
  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-07-17 16:04:35 +02:00
dependabot[bot]
52854e61c7 web: bump @codemirror/theme-one-dark from 6.1.2 to 6.1.3 in /web (#15618)
Bumps [@codemirror/theme-one-dark](https://github.com/codemirror/theme-one-dark) from 6.1.2 to 6.1.3.
- [Changelog](https://github.com/codemirror/theme-one-dark/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/theme-one-dark/compare/6.1.2...6.1.3)

---
updated-dependencies:
- dependency-name: "@codemirror/theme-one-dark"
  dependency-version: 6.1.3
  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-07-17 15:25:09 +02:00
dependabot[bot]
53aa0113ca web: bump prettier-plugin-packagejson from 2.5.17 to 2.5.18 in /packages/esbuild-plugin-live-reload (#15614)
web: bump prettier-plugin-packagejson

Bumps [prettier-plugin-packagejson](https://github.com/matzkoh/prettier-plugin-packagejson) from 2.5.17 to 2.5.18.
- [Release notes](https://github.com/matzkoh/prettier-plugin-packagejson/releases)
- [Commits](https://github.com/matzkoh/prettier-plugin-packagejson/compare/v2.5.17...v2.5.18)

---
updated-dependencies:
- dependency-name: prettier-plugin-packagejson
  dependency-version: 2.5.18
  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-07-17 15:07:47 +02:00
dependabot[bot]
9f71face62 web: bump @types/node from 24.0.10 to 24.0.14 in /packages/esbuild-plugin-live-reload (#15613)
web: bump @types/node in /packages/esbuild-plugin-live-reload

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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.14
  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-07-17 15:07:41 +02:00
dependabot[bot]
2fadefb5b4 web: bump @types/node from 24.0.4 to 24.0.14 in /packages/prettier-config (#15616)
web: bump @types/node in /packages/prettier-config

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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.14
  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-07-17 15:07:22 +02:00
dependabot[bot]
23e92bceae web: bump @types/dompurify from 3.0.5 to 3.2.0 in /web (#15617)
Bumps [@types/dompurify](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/dompurify) from 3.0.5 to 3.2.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/dompurify)

---
updated-dependencies:
- dependency-name: "@types/dompurify"
  dependency-version: 3.2.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-07-17 15:07:14 +02:00
dependabot[bot]
1ff2eea20a web: bump @codemirror/legacy-modes from 6.4.1 to 6.5.1 in /web (#15619)
Bumps [@codemirror/legacy-modes](https://github.com/codemirror/legacy-modes) from 6.4.1 to 6.5.1.
- [Changelog](https://github.com/codemirror/legacy-modes/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/legacy-modes/compare/6.4.1...6.5.1)

---
updated-dependencies:
- dependency-name: "@codemirror/legacy-modes"
  dependency-version: 6.5.1
  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-07-17 15:07:01 +02:00
dependabot[bot]
abcd2179bf web: bump mermaid from 11.6.0 to 11.9.0 in /web (#15620)
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 11.6.0 to 11.9.0.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/commits)

---
updated-dependencies:
- dependency-name: mermaid
  dependency-version: 11.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-17 15:06:52 +02:00
dependabot[bot]
6a4b5850a0 web: bump @types/node from 22.15.19 to 24.0.14 in /web (#15621)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.15.19 to 24.0.14.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-17 15:06:36 +02:00
dependabot[bot]
821c8c36cd lifecycle/aws: bump aws-cdk from 2.1020.2 to 2.1021.0 in /lifecycle/aws (#15622)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1020.2 to 2.1021.0.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1021.0/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-version: 2.1021.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-07-17 15:06:19 +02:00
dependabot[bot]
8838efe3c0 core: bump msgraph-sdk from 1.37.0 to 1.38.0 (#15624)
Bumps [msgraph-sdk](https://github.com/microsoftgraph/msgraph-sdk-python) from 1.37.0 to 1.38.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.37.0...v1.38.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-17 15:06:07 +02:00
transifex-integration[bot]
433a4a3037 translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#15627)
Translate locale/en/LC_MESSAGES/django.po in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-07-17 15:05:15 +02:00
transifex-integration[bot]
2d69a67e9d translate: Updates for file web/xliff/en.xlf in de (#15628)
Translate web/xliff/en.xlf in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-07-17 15:04:53 +02:00
authentik-automation[bot]
1294cc64e8 core, web: update translations (#15612) 2025-07-17 03:00:00 +02:00
Jens L.
910326a05a providers/oauth2: Add cause to debug issues and better tests (#15057)
* fix incorrect tests/add more

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

* add cause for oauth authorization errors

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

* include request_id in token response

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

* rework device endpoints

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

* fix some stuff

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

* fix tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-16 21:30:21 +02:00
Marcelo Elizeche Landó
9257b3e570 core: bump aiohttp from 3.12.13 to v3.12.14 (#15603) 2025-07-16 20:32:21 +02:00
Marcelo Elizeche Landó
cdd18a7e5a core: bump azure-identity from 1.23.0 to v1.23.1 (#15605) 2025-07-16 20:32:19 +02:00
Marcelo Elizeche Landó
88bea46648 core: bump boto3 from 1.39.3 to v1.39.7 (#15606) 2025-07-16 20:32:16 +02:00
Marcelo Elizeche Landó
295090a80b core: bump certifi from 2025.6.15 to v2025.7.14 (#15607) 2025-07-16 20:32:13 +02:00
Marcelo Elizeche Landó
bff607a5c3 core: bump microsoft-kiota-authentication-azure from 1.9.3 to v1.9.4 (#15608) 2025-07-16 20:32:10 +02:00
Marcelo Elizeche Landó
bfb2fb4fcf core: bump microsoft-kiota-http from 1.9.3 to v1.9.4 (#15609) 2025-07-16 20:32:06 +02:00
Marcelo Elizeche Landó
93015b0fce core: bump opentelemetry-api from 1.34.1 to v1.35.0 (#15610) 2025-07-16 20:32:03 +02:00
Marcelo Elizeche Landó
9b6c0d3f1a core: bump orjson from 3.10.18 to v3.11.0 (#15611) 2025-07-16 20:32:00 +02:00
Marcelo Elizeche Landó
66e95ddb20 core: bump asgiref from 3.9.0 to v3.9.1 (#15604) 2025-07-16 20:21:08 +02:00
dependabot[bot]
c5d8524a7d web: bump @types/react-dom from 19.1.5 to 19.1.6 in /packages/docusaurus-config (#15592)
web: bump @types/react-dom in /packages/docusaurus-config

---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-version: 19.1.6
  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-07-16 18:08:28 +02:00
dependabot[bot]
a4761064c2 web: bump @sentry/browser from 9.38.0 to 9.39.0 in /web in the sentry group across 1 directory (#15586)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 9.38.0 to 9.39.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/9.39.0/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/9.38.0...9.39.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-16 18:08:21 +02:00
dependabot[bot]
b0de8bf71f web: bump @types/react from 19.1.6 to 19.1.8 in /packages/docusaurus-config (#15593)
web: bump @types/react in /packages/docusaurus-config

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-version: 19.1.8
  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-07-16 18:08:13 +02:00
Jens L.
32100fd3b9 events: improve error formatting in events (#15187)
* events: improve error formatting in events

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-07-16 17:22:54 +02:00
dependabot[bot]
4815e97162 web: bump @types/react-dom from 19.1.5 to 19.1.6 in /web (#15596)
---
updated-dependencies:
- dependency-name: "@types/react-dom"
  dependency-version: 19.1.6
  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-07-16 17:20:32 +02:00
dependabot[bot]
dee99c38bb web: bump prettier from 3.5.3 to 3.6.2 in /packages/docusaurus-config (#15594)
---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.6.2
  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-07-16 17:20:23 +02:00
dependabot[bot]
a024056b62 web: bump prettier from 3.6.1 to 3.6.2 in /packages/prettier-config (#15595)
---
updated-dependencies:
- dependency-name: prettier
  dependency-version: 3.6.2
  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-07-16 17:20:01 +02:00
authentik-automation[bot]
a8dc21b707 core, web: update translations (#15580)
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-07-16 16:49:51 +02:00
dependabot[bot]
7ccda743df web: bump the storybook group across 1 directory with 5 updates (#15587)
Bumps the storybook group with 4 updates in the /web directory: [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/docs), [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links), [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) and [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite).


Updates `@storybook/addon-docs` from 9.0.16 to 9.0.17
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.17/code/addons/docs)

Updates `@storybook/addon-links` from 9.0.16 to 9.0.17
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.17/code/addons/links)

Updates `@storybook/web-components` from 9.0.16 to 9.0.17
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.17/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 9.0.16 to 9.0.17
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.17/code/frameworks/web-components-vite)

Updates `storybook` from 9.0.16 to 9.0.17
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.0.17/code/core)

---
updated-dependencies:
- dependency-name: "@storybook/addon-docs"
  dependency-version: 9.0.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-version: 9.0.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-version: 9.0.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-version: 9.0.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-version: 9.0.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-16 16:49:31 +02:00
dependabot[bot]
0c795dd077 core: bump github.com/golang-jwt/jwt/v5 from 5.2.2 to 5.2.3 (#15582)
Bumps [github.com/golang-jwt/jwt/v5](https://github.com/golang-jwt/jwt) from 5.2.2 to 5.2.3.
- [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.2...v5.2.3)

---
updated-dependencies:
- dependency-name: github.com/golang-jwt/jwt/v5
  dependency-version: 5.2.3
  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-07-16 16:19:53 +02:00
dependabot[bot]
5df9ed3582 website: bump the build group in /website with 3 updates (#15583)
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.4.6 to 1.4.8
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.4.8/packages/rspack)

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

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

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-version: 1.4.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-version: 1.4.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-version: 1.4.8
  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-07-16 16:19:50 +02:00
dependabot[bot]
a47b4934a5 website: bump @types/node from 24.0.13 to 24.0.14 in /website (#15584)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.0.13 to 24.0.14.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.14
  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-07-16 16:19:47 +02:00
dependabot[bot]
338a6e74f4 core: bump sentry-sdk from 2.32.0 to 2.33.0 (#15585)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.32.0 to 2.33.0.
- [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.32.0...2.33.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-16 16:19:44 +02:00
dependabot[bot]
8897af1048 web: bump the esbuild group across 2 directories with 5 updates (#15588)
Bumps the esbuild group with 1 update in the /packages/esbuild-plugin-live-reload directory: [esbuild](https://github.com/evanw/esbuild).
Bumps the esbuild group with 2 updates in the /web directory: [esbuild](https://github.com/evanw/esbuild) and [esbuild-plugins-node-modules-polyfill](https://github.com/imranbarbhuiya/esbuild-plugins-node-modules-polyfill).


Updates `esbuild` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

Updates `@esbuild/darwin-arm64` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

Updates `@esbuild/linux-arm64` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

Updates `@esbuild/linux-x64` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

Updates `esbuild` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

Updates `esbuild-plugins-node-modules-polyfill` from 1.7.0 to 1.7.1
- [Release notes](https://github.com/imranbarbhuiya/esbuild-plugins-node-modules-polyfill/releases)
- [Changelog](https://github.com/imranbarbhuiya/esbuild-plugins-node-modules-polyfill/blob/main/CHANGELOG.md)
- [Commits](https://github.com/imranbarbhuiya/esbuild-plugins-node-modules-polyfill/compare/v1.7.0...v1.7.1)

Updates `@esbuild/darwin-arm64` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

Updates `@esbuild/linux-arm64` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

Updates `@esbuild/linux-x64` from 0.25.5 to 0.25.6
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.5...v0.25.6)

---
updated-dependencies:
- dependency-name: esbuild
  dependency-version: 0.25.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/darwin-arm64"
  dependency-version: 0.25.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-arm64"
  dependency-version: 0.25.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-x64"
  dependency-version: 0.25.6
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: esbuild
  dependency-version: 0.25.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: esbuild-plugins-node-modules-polyfill
  dependency-version: 1.7.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/darwin-arm64"
  dependency-version: 0.25.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-arm64"
  dependency-version: 0.25.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
- dependency-name: "@esbuild/linux-x64"
  dependency-version: 0.25.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: esbuild
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-16 16:19:39 +02:00
dependabot[bot]
56ec3f7def web: bump the rollup group across 1 directory with 5 updates (#15589)
---
updated-dependencies:
- dependency-name: "@rollup/rollup-darwin-arm64"
  dependency-version: 4.45.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-arm64-gnu"
  dependency-version: 4.45.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-x64-gnu"
  dependency-version: 4.45.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rollup
- dependency-name: "@rollup/plugin-commonjs"
  dependency-version: 28.0.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: rollup
  dependency-version: 4.45.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: rollup
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-16 16:19:36 +02:00
dependabot[bot]
53fd893d91 web: bump the swc group across 1 directory with 12 updates (#15590)
---
updated-dependencies:
- dependency-name: "@swc/cli"
  dependency-version: 0.7.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: swc
- dependency-name: "@swc/core"
  dependency-version: 1.12.14
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-darwin-x64"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm-gnueabihf"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-arm64-musl"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-linux-x64-musl"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-arm64-msvc"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-ia32-msvc"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
- dependency-name: "@swc/core-win32-x64-msvc"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: swc
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-16 16:19:33 +02:00
dependabot[bot]
f7d9a8cafe web: bump @types/react from 19.1.5 to 19.1.8 in /web (#15597)
---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-version: 19.1.8
  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-07-16 16:17:31 +02:00
Jens L.
f97c1071f3 website/integrations: re-add sitemap (#15600)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-16 15:24:36 +02:00
Teffen Ellis
4da1115a7c web: Storybook v9 (#15550)
* web: Update Storybook. Clean up theme styles.

* web: Ignore Storybook output.
2025-07-16 04:29:01 +00:00
Jens L.
63b1ccd4c3 enterprise/audit: fix diff with update_fields (#15574)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-16 00:07:51 +02:00
Jens L.
63aa7f4684 enterprise: fix frontend considering license valid when it isnt (#15578)
* web: fix mis-matched license state check between backend and frontend

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

* make license key unique

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-15 22:36:57 +02:00
Teffen Ellis
d997930b60 website: Prep for 3.8 path resolution. (#15575) 2025-07-15 19:09:40 +02:00
Jens L.
a088a62981 stages/email: only update is_active on user to not overwrite external changes (#15508)
* stages/email: only update is_active on user to not overwrite external changes

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

* respect update_fields for diff

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-15 16:43:41 +02:00
Teffen Ellis
118e05f256 website: Update commands. (#15561) 2025-07-15 16:36:20 +02:00
dependabot[bot]
b30500094f website: bump the eslint group in /website with 3 updates (#15565)
Bumps the eslint group in /website with 3 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@typescript-eslint/eslint-plugin` from 8.36.0 to 8.37.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.37.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.36.0 to 8.37.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.37.0/packages/parser)

Updates `typescript-eslint` from 8.36.0 to 8.37.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.37.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-version: 8.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-15 16:32:41 +02:00
Marcelo Elizeche Landó
21af51ba59 website/docs: Fix typo in matrix documentation (#15558)
Fix typo in matrix documentation
2025-07-15 07:35:11 -05:00
authentik-automation[bot]
87da0497e0 core, web: update translations (#15560)
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-07-15 14:20:48 +02:00
dependabot[bot]
87317d6e7f core: bump goauthentik.io/api/v3 from 3.2025063.4 to 3.2025063.5 (#15564)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025063.4 to 3.2025063.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.2025063.4...v3.2025063.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-15 14:20:39 +02:00
authentik-automation[bot]
071305da18 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#15563)
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-07-15 13:39:47 +02:00
dependabot[bot]
1dc8ed5e55 web: bump the eslint group across 2 directories with 3 updates (#15566)
---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.37.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.37.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.37.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-version: 8.37.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.37.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.37.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-15 13:37:16 +02:00
dependabot[bot]
dc8dee985f core: bump astral-sh/uv from 0.7.20 to 0.7.21 (#15567)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.7.20 to 0.7.21.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.7.20...0.7.21)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.7.21
  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-07-15 13:37:06 +02:00
dependabot[bot]
2b20b06baa website: bump the build group in /website with 6 updates (#15568)
Bumps the build group in /website with 6 updates:

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


Updates `@swc/core-darwin-arm64` from 1.12.11 to 1.12.14
- [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.12.11...v1.12.14)

Updates `@swc/core-linux-arm64-gnu` from 1.12.11 to 1.12.14
- [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.12.11...v1.12.14)

Updates `@swc/core-linux-x64-gnu` from 1.12.11 to 1.12.14
- [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.12.11...v1.12.14)

Updates `@swc/html-darwin-arm64` from 1.12.11 to 1.12.14
- [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.12.11...v1.12.14)

Updates `@swc/html-linux-arm64-gnu` from 1.12.11 to 1.12.14
- [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.12.11...v1.12.14)

Updates `@swc/html-linux-x64-gnu` from 1.12.11 to 1.12.14
- [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.12.11...v1.12.14)

---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-version: 1.12.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-version: 1.12.14
  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-07-15 13:36:57 +02:00
Teffen Ellis
6cab1f85e4 web: Fix intermediate wizard steps propagating refresh events to parent (#15548)
* web: Fix issue where wizard steps with refresh events trigger parent rerenders.

* Apply suggestions from code review. Tidy.

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

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
2025-07-15 02:28:57 +02:00
Tana M Berry
f836c38b18 website/docs: added enterprise label to new Logging docs (#15556)
added enterprise label

Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-07-14 18:18:14 -03:00
Tana M Berry
07e373e505 website/docs: fix a typo in SSF docs (#15554)
website/docs/add-secure-apps/providers/ssf/index.md

Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-07-14 11:36:16 -05:00
Teffen Ellis
e361d38978 web: Disable autocomplete. (#15551) 2025-07-14 15:49:17 +00:00
Teffen Ellis
3ba1691db6 web: Fix missing TypeScript dependency when running make for first time. (#15502)
* web: Fix missing TypeScript dependency when running make for first time.

Co-authored-by: Connor Peshek <connor@connorpeshek.me>

* Update Makefile

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Connor Peshek <connor@connorpeshek.me>
Co-authored-by: Jens L. <jens@goauthentik.io>
2025-07-14 11:40:00 -04:00
Tana M Berry
7c2987ea32 website/docs: add use case, move diagram, link to ABM (#15491)
* add use case, move diagram, link to ABM

* change word to match

* fix UI

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

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

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-07-14 10:08:49 -05:00
authentik-automation[bot]
4ca88caf07 web: bump API Client version (#15547)
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-07-14 14:08:52 +00:00
Jens L.
6c939341b0 sources/oauth: add entra ID source and move logic over (#15538)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-14 15:44:07 +02:00
dependabot[bot]
4142584788 core: bump goauthentik.io/api/v3 from 3.2025063.3 to 3.2025063.4 (#15541)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025063.3 to 3.2025063.4.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Changelog](https://github.com/goauthentik/client-go/blob/main/model_version_history.go)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2025063.3...v3.2025063.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 12:43:49 +02:00
dependabot[bot]
f6fbafd280 core: bump github.com/grafana/pyroscope-go from 1.2.2 to 1.2.3 (#15540)
Bumps [github.com/grafana/pyroscope-go](https://github.com/grafana/pyroscope-go) from 1.2.2 to 1.2.3.
- [Release notes](https://github.com/grafana/pyroscope-go/releases)
- [Commits](https://github.com/grafana/pyroscope-go/compare/v1.2.2...v1.2.3)

---
updated-dependencies:
- dependency-name: github.com/grafana/pyroscope-go
  dependency-version: 1.2.3
  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-07-14 12:43:00 +02:00
dependabot[bot]
7c9555bee8 website: bump the eslint group in /website with 2 updates (#15542)
Bumps the eslint group in /website with 2 updates: [@eslint/js](https://github.com/eslint/eslint/tree/HEAD/packages/js) and [eslint](https://github.com/eslint/eslint).


Updates `@eslint/js` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.31.0/packages/js)

Updates `eslint` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.30.1...v9.31.0)

---
updated-dependencies:
- dependency-name: "@eslint/js"
  dependency-version: 9.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint
  dependency-version: 9.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 12:42:49 +02:00
dependabot[bot]
82cd64dfe7 website: bump @types/node from 24.0.12 to 24.0.13 in /website (#15544)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.0.12 to 24.0.13.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.13
  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-07-14 12:42:37 +02:00
dependabot[bot]
28f0b48e33 web: bump @sentry/browser from 9.37.0 to 9.38.0 in /web in the sentry group across 1 directory (#15545)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 9.37.0 to 9.38.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/9.37.0...9.38.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 12:42:25 +02:00
dependabot[bot]
38c02dc490 web: bump the eslint group across 3 directories with 2 updates (#15546)
Bumps the eslint group with 1 update in the /packages/eslint-config directory: [eslint](https://github.com/eslint/eslint).
Bumps the eslint group with 1 update in the /packages/prettier-config directory: [eslint](https://github.com/eslint/eslint).
Bumps the eslint group with 1 update in the /web directory: [eslint](https://github.com/eslint/eslint).


Updates `eslint` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.30.1...v9.31.0)

Updates `@eslint/js` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.31.0/packages/js)

Updates `eslint` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.30.1...v9.31.0)

Updates `@eslint/js` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.31.0/packages/js)

Updates `eslint` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.30.1...v9.31.0)

Updates `@eslint/js` from 9.30.1 to 9.31.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/commits/v9.31.0/packages/js)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@eslint/js"
  dependency-version: 9.31.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint
  dependency-version: 9.31.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@eslint/js"
  dependency-version: 9.31.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint
  dependency-version: 9.31.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@eslint/js"
  dependency-version: 9.31.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 12:42:13 +02:00
Pascal Weidenhammer
79505969db website/docs: Use Django case insensitive filter for unique emails (#15539)
* Use Django case insensitive filter for unique emails

https://docs.djangoproject.com/en/dev/ref/models/querysets/#std-fieldlookup-iexact

* use ak_user_by

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-07-14 10:35:26 +00:00
dependabot[bot]
9870888456 web: bump brace-expansion from 1.1.11 to 1.1.12 in /packages/eslint-config (#15536)
web: bump brace-expansion in /packages/eslint-config

Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.11 to 1.1.12.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](https://github.com/juliangruber/brace-expansion/compare/1.1.11...v1.1.12)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 1.1.12
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-14 01:05:03 +02:00
authentik-automation[bot]
5c06e1920e web: bump API Client version (#15537)
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-07-13 23:02:28 +00:00
Jens L.
1506ad8aa4 ci: fix NPM publish again (#15535)
* ci: npm apparently needs a tag flag now for some reason...? like what the hell is a dist-tag even

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

* revert frontend styling

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

* fix autosubmit duplicate label

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-14 00:40:24 +02:00
Jens L.
21b6204c90 sources/SCIM: Full Patch support for User and Group (#15485)
* add patch support

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

* fix group members

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

* add tests for group adding

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

* format, more tests

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

* mark patch as supported

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

* fix

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

* support excludedAttributes

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

* allow updating externalId

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

* more patcher tests

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

* let the ai do things?

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

* format

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

* fix ai generated code

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

* fix tests

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

* remove the old code

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

* add fix to handle URN format

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

* tests pass

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

* improve 404 handling for non uuid IDs

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

* better None path handling

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

* split code to make it more readable

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

* handle patch operation with Path None and value containing urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:organization

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

* fix tests that were not correct

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

* fix external ID change - the bad way

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

* add separate field for externalId

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

* more schema fixes

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

* fix replace for manager

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

* save last_updated

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

* more unittests

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

* more tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-14 00:02:15 +02:00
transifex-integration[bot]
05621735cb translate: Updates for file locale/en/LC_MESSAGES/django.po in es (#15534)
Translate locale/en/LC_MESSAGES/django.po in es

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-07-13 19:57:54 +00:00
authentik-automation[bot]
f9ffd35ab8 core, web: update translations (#15532)
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-07-13 21:39:57 +02:00
transifex-integration[bot]
c3ded3a835 translate: Updates for file web/xliff/en.xlf in it (#15530)
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-07-12 17:50:47 +02:00
transifex-integration[bot]
7629c22050 translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#15529)
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-07-12 17:49:33 +02:00
Jens L.
29a66410fd stages/prompt: fix list policy for prompt validation failing with multiple policies (#15522)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-11 21:59:45 +02:00
dependabot[bot]
f147d40c5f website: bump the build group in /website with 3 updates (#15515)
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.4.5 to 1.4.6
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.4.6/packages/rspack)

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

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

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-version: 1.4.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-version: 1.4.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-version: 1.4.6
  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-07-11 18:37:04 +02:00
dependabot[bot]
15b556c1be website: bump @reduxjs/toolkit from 1.9.7 to 2.8.2 in /website (#15516)
Bumps [@reduxjs/toolkit](https://github.com/reduxjs/redux-toolkit) from 1.9.7 to 2.8.2.
- [Release notes](https://github.com/reduxjs/redux-toolkit/releases)
- [Commits](https://github.com/reduxjs/redux-toolkit/compare/v1.9.7...v2.8.2)

---
updated-dependencies:
- dependency-name: "@reduxjs/toolkit"
  dependency-version: 2.8.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 15:48:49 +02:00
dependabot[bot]
522e8a26a2 core: bump twilio from 9.6.4 to 9.6.5 (#15517)
Bumps [twilio](https://github.com/twilio/twilio-python) from 9.6.4 to 9.6.5.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/9.6.4...9.6.5)

---
updated-dependencies:
- dependency-name: twilio
  dependency-version: 9.6.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 15:48:32 +02:00
dependabot[bot]
403d762f65 core: bump xmlsec from 1.3.15 to 1.3.16 (#15518)
Bumps [xmlsec](https://github.com/mehcode/python-xmlsec) from 1.3.15 to 1.3.16.
- [Release notes](https://github.com/mehcode/python-xmlsec/releases)
- [Commits](https://github.com/mehcode/python-xmlsec/compare/1.3.15...1.3.16)

---
updated-dependencies:
- dependency-name: xmlsec
  dependency-version: 1.3.16
  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-07-11 15:48:07 +02:00
dependabot[bot]
cbc65ffd74 web: bump @sentry/browser from 9.36.0 to 9.37.0 in /web in the sentry group across 1 directory (#15519)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 9.36.0 to 9.37.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/9.36.0...9.37.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 15:47:25 +02:00
authentik-automation[bot]
9a9bafdfb4 core, web: update translations (#15514) 2025-07-11 02:52:59 +02:00
Teffen Ellis
198d2a1a8a web: Clean up file methods. (#15479) 2025-07-10 22:47:22 +00:00
Tana M Berry
239edace16 website/docs: add noun for SSO (#15509)
* add noun for SSO

* change to use term platform

---------

Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-07-10 17:32:02 -05:00
Teffen Ellis
370d5ff0c0 web: Fix form captcha submission (#15482)
* web: Validate Captcha during form submission.

web: Clean up loading state. Remove outdated.

Flesh out story. Adjust centering.

* web: Fix issue where setting password warns of missing username.

* web: Fix issue where private method triggers runtime error.
2025-07-10 22:23:34 +00:00
Teffen Ellis
635b09621b web: Form submission (#15477)
* web: Clean up usage of method.

* web: Clean up form submission behavior.

* web: Normalize use of form submission listener.
2025-07-10 21:35:59 +00:00
Teffen Ellis
4335498ac5 web: Import organization (#14696)
* web: Clean up locale.

* web: Clean ambiguous imports.

* web: Clean up entrypoint imports.

* web: Format imports.

* web: Normalize extensions.

* web: Tidy order.

* web: Remove TS aliases.
2025-07-10 20:36:56 +00:00
Teffen Ellis
72af009de8 website/docs: Improved Version Picker. (#14404)
* website: Flesh out version picker. Port 3.8 theme.

* website: Update Dockerfile to include compose.

* website: Flesh out branch override. Tidy list items.
2025-07-10 15:36:48 -04:00
Teffen Ellis
3a07d5d829 web: Consistent use of static styles (#15510)
* web: Initial style clean up.

* web: Clean up type 2 styles.

* web: Clean up type 3 styles.

* web: Add Prettier formatter.
2025-07-10 19:35:58 +00:00
Marc 'risson' Schmitt
7122891f0f providers/proxy: fix ingress-nginx proxy buffer size annotations (#15506)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-07-10 15:06:35 +00:00
Dominic R
c32d6cc75e website/docs: troubleshooting: Fix variable for postgres database in k8s (#15503) 2025-07-10 16:41:27 +02:00
dependabot[bot]
eaf6be74f3 web: bump @sentry/browser from 9.35.0 to 9.36.0 in /web in the sentry group across 1 directory (#15492)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 9.35.0 to 9.36.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/9.35.0...9.36.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 15:08:50 +02:00
dependabot[bot]
c35650afbd core: bump golang.org/x/sync from 0.15.0 to 0.16.0 (#15493)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 15:06:15 +02:00
dependabot[bot]
a1f9ff8b7d core: bump maxmind/geoipupdate from v7.1.0 to v7.1.1 (#15495)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 13:46:49 +02:00
dependabot[bot]
962f7513ba core: bump astral-sh/uv from 0.7.19 to 0.7.20 (#15496)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-10 13:46:32 +02:00
Teffen Ellis
0ec5ea69ef Docusaurus 3.8 prep integrations (#15483)
* website: Port gitignore.

* website: Flesh out Integrations clean up.
2025-07-09 16:41:11 -04:00
Teffen Ellis
d8a3098329 web: Fix dangling div. (#15478) 2025-07-09 22:00:18 +02:00
dependabot[bot]
80ad97b28d core: bump google-api-python-client from 2.175.0 to 2.176.0 (#15471)
---
updated-dependencies:
- dependency-name: google-api-python-client
  dependency-version: 2.176.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-09 11:39:25 +02:00
authentik-automation[bot]
cd98767dbc core, web: update translations (#15468)
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-07-09 11:28:51 +02:00
dependabot[bot]
30f09e8c45 website: bump the build group in /website with 3 updates (#15469)
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.4.4 to 1.4.5
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.4.5/packages/rspack)

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

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

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-version: 1.4.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-version: 1.4.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-version: 1.4.5
  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-07-09 11:28:48 +02:00
dependabot[bot]
154bcb58a6 website: bump @types/node from 24.0.10 to 24.0.12 in /website (#15470)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.0.10 to 24.0.12.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-09 11:28:46 +02:00
dependabot[bot]
597945edf1 core: bump msgraph-sdk from 1.36.0 to 1.37.0 (#15472)
---
updated-dependencies:
- dependency-name: msgraph-sdk
  dependency-version: 1.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-09 11:28:41 +02:00
Jens L.
38d6e39fe0 web/flows: more padding fixes (#15467)
fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-09 11:27:58 +02:00
Jens L.
1a6065f72a events: fix ak_client_ip not set in notification rule policy context (#15464)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-08 23:53:36 +02:00
Tana M Berry
d07e0f015d website/docs: edits to latest Events docs (#15457)
* edits to latest Events docs

* Optimised images with calibre/image-actions

---------

Co-authored-by: Tana M Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-07-08 09:53:30 -05:00
dependabot[bot]
7f931917fa website: bump the eslint group in /website with 3 updates (#15452)
Bumps the eslint group in /website with 3 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) and [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `@typescript-eslint/eslint-plugin` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/parser)

Updates `typescript-eslint` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-version: 8.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 15:29:18 +02:00
dechen-authentik
d7fb684292 website/docs: fix small typos (#15403)
* website/docs/developer-docs: use sentence case for titles

* website/docs/developer-docs: use consistent form when referring to the frontend

* website/docs/developer-docs: fix more instances of sentence casing

* Update web/package.json

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

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

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

* Apply suggestions from code review

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

* Update website/docs/developer-docs/index.md

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

* Update website/docs/developer-docs/index.md

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

---------

Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-07-08 07:52:57 -05:00
Marc 'risson' Schmitt
bd0fa7be98 root: monitoring: force db connection reload before healthcheck (#9970) 2025-07-08 14:52:31 +02:00
Marcelo Elizeche Landó
2907808a7e core: bump microsoft-kiota-serialization-form from 1.9.3 to v1.9.4 (#15441) 2025-07-08 13:12:29 +02:00
Marcelo Elizeche Landó
c53016b2e5 core: bump multidict from 6.5.1 to v6.6.3 (#15446) 2025-07-08 13:11:38 +02:00
Marcelo Elizeche Landó
4479587baa core: bump aiosignal from 1.3.2 to v1.4.0 (#15435) 2025-07-08 13:10:10 +02:00
Marcelo Elizeche Landó
08d24a1871 core: bump asgiref from 3.8.1 to v3.9.0 (#15436) 2025-07-08 13:09:59 +02:00
Marcelo Elizeche Landó
42ea8bb3ed core: bump microsoft-kiota-serialization-json from 1.9.3 to v1.9.4 (#15442) 2025-07-08 13:09:46 +02:00
Marcelo Elizeche Landó
c9a07fa18d core: bump azure-core from 1.34.0 to v1.35.0 (#15437) 2025-07-08 13:09:22 +02:00
Marcelo Elizeche Landó
4130446cbc core: bump microsoft-kiota-serialization-multipart from 1.9.3 to v1.9.4 (#15443) 2025-07-08 13:09:12 +02:00
dependabot[bot]
b4aecbd782 web: bump the eslint group across 2 directories with 3 updates (#15450)
Bumps the eslint group with 1 update in the /packages/eslint-config directory: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).
Bumps the eslint group with 1 update in the /web directory: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `typescript-eslint` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/typescript-eslint)

Updates `@typescript-eslint/eslint-plugin` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/parser)

Updates `typescript-eslint` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/typescript-eslint)

Updates `@typescript-eslint/eslint-plugin` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.35.1 to 8.36.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.36.0/packages/parser)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.36.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.36.0
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: typescript-eslint
  dependency-version: 8.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.36.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 13:09:02 +02:00
Marcelo Elizeche Landó
981d2af109 core: bump microsoft-kiota-serialization-text from 1.9.3 to v1.9.4 (#15444) 2025-07-08 13:08:16 +02:00
Marcelo Elizeche Landó
db96e13813 core: bump daphne from 4.2.0 to v4.2.1 (#15439) 2025-07-08 13:04:34 +02:00
Marcelo Elizeche Landó
3d39cc4974 core: bump boto3 from 1.38.43 to v1.39.3 (#15438) 2025-07-08 13:04:21 +02:00
Marcelo Elizeche Landó
d36ec31224 core: bump microsoft-kiota-abstractions from 1.9.3 to v1.9.4 (#15440) 2025-07-08 13:04:06 +02:00
Marcelo Elizeche Landó
bb7a2002f2 core: bump typing-extensions from 4.14.0 to v4.14.1 (#15449) 2025-07-08 13:03:50 +02:00
Marcelo Elizeche Landó
8fff802936 core: bump msgraph-core from 1.3.4 to v1.3.5 (#15445) 2025-07-08 13:03:40 +02:00
Marcelo Elizeche Landó
0f3fb9f93c core: bump rpds-py from 0.25.1 to v0.26.0 (#15447) 2025-07-08 13:03:21 +02:00
Marcelo Elizeche Landó
1e76d1f883 core: bump txaio from 23.1.1 to v25.6.1 (#15448) 2025-07-08 13:03:03 +02:00
dependabot[bot]
140d9fe95c core: bump github.com/getsentry/sentry-go from 0.34.0 to 0.34.1 (#15451)
---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-version: 0.34.1
  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-07-08 13:02:38 +02:00
dependabot[bot]
67eacbe860 website: bump the build group in /website with 6 updates (#15453)
Bumps the build group in /website with 6 updates:

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


Updates `@swc/core-darwin-arm64` from 1.12.9 to 1.12.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.12.9...v1.12.11)

Updates `@swc/core-linux-arm64-gnu` from 1.12.9 to 1.12.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.12.9...v1.12.11)

Updates `@swc/core-linux-x64-gnu` from 1.12.9 to 1.12.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.12.9...v1.12.11)

Updates `@swc/html-darwin-arm64` from 1.12.9 to 1.12.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.12.9...v1.12.11)

Updates `@swc/html-linux-arm64-gnu` from 1.12.9 to 1.12.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.12.9...v1.12.11)

Updates `@swc/html-linux-x64-gnu` from 1.12.9 to 1.12.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.12.9...v1.12.11)

---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.12.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.12.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.12.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-version: 1.12.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-version: 1.12.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-version: 1.12.11
  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-07-08 13:02:27 +02:00
transifex-integration[bot]
435b815617 translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#15454)
Translate locale/en/LC_MESSAGES/django.po in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-07-08 12:58:15 +02:00
transifex-integration[bot]
0459feeb8a translate: Updates for file web/xliff/en.xlf in de (#15455)
Translate web/xliff/en.xlf in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-07-08 12:57:46 +02:00
Dewi Roberts
4e6e730014 website/integrations: add zoho (#15388)
* Initial testing

* WIP

* WIP

* Finished doc

* Lint fix

* Spelling

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

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

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

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
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>
2025-07-08 08:00:17 +00:00
Šimon Bartoš
1231fc8237 website/docs: fix typo and update wordpress plugin name in wordpress integration guide (#15432)
Update index.md

Edited plugin name and plugin author's name - it seems they have changed slightly since this guide was written.
Changed available scopes to selected scopes - "offline_access" is already present in available scopes, and you are adding it to selected scopes, not to available scopes.

Signed-off-by: Šimon Bartoš <63071826+TyphousCrane654@users.noreply.github.com>
2025-07-07 20:53:41 -05:00
Dewi Roberts
b7f320d7cc website/docs: add manual RAC outpost deployment information (#15362)
* Add RAC deployment information

* Applied suggestions from Tana

* Language change and punctuation

* Updated URLs to authentik.company
2025-07-07 20:09:33 -05:00
dependabot[bot]
35073b03ac website: bump the build group in /website with 3 updates (#15423)
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.4.3 to 1.4.4
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.4.4/packages/rspack)

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

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

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-version: 1.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-version: 1.4.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-version: 1.4.4
  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-07-08 00:12:26 +02:00
dependabot[bot]
b3b8b8bb1c web: bump @sentry/browser from 9.34.0 to 9.35.0 in /web in the sentry group across 1 directory (#15424)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 9.34.0 to 9.35.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/9.34.0...9.35.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.35.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 00:12:23 +02:00
dependabot[bot]
17ee42f98f core: bump axllent/mailpit from v1.27.0 to v1.27.1 in /tests/e2e (#15425)
Bumps axllent/mailpit from v1.27.0 to v1.27.1.

---
updated-dependencies:
- dependency-name: axllent/mailpit
  dependency-version: v1.27.1
  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-07-08 00:12:21 +02:00
dependabot[bot]
e8f95a4b08 core: bump selenium/standalone-chrome from 137.0 to 138.0 in /tests/e2e (#15426)
Bumps selenium/standalone-chrome from 137.0 to 138.0.

---
updated-dependencies:
- dependency-name: selenium/standalone-chrome
  dependency-version: '138.0'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 00:12:18 +02:00
Tana M Berry
decc0c1ae1 website/docs: replace single step with a bullt (#15428)
* remove single step numbering

* tweak

---------

Co-authored-by: Tana M Berry <tana@goauthentik.io>
2025-07-07 08:29:21 -05:00
authentik-automation[bot]
716bfa9043 core, web: update translations (#15422)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-07-07 05:21:03 +02:00
transifex-integration[bot]
4d8feb15e3 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#15417)
* Translate locale/en/LC_MESSAGES/django.po in zh_CN

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

* 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-07-07 00:56:45 +02:00
transifex-integration[bot]
d50eab08e8 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#15419)
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-07-07 00:56:30 +02:00
transifex-integration[bot]
09b2a2bd4f translate: Updates for file web/xliff/en.xlf in zh_CN (#15418)
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-07-07 00:56:13 +02:00
transifex-integration[bot]
210d9cf31c translate: Updates for file web/xliff/en.xlf in zh-Hans (#15420)
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-07-07 00:55:58 +02:00
authentik-automation[bot]
a0291a1b32 web: bump API Client version (#15416)
* web: bump API Client version

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

* update go modules

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-07-06 02:01:41 +02:00
Jens L.
790ae0c3d8 web: rework storybook for flow components and to make the design consistent (#15415)
* unrelated: improve schema for authenticator validate device class

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

* fix static for storybook

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

* fix flow interface for storybook

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

* rework storybooks

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

* fix email authenticator icon

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

* fix accidental nested flow card

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

* fix webauthn padding partially

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

* fix autosubmit

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

* make consent stage look good

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

* clean

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

* add password stage

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

* start executor stories

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

* fix invalid html

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

* format

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

* fix frame stage

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

* cleanup

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

* fix design for device picker

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

* fix most of the padding

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

* make it work

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

* fix tests

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

* format

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

* fix

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

* use footer band for password recoery

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

* add prompt stage

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

* fix table persistence

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-06 00:26:22 +02:00
HeySora
8fc744fb56 website/docs: Re-introduce Websockets for nginx proxy manager (#14525)
Re-introduce Websocks for nginx proxy manager

Signed-off-by: HeySora <github@heysora.net>
2025-07-05 13:31:53 +02:00
authentik-automation[bot]
392011cac4 core, web: update translations (#15414)
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-07-05 13:31:34 +02:00
Jens L.
15316b6bae brands: sort matched brand by match length (#15413)
* brands: sort matched brand by match length

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-07-05 00:50:57 +02:00
Jason Fu
dccb1d01f0 website/integrations: add seafile (#14841)
* Docs

* forgot to change heading

* forgot to delete template

* forgot on more header

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

* added references and updated link to v13 of seafile

* whitespace

* shorter description

* apply suggestion

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

* prettier write

* apply suggestions

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

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>

* remove unrelated items

---------

Signed-off-by: Jason Fu <95495174+fasonju@users.noreply.github.com>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-07-04 16:21:04 -05:00
Dominic R
e8cd762c6e website/docs: air-gapped: Modernize for 2025.8 and address suggestions (#15305)
* website/docs: air-gapped: Modernize for 2025.8 and address suggestions

Signed-off-by: Dominic R <dominic@sdko.org>
Fixes: https://authentiksecurity.slack.com/archives/C08MZQV91T2/p1751074392062939

* Update default LDAP(S) ports based on default.yml

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

* Apply suggestions from code review

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

* lint-fix

* Apply suggestions from code review

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

* Update website/docs/install-config/air-gapped.mdx

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

* Apply suggestions from code review

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

* Address review comments

* Update website/docs/install-config/air-gapped.mdx

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

* Update website/docs/install-config/air-gapped.mdx

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

* Update website/docs/install-config/air-gapped.mdx

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

* lint

* Apply suggestions from code review

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

---------

Signed-off-by: Dominic R <dominic@sdko.org>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-07-04 15:59:01 -05:00
Dominic R
12847d9a87 website/docs: configuration: cleanup postgres section (#14544)
* website/docs: configuration: cleanup postgres section

* dont repeat myself

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

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

* fix

* review p1

* review p2

* typo

* Cleanup

* Lint

* here too?

* fix thing

* Apply suggestions from code review

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

* wip

* Apply suggestions from code review

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

* Update configuration.mdx

Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Dominic R <dominic@sdko.org>

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

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

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

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

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

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

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

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

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

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

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

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

* lint

---------

Signed-off-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-07-04 15:13:21 -05:00
transifex-integration[bot]
6c4cb06825 translate: Updates for file web/xliff/en.xlf in de (#15410)
Translate web/xliff/en.xlf in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-07-04 20:03:09 +00:00
authentik-automation[bot]
aa8e971477 web: bump API Client version (#15411)
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-07-04 21:50:22 +02:00
Jens L.
6c02d5a316 web/flow: fix flow dark theme flow footer band; user settings flow (#15408)
* fix flow band dark theme

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

* fix title

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

* fix api build?

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-04 21:42:44 +02:00
Teffen Ellis
2f3259bf13 web: Fix lack of error when setting recovery password (#15405)
web: Fix lack of error.
2025-07-04 21:29:58 +02:00
Jens L.
8b7a538419 stages/authenticator_validate: fix WebAuthn in android during google account addition (#15351)
* stages/authenticator_validate: fix WebAuthn in android during google account addition

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

* only use fallback on android MinuteMaid

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-04 21:29:27 +02:00
Jens L.
d0127d83c9 stages/user_login: unknown device (#14459)
* unrelated: add tests for session binding

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

* initial implementation

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

* also check currently authenticated sessions

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

* fix tests

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

* allow other stages to set known_device, and if set don't override it

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

* add options

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-04 21:12:09 +02:00
Jens L.
262ca4aea9 web/flow: fix ak-flow-card layout for identification stage with source and enrollment (#15404)
* web/flow: fix style issues I introduced, oops

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

* remove empty html``

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-04 14:11:10 +02:00
Jens L.
9923cb73a6 policies: Optimize policy checking for static bindings (#14957)
* initial optimisation

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

* improve

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

* less hardcoded names

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

* better

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

* found the first bug

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

* fix em actually

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

* fix more

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

* fix

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

* slight refactors

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

* add complex test

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-04 13:54:12 +02:00
dependabot[bot]
b58a8774d4 core: bump google-api-python-client from 2.174.0 to 2.175.0 (#15397)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.174.0 to 2.175.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.174.0...v2.175.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-04 12:33:00 +02:00
dependabot[bot]
bf6a37a5dc website: bump the build group in /website with 3 updates (#15398)
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.4.2 to 1.4.3
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/HEAD/packages/rspack)

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

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

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-version: 1.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-version: 1.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-version: 1.4.3
  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-07-04 11:48:47 +02:00
dependabot[bot]
1eda16cbd6 lifecycle/aws: bump aws-cdk from 2.1020.1 to 2.1020.2 in /lifecycle/aws (#15402)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1020.1 to 2.1020.2.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1020.2/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-version: 2.1020.2
  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-07-04 11:48:40 +02:00
Jens L.
8c3397e5f2 enterprise/search: fix schema once again (#15392)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-04 11:48:25 +02:00
hobyte
974b4d5c82 website/integrations: add OVH (#14664)
* Add documentation for OVH integration

* Apply suggested changes

* update file path to reflect service name change

* Fix formatting

* Improve ACS URL options

- add option for US region
- add section with references to OVHcloud help center

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

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

* Apply suggestions

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Minor changes

* prettier fix

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

---------

Signed-off-by: hobyte <63231858+hobyte@users.noreply.github.com>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: hobyte <hobyte+git@posteo.de>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-07-04 09:00:20 +00:00
Brian Begun
00daba0d0c website/docs: update index.md for Sonarr (#15395)
* Update index.md

Added additional note to get authentication to pass through to Sonarr.

Signed-off-by: Brian Begun <begunfx@usa.net>

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

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

* Prettier fix

---------

Signed-off-by: Brian Begun <begunfx@usa.net>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-07-04 08:45:20 +00:00
dependabot[bot]
63d547194c core: bump twilio from 9.6.3 to 9.6.4 (#15396)
Bumps [twilio](https://github.com/twilio/twilio-python) from 9.6.3 to 9.6.4.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/9.6.3...9.6.4)

---
updated-dependencies:
- dependency-name: twilio
  dependency-version: 9.6.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-04 09:32:15 +02:00
dependabot[bot]
ec171bd282 core: bump opencontainers from 0.0.14 to 0.0.15 (#15399)
Bumps [opencontainers](https://github.com/vsoch/oci-python) from 0.0.14 to 0.0.15.
- [Changelog](https://github.com/vsoch/oci-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vsoch/oci-python/commits)

---
updated-dependencies:
- dependency-name: opencontainers
  dependency-version: 0.0.15
  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-07-04 09:31:43 +02:00
authentik-automation[bot]
155fa433b3 core, web: update translations (#15394)
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-07-04 02:35:29 +02:00
Dewi Roberts
7a88fd5b6b website/integrations: add ironclad (#14446)
* Updated sidebar and started integration doc

* Added property mapping section and further instructions.

* Added more details about property mapping

* Changed wording and updated property mappings

* Added final steps

* Improved 'what is' description

* Applied suggestions

* Updated note

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

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

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-07-03 18:26:13 -05:00
Tana M Berry
7d9fb85827 website/docs: improve the docs about our Events and logging (#15270)
* tweak

* more content

* major surgery

* fix image link

* Optimised images with calibre/image-actions

* tweaks

* dom and dewi edits

* tweak to bump build

---------

Co-authored-by: Tana M Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-07-03 17:19:02 -05:00
Jens L.
0021e5fa25 web/flows: fix bottom padding when loading challenge (#15372)
* web/flows: fix bottom padding when loading challenge

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

* add base class that does layout for login cards

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

* ok actually rework the whole thing

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

* fix leftover div

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

* fix other stages

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

* better declare loading state

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

* format

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

* fix tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-03 22:07:22 +02:00
Jens L.
6919838c12 core: fix set_token_key permission not declared (#15384)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-03 21:45:50 +02:00
Jens L.
9841d976e1 web/admin: fix nested table pagination and search (#15385)
* web/admin: fix nested table pagination and search

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

* update

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-03 20:58:48 +02:00
Dewi Roberts
87051cf588 website/integrations: add planka (#15108)
* Start document and update sidebar

* Finish document

* Typo

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

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

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

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

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

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

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

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

* Applying suggestions

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

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

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

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
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-07-03 11:20:56 +00:00
Dewi Roberts
dec7ac675c website/integrations: add papra (#15093)
* Start document and update sidebar

* Finished document

* Changed icon link to authentik

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

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

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

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

* Docker Compose captialization

* Updated language

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

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

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

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

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-07-03 11:20:33 +00:00
dependabot[bot]
53e17ff877 core: bump astral-sh/uv from 0.7.18 to 0.7.19 (#15379)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 11:00:29 +00:00
Dewi Roberts
4635a07edd website/docs: clarify upgrade process (#15330)
* Clarify upgrade process and change to sub headers to make it easier to read.

* Applied suggestions

* Moved sentence

* Changes based on meeting with Tana
2025-07-03 11:56:49 +01:00
authentik-automation[bot]
f70b74fc03 core, web: update translations (#15377)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-07-03 12:37:50 +02:00
Dewi Roberts
2713a5ec88 website/integrations: fix kanboard doc prettier (#15381)
Removes linebreak
2025-07-03 11:53:29 +02:00
1199 changed files with 33990 additions and 25917 deletions

View File

@@ -1,5 +1,5 @@
[bumpversion]
current_version = 2025.6.3
current_version = 2025.6.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*))?

View File

@@ -31,4 +31,4 @@ If changes to the frontend have been made
If applicable
- [ ] The documentation has been updated
- [ ] The documentation has been formatted (`make website`)
- [ ] The documentation has been formatted (`make docs`)

View File

@@ -27,8 +27,8 @@ jobs:
- name: Publish package
working-directory: gen-ts-api/
run: |
npm ci
npm publish
npm i
npm publish --tag generated
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
- name: Upgrade /web

94
.github/workflows/ci-api-docs.yml vendored Normal file
View File

@@ -0,0 +1,94 @@
name: authentik-ci-api-docs
on:
push:
branches:
- main
- next
- version-*
pull_request:
branches:
- main
- version-*
jobs:
lint:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
command:
- prettier-check
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
working-directory: website/
run: npm ci
- name: Lint
working-directory: website/
run: npm run ${{ matrix.command }}
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: website/package.json
cache: "npm"
cache-dependency-path: website/package-lock.json
- working-directory: website/
name: Install Dependencies
run: npm ci
- uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/website/api/.docusaurus
${{ github.workspace }}/website/api/**/.cache
key: |
${{ runner.os }}-docusaurus-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
restore-keys: |
${{ runner.os }}-docusaurus-${{ hashFiles('**/package-lock.json') }}
- name: Build API Docs via Docusaurus
working-directory: website
env:
NODE_ENV: production
run: npm run build -w api
- uses: actions/upload-artifact@v4
with:
name: api-docs
path: website/api/build
retention-days: 7
deploy:
runs-on: ubuntu-latest
needs:
- lint
- build
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: api-docs
path: website/api/build
- uses: actions/setup-node@v4
with:
node-version-file: website/package.json
cache: "npm"
cache-dependency-path: website/package-lock.json
- name: Deploy Netlify (Production)
working-directory: website/api
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
env:
NETLIFY_SITE_ID: authentik-api-docs.netlify.app
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
run: npx netlify deploy --no-build --prod
- name: Deploy Netlify (Preview)
if: github.event_name == 'pull_request' || github.ref != 'refs/heads/main'
working-directory: website/api
env:
NETLIFY_SITE_ID: authentik-api-docs.netlify.app
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
run: |
if [ -n "${VAR}" ]; then
npx netlify deploy --no-build --alias=deploy-preview-${{ github.event.number }}
fi

View File

@@ -1,4 +1,4 @@
name: authentik-ci-website
name: authentik-ci-docs
on:
push:
@@ -18,17 +18,18 @@ jobs:
fail-fast: false
matrix:
command:
- lint:lockfile
- prettier-check
steps:
- uses: actions/checkout@v4
- working-directory: website/
- name: Install dependencies
working-directory: website/
run: npm ci
- name: Lint
working-directory: website/
run: npm run ${{ matrix.command }}
test:
build-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
@@ -37,19 +38,14 @@ jobs:
cache: "npm"
cache-dependency-path: website/package-lock.json
- working-directory: website/
name: Install Dependencies
run: npm ci
- name: test
- name: Build Documentation via Docusaurus
working-directory: website/
run: npm test
build:
run: npm run build
build-integrations:
runs-on: ubuntu-latest
name: ${{ matrix.job }}
strategy:
fail-fast: false
matrix:
job:
- build
- build:integrations
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
@@ -58,10 +54,11 @@ jobs:
cache: "npm"
cache-dependency-path: website/package-lock.json
- working-directory: website/
name: Install Dependencies
run: npm ci
- name: build
- name: Build Integrations via Docusaurus
working-directory: website/
run: npm run ${{ matrix.job }}
run: npm run build -w integrations
build-container:
if: ${{ github.repository != 'goauthentik/authentik-internal' }}
runs-on: ubuntu-latest
@@ -115,8 +112,8 @@ jobs:
if: always()
needs:
- lint
- test
- build
- build-docs
- build-integrations
- build-container
runs-on: ubuntu-latest
steps:

View File

@@ -10,7 +10,8 @@ coverage
dist
out
.docusaurus
website/docs/developer-docs/api/**/*
# TODO Replace after moving website to docs
website/api/reference
## Environment
*.env

11
.vscode/settings.json vendored
View File

@@ -7,7 +7,10 @@
"!Enumerate sequence",
"!Env scalar",
"!Env sequence",
"!File scalar",
"!File sequence",
"!Find sequence",
"!FindObject sequence",
"!Format sequence",
"!If sequence",
"!Index scalar",
@@ -31,6 +34,10 @@
"ignoreCase": false
}
],
"go.testFlags": ["-count=1"],
"github-actions.workflows.pinned.workflows": [".github/workflows/ci-main.yml"]
"go.testFlags": [
"-count=1"
],
"github-actions.workflows.pinned.workflows": [
".github/workflows/ci-main.yml"
]
}

44
.vscode/tasks.json vendored
View File

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

View File

@@ -32,8 +32,12 @@ tests/wdio/ @goauthentik/frontend
locale/ @goauthentik/backend @goauthentik/frontend
web/xliff/ @goauthentik/backend @goauthentik/frontend
# Docs & Website
docs/ @goauthentik/docs
# TODO Remove after moving website to docs
website/ @goauthentik/docs
CODE_OF_CONDUCT.md @goauthentik/docs
# Security
SECURITY.md @goauthentik/security @goauthentik/docs
website/docs/security/ @goauthentik/security @goauthentik/docs
# TODO Remove after moving website to docs
website/security/ @goauthentik/security @goauthentik/docs
docs/security/ @goauthentik/security @goauthentik/docs

View File

@@ -14,10 +14,11 @@ RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/packages/sfe/package.json,src=./web/packages/sfe/package.json \
--mount=type=bind,target=/work/web/scripts,src=./web/scripts \
--mount=type=cache,id=npm-ak,sharing=shared,target=/root/.npm \
npm ci --include=dev
npm ci
COPY ./package.json /work
COPY ./web /work/web/
# TODO: Update this after moving website to docs
COPY ./website /work/website/
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
@@ -62,7 +63,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
go build -o /go/authentik ./cmd/server
# Stage 3: MaxMind GeoIP
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.1 AS geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN"
ENV GEOIPUPDATE_VERBOSE="1"
@@ -75,7 +76,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 4: Download uv
FROM ghcr.io/astral-sh/uv:0.7.18 AS uv
FROM ghcr.io/astral-sh/uv:0.8.2 AS uv
# Stage 5: Base python image
FROM ghcr.io/goauthentik/fips-python:3.13.5-slim-bookworm-fips AS python-base

View File

@@ -1,4 +1,4 @@
.PHONY: gen dev-reset all clean test web website
.PHONY: gen dev-reset all clean test web docs
SHELL := /usr/bin/env bash
.SHELLFLAGS += ${SHELLFLAGS} -e -o pipefail
@@ -73,7 +73,7 @@ core-i18n-extract:
--ignore website \
-l en
install: web-install website-install core-install ## Install all requires dependencies for `web`, `website` and `core`
install: node-install docs-install core-install ## Install all requires dependencies for `node`, `docs` and `core`
dev-drop-db:
dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
@@ -121,7 +121,7 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a
sed -i 's/}/&#125;/g' diff.md
npx prettier --write diff.md
gen-clean-ts: ## Remove generated API client for Typescript
gen-clean-ts: ## Remove generated API client for TypeScript
rm -rf ${PWD}/${GEN_API_TS}/
rm -rf ${PWD}/web/node_modules/@goauthentik/api/
@@ -183,18 +183,23 @@ gen-dev-config: ## Generate a local development config file
gen: gen-build gen-client-ts
#########################
## Node.js
#########################
node-install: ## Install the necessary libraries to build Node.js packages
npm ci
npm ci --prefix web
#########################
## Web
#########################
web-build: web-install ## Build the Authentik UI
web-build: node-install ## Build the Authentik UI
cd web && npm run build
web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
web-install: ## Install the necessary libraries to build the Authentik UI
cd web && npm ci
web-test: ## Run tests for the Authentik UI
cd web && npm run test
@@ -221,22 +226,40 @@ web-i18n-extract:
cd web && npm run extract-locales
#########################
## Website
## Docs
#########################
website: website-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it
docs: docs-lint-fix docs-build ## Automatically fix formatting issues in the Authentik docs source code, lint the code, and compile it
website-install:
cd website && npm ci
docs-install:
npm ci --prefix website
website-lint-fix: lint-codespell
cd website && npm run prettier
docs-lint-fix: lint-codespell
npm run prettier --prefix website
website-build:
cd website && npm run build
docs-build:
npm run build --prefix website
website-watch: ## Build and watch the documentation website, updating automatically
cd website && npm run watch
docs-watch: ## Build and watch the topics documentation
npm run start --prefix website
integrations: docs-lint-fix integrations-build ## Fix formatting issues in the integrations source code, lint the code, and compile it
integrations-build:
npm run build --prefix website -w integrations
integrations-watch: ## Build and watch the Integrations documentation
npm run start --prefix website -w integrations
docs-api-build:
npm run build --prefix website -w api
docs-api-watch: ## Build and watch the API documentation
npm run build:api --prefix website -w api
npm run start --prefix website -w api
docs-api-clean: ## Clean generated API documentation
npm run build:api:clean --prefix website -w api
#########################
## Docker

View File

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

View File

@@ -12,8 +12,8 @@ context:
context1: context-nested-value
context2: !Context context1
entries:
- model: !Format ["%s", authentik_sources_oauth.oauthsource]
state: !Format ["%s", present]
- model: !Format ["%%s", authentik_sources_oauth.oauthsource]
state: !Format ["%%s", present]
identifiers:
slug: test
attrs:
@@ -27,20 +27,23 @@ entries:
[slug, default-source-authentication],
]
enrollment_flow:
!Find [!Format ["%s", authentik_flows.Flow], [slug, default-source-enrollment]]
!Find [!Format ["%%s", authentik_flows.Flow], [slug, default-source-enrollment]]
- attrs:
expression: return True
identifiers:
name: !Format [foo-%s-%s-%s, !Context foo, !Context bar, qux]
name: !Format [foo-%%s-%%s-%%s, !Context foo, !Context bar, qux]
id: policy
model: authentik_policies_expression.expressionpolicy
- attrs:
attributes:
env_null: !Env [bar-baz, null]
file_content: !File '%(file_name)s'
file_default: !File ['%(file_default_name)s', 'default']
file_non_existent: !File '/does-not-exist'
json_parse: !ParseJSON '{"foo": "bar"}'
policy_pk1:
!Format [
"%s-%s",
"%%s-%%s",
!Find [
authentik_policies_expression.expressionpolicy,
[
@@ -51,29 +54,29 @@ entries:
],
suffix,
]
policy_pk2: !Format ["%s-%s", !KeyOf policy, suffix]
policy_pk2: !Format ["%%s-%%s", !KeyOf policy, suffix]
boolAnd:
!Condition [AND, !Context foo, !Format ["%s", "a_string"], 1]
!Condition [AND, !Context foo, !Format ["%%s", "a_string"], 1]
boolNand:
!Condition [NAND, !Context foo, !Format ["%s", "a_string"], 1]
!Condition [NAND, !Context foo, !Format ["%%s", "a_string"], 1]
boolOr:
!Condition [
OR,
!Context foo,
!Format ["%s", "a_string"],
!Format ["%%s", "a_string"],
null,
]
boolNor:
!Condition [
NOR,
!Context foo,
!Format ["%s", "a_string"],
!Format ["%%s", "a_string"],
null,
]
boolXor:
!Condition [XOR, !Context foo, !Format ["%s", "a_string"], 1]
!Condition [XOR, !Context foo, !Format ["%%s", "a_string"], 1]
boolXnor:
!Condition [XNOR, !Context foo, !Format ["%s", "a_string"], 1]
!Condition [XNOR, !Context foo, !Format ["%%s", "a_string"], 1]
boolComplex:
!Condition [
XNOR,
@@ -89,7 +92,7 @@ entries:
{
with: { keys: "and_values" },
and_nested_custom_tags:
!Format ["foo-%s", !Context foo],
!Format ["foo-%%s", !Context foo],
},
},
null,
@@ -98,7 +101,7 @@ entries:
!If [
!Condition [AND, false],
null,
[list, with, items, !Format ["foo-%s", !Context foo]],
[list, with, items, !Format ["foo-%%s", !Context foo]],
]
if_true_simple: !If [!Context foo, true, text]
if_short: !If [!Context foo]
@@ -106,22 +109,22 @@ entries:
enumerate_mapping_to_mapping: !Enumerate [
!Context mapping,
MAP,
[!Format ["prefix-%s", !Index 0], !Format ["other-prefix-%s", !Value 0]]
[!Format ["prefix-%%s", !Index 0], !Format ["other-prefix-%%s", !Value 0]]
]
enumerate_mapping_to_sequence: !Enumerate [
!Context mapping,
SEQ,
!Format ["prefixed-pair-%s-%s", !Index 0, !Value 0]
!Format ["prefixed-pair-%%s-%%s", !Index 0, !Value 0]
]
enumerate_sequence_to_sequence: !Enumerate [
!Context sequence,
SEQ,
!Format ["prefixed-items-%s-%s", !Index 0, !Value 0]
!Format ["prefixed-items-%%s-%%s", !Index 0, !Value 0]
]
enumerate_sequence_to_mapping: !Enumerate [
!Context sequence,
MAP,
[!Format ["index: %d", !Index 0], !Value 0]
[!Format ["index: %%d", !Index 0], !Value 0]
]
nested_complex_enumeration: !Enumerate [
!Context sequence,
@@ -132,9 +135,9 @@ entries:
!Context mapping,
MAP,
[
!Format ["%s", !Index 0],
!Format ["%%s", !Index 0],
[
!Enumerate [!Value 2, SEQ, !Format ["prefixed-%s", !Value 0]],
!Enumerate [!Value 2, SEQ, !Format ["prefixed-%%s", !Value 0]],
{
outer_value: !Value 1,
outer_index: !Index 1,
@@ -151,6 +154,7 @@ entries:
at_index_sequence_default: !AtIndex [!Context sequence, 100, "non existent"]
at_index_mapping: !AtIndex [!Context mapping, "key2"]
at_index_mapping_default: !AtIndex [!Context mapping, "invalid", "non existent"]
find_object: !AtIndex [!FindObject [authentik_providers_oauth2.scopemapping, [scope_name, openid]], managed]
identifiers:
name: test
conditions:

View File

@@ -1,9 +1,11 @@
"""Test blueprints v1"""
from os import environ
from os import chmod, environ, unlink, write
from tempfile import mkstemp
from django.test import TransactionTestCase
from authentik.blueprints.tests import apply_blueprint
from authentik.blueprints.v1.exporter import FlowExporter
from authentik.blueprints.v1.importer import Importer, transaction_rollback
from authentik.core.models import Group
@@ -126,102 +128,119 @@ class TestBlueprintsV1(TransactionTestCase):
self.assertEqual(Prompt.objects.filter(field_key="username").count(), count_before)
@apply_blueprint("system/providers-oauth2.yaml")
def test_import_yaml_tags(self):
"""Test some yaml tags"""
ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").delete()
Group.objects.filter(name="test").delete()
environ["foo"] = generate_id()
importer = Importer.from_string(load_fixture("fixtures/tags.yaml"), {"bar": "baz"})
file, file_name = mkstemp()
write(file, b"foo")
_, file_default_name = mkstemp()
chmod(file_default_name, 0o000) # Remove all permissions so we can't read the file
importer = Importer.from_string(
load_fixture(
"fixtures/tags.yaml",
file_name=file_name,
file_default_name=file_default_name,
),
{"bar": "baz"},
)
self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply())
policy = ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").first()
self.assertTrue(policy)
self.assertTrue(
Group.objects.filter(
attributes={
"policy_pk1": str(policy.pk) + "-suffix",
"policy_pk2": str(policy.pk) + "-suffix",
"boolAnd": True,
"boolNand": False,
"boolOr": True,
"boolNor": False,
"boolXor": True,
"boolXnor": False,
"boolComplex": True,
"if_true_complex": {
"dictionary": {
"with": {"keys": "and_values"},
"and_nested_custom_tags": "foo-bar",
}
group = Group.objects.filter(name="test").first()
self.assertIsNotNone(group)
self.assertEqual(
group.attributes,
{
"policy_pk1": str(policy.pk) + "-suffix",
"policy_pk2": str(policy.pk) + "-suffix",
"boolAnd": True,
"boolNand": False,
"boolOr": True,
"boolNor": False,
"boolXor": True,
"boolXnor": False,
"boolComplex": True,
"if_true_complex": {
"dictionary": {
"with": {"keys": "and_values"},
"and_nested_custom_tags": "foo-bar",
}
},
"if_false_complex": ["list", "with", "items", "foo-bar"],
"if_true_simple": True,
"if_short": True,
"if_false_simple": 2,
"enumerate_mapping_to_mapping": {
"prefix-key1": "other-prefix-value",
"prefix-key2": "other-prefix-2",
},
"enumerate_mapping_to_sequence": [
"prefixed-pair-key1-value",
"prefixed-pair-key2-2",
],
"enumerate_sequence_to_sequence": [
"prefixed-items-0-foo",
"prefixed-items-1-bar",
],
"enumerate_sequence_to_mapping": {"index: 0": "foo", "index: 1": "bar"},
"nested_complex_enumeration": {
"0": {
"key1": [
["prefixed-f", "prefixed-o", "prefixed-o"],
{
"outer_value": "foo",
"outer_index": 0,
"middle_value": "value",
"middle_index": "key1",
},
],
"key2": [
["prefixed-f", "prefixed-o", "prefixed-o"],
{
"outer_value": "foo",
"outer_index": 0,
"middle_value": 2,
"middle_index": "key2",
},
],
},
"if_false_complex": ["list", "with", "items", "foo-bar"],
"if_true_simple": True,
"if_short": True,
"if_false_simple": 2,
"enumerate_mapping_to_mapping": {
"prefix-key1": "other-prefix-value",
"prefix-key2": "other-prefix-2",
"1": {
"key1": [
["prefixed-b", "prefixed-a", "prefixed-r"],
{
"outer_value": "bar",
"outer_index": 1,
"middle_value": "value",
"middle_index": "key1",
},
],
"key2": [
["prefixed-b", "prefixed-a", "prefixed-r"],
{
"outer_value": "bar",
"outer_index": 1,
"middle_value": 2,
"middle_index": "key2",
},
],
},
"enumerate_mapping_to_sequence": [
"prefixed-pair-key1-value",
"prefixed-pair-key2-2",
],
"enumerate_sequence_to_sequence": [
"prefixed-items-0-foo",
"prefixed-items-1-bar",
],
"enumerate_sequence_to_mapping": {"index: 0": "foo", "index: 1": "bar"},
"nested_complex_enumeration": {
"0": {
"key1": [
["prefixed-f", "prefixed-o", "prefixed-o"],
{
"outer_value": "foo",
"outer_index": 0,
"middle_value": "value",
"middle_index": "key1",
},
],
"key2": [
["prefixed-f", "prefixed-o", "prefixed-o"],
{
"outer_value": "foo",
"outer_index": 0,
"middle_value": 2,
"middle_index": "key2",
},
],
},
"1": {
"key1": [
["prefixed-b", "prefixed-a", "prefixed-r"],
{
"outer_value": "bar",
"outer_index": 1,
"middle_value": "value",
"middle_index": "key1",
},
],
"key2": [
["prefixed-b", "prefixed-a", "prefixed-r"],
{
"outer_value": "bar",
"outer_index": 1,
"middle_value": 2,
"middle_index": "key2",
},
],
},
},
"nested_context": "context-nested-value",
"env_null": None,
"json_parse": {"foo": "bar"},
"at_index_sequence": "foo",
"at_index_sequence_default": "non existent",
"at_index_mapping": 2,
"at_index_mapping_default": "non existent",
}
).exists()
},
"nested_context": "context-nested-value",
"env_null": None,
"file_content": "foo",
"file_default": "default",
"file_non_existent": None,
"json_parse": {"foo": "bar"},
"at_index_sequence": "foo",
"at_index_sequence_default": "non existent",
"at_index_mapping": 2,
"at_index_mapping_default": "non existent",
"find_object": "goauthentik.io/providers/oauth2/scope-openid",
},
)
self.assertTrue(
OAuthSource.objects.filter(
@@ -229,6 +248,8 @@ class TestBlueprintsV1(TransactionTestCase):
consumer_key=environ["foo"],
)
)
unlink(file_name)
unlink(file_default_name)
def test_export_validate_import_policies(self):
"""Test export and validate it"""

View File

@@ -18,12 +18,15 @@ from django.db.models import Model, Q
from rest_framework.exceptions import ValidationError
from rest_framework.fields import Field
from rest_framework.serializers import Serializer
from structlog.stdlib import get_logger
from yaml import SafeDumper, SafeLoader, ScalarNode, SequenceNode
from authentik.lib.models import SerializerModel
from authentik.lib.sentry import SentryIgnoredException
from authentik.policies.models import PolicyBindingModel
LOGGER = get_logger()
class UNSET:
"""Used to test whether a key has not been set."""
@@ -268,6 +271,34 @@ class Env(YAMLTag):
return getenv(self.key) or self.default
class File(YAMLTag):
"""Lookup file with optional default"""
path: str
default: Any | None
def __init__(self, loader: "BlueprintLoader", node: ScalarNode | SequenceNode) -> None:
super().__init__()
self.default = None
if isinstance(node, ScalarNode):
self.path = node.value
if isinstance(node, SequenceNode):
self.path = loader.construct_object(node.value[0])
self.default = loader.construct_object(node.value[1])
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
try:
with open(self.path, encoding="utf8") as _file:
return _file.read().strip()
except OSError as exc:
LOGGER.warning(
"Failed to read file. Falling back to default value",
path=self.path,
exc=exc,
)
return self.default
class Context(YAMLTag):
"""Lookup key from instance context"""
@@ -336,7 +367,7 @@ class Format(YAMLTag):
class Find(YAMLTag):
"""Find any object"""
"""Find any object primary key"""
model_name: str | YAMLTag
conditions: list[list]
@@ -351,7 +382,7 @@ class Find(YAMLTag):
values.append(loader.construct_object(node_values))
self.conditions.append(values)
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
def _get_instance(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
if isinstance(self.model_name, YAMLTag):
model_name = self.model_name.resolve(entry, blueprint)
else:
@@ -373,12 +404,29 @@ class Find(YAMLTag):
else:
query_value = cond[1]
query &= Q(**{query_key: query_value})
instance = model_class.objects.filter(query).first()
return model_class.objects.filter(query).first()
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
instance = self._get_instance(entry, blueprint)
if instance:
return instance.pk
return None
class FindObject(Find):
"""Find any object"""
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
instance = self._get_instance(entry, blueprint)
if not instance:
return None
if not isinstance(instance, SerializerModel):
raise EntryInvalidError.from_entry(
f"Model {self.model_name} is not resolvable through FindObject", entry
)
return instance.serializer(instance=instance).data
class Condition(YAMLTag):
"""Convert all values to a single boolean"""
@@ -674,11 +722,13 @@ class BlueprintLoader(SafeLoader):
super().__init__(*args, **kwargs)
self.add_constructor("!KeyOf", KeyOf)
self.add_constructor("!Find", Find)
self.add_constructor("!FindObject", FindObject)
self.add_constructor("!Context", Context)
self.add_constructor("!Format", Format)
self.add_constructor("!Condition", Condition)
self.add_constructor("!If", If)
self.add_constructor("!Env", Env)
self.add_constructor("!File", File)
self.add_constructor("!Enumerate", Enumerate)
self.add_constructor("!Value", Value)
self.add_constructor("!Index", Index)

View File

@@ -52,6 +52,27 @@ class TestBrands(APITestCase):
},
)
def test_brand_subdomain_same_suffix(self):
"""Test Current brand API"""
Brand.objects.all().delete()
Brand.objects.create(domain="bar.baz", branding_title="custom")
Brand.objects.create(domain="foo.bar.baz", branding_title="custom")
self.assertJSONEqual(
self.client.get(
reverse("authentik_api:brand-current"), HTTP_HOST="foo.bar.baz"
).content.decode(),
{
"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": "foo.bar.baz",
"ui_footer_links": [],
"ui_theme": Themes.AUTOMATIC,
"default_locale": "",
},
)
def test_fallback(self):
"""Test fallback brand"""
Brand.objects.all().delete()

View File

@@ -4,6 +4,7 @@ from typing import Any
from django.db.models import F, Q
from django.db.models import Value as V
from django.db.models.functions import Length
from django.http.request import HttpRequest
from django.utils.html import _json_script_escapes
from django.utils.safestring import mark_safe
@@ -20,9 +21,9 @@ DEFAULT_BRAND = Brand(domain="fallback")
def get_brand_for_request(request: HttpRequest) -> Brand:
"""Get brand object for current request"""
db_brands = (
Brand.objects.annotate(host_domain=V(request.get_host()))
Brand.objects.annotate(host_domain=V(request.get_host()), match_length=Length("domain"))
.filter(Q(host_domain__iendswith=F("domain")) | _q_default)
.order_by("default")
.order_by("-match_length", "default")
)
brands = list(db_brands.all())
if len(brands) < 1:
@@ -42,6 +43,6 @@ def context_processor(request: HttpRequest) -> dict[str, Any]:
"brand": brand,
"brand_css": brand_css,
"footer_links": tenant.footer_links,
"html_meta": {**get_http_meta()},
"html_meta": get_http_meta(),
"version": get_full_version(),
}

View File

@@ -149,10 +149,10 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
return applications
def _filter_applications_with_launch_url(
self, pagined_apps: Iterator[Application]
self, paginated_apps: Iterator[Application]
) -> list[Application]:
applications = []
for app in pagined_apps:
for app in paginated_apps:
if app.get_launch_url():
applications.append(app)
return applications

View File

@@ -11,7 +11,6 @@ from authentik.core.expression.exceptions import SkipObjectException
from authentik.core.models import User
from authentik.events.models import Event, EventAction
from authentik.lib.expression.evaluator import BaseEvaluator
from authentik.lib.utils.errors import exception_to_string
from authentik.policies.types import PolicyRequest
PROPERTY_MAPPING_TIME = Histogram(
@@ -69,12 +68,11 @@ class PropertyMappingEvaluator(BaseEvaluator):
# For dry-run requests we don't save exceptions
if self.dry_run:
return
error_string = exception_to_string(exc)
event = Event.new(
EventAction.PROPERTY_MAPPING_EXCEPTION,
expression=expression_source,
message=error_string,
)
message="Failed to execute property mapping",
).with_exception(exc)
if "request" in self._context:
req: PolicyRequest = self._context["request"]
if req.http_request:

View File

@@ -5,6 +5,7 @@ from contextvars import ContextVar
from functools import partial
from uuid import uuid4
from django.contrib.auth import logout
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import ImproperlyConfigured
from django.http import HttpRequest, HttpResponse
@@ -58,6 +59,11 @@ class AuthenticationMiddleware(MiddlewareMixin):
request.user = SimpleLazyObject(lambda: get_user(request))
request.auser = partial(aget_user, request)
user = request.user
if user and user.is_authenticated and not user.is_active:
logout(request)
raise AssertionError()
class ImpersonateMiddleware:
"""Middleware to impersonate users"""

View File

@@ -0,0 +1,24 @@
# Generated by Django 5.1.11 on 2025-07-03 13:08
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0048_delete_oldauthenticatedsession_content_type"),
]
operations = [
migrations.AlterModelOptions(
name="token",
options={
"permissions": [
("view_token_key", "View token's key"),
("set_token_key", "Set a token's key"),
],
"verbose_name": "Token",
"verbose_name_plural": "Tokens",
},
),
]

View File

@@ -953,7 +953,10 @@ class Token(SerializerModel, ManagedModel, ExpiringModel):
models.Index(fields=["identifier"]),
models.Index(fields=["key"]),
]
permissions = [("view_token_key", _("View token's key"))]
permissions = [
("view_token_key", _("View token's key")),
("set_token_key", _("Set a token's key")),
]
def __str__(self):
description = f"{self.identifier}"

View File

@@ -79,8 +79,8 @@ class SourceFlowManager:
identifier: str
user_connection_type: type[UserSourceConnection] = UserSourceConnection
group_connection_type: type[GroupSourceConnection] = GroupSourceConnection
user_connection_type: type[UserSourceConnection]
group_connection_type: type[GroupSourceConnection]
user_info: dict[str, Any]
policy_context: dict[str, Any]

View File

@@ -10,6 +10,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
{# Darkreader breaks the site regardless of theme as its not compatible with webcomponents, and we default to a dark theme based on preferred colour-scheme #}
<meta name="darkreader-lock">
<base href="{{ base_url_rel }}" />
<title>{% block title %}{% trans title|default:brand.branding_title %}{% endblock %}</title>
<link rel="icon" href="{{ brand.branding_favicon_url }}">
<link rel="shortcut icon" href="{{ brand.branding_favicon_url }}">

View File

@@ -12,6 +12,7 @@ from rest_framework.fields import CharField, IntegerField
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
@@ -53,6 +54,7 @@ class LicenseSerializer(ModelSerializer):
"external_users",
]
extra_kwargs = {
"key": {"validators": [UniqueValidator(queryset=License.objects.all())]},
"name": {"read_only": True},
"expiry": {"read_only": True},
"internal_users": {"read_only": True},

View File

@@ -65,13 +65,17 @@ class EnterpriseAuditMiddleware(AuditMiddleware):
data[field.name] = deepcopy(field_value)
return cleanse_dict(data)
def diff(self, before: dict, after: dict) -> dict:
def diff(self, before: dict, after: dict, update_fields: list[str] | None = None) -> dict:
"""Generate diff between dicts"""
diff = {}
for key, value in before.items():
if update_fields and key not in update_fields:
continue
if after.get(key) != value:
diff[key] = {"previous_value": value, "new_value": after.get(key)}
for key, value in after.items():
if update_fields and key not in update_fields:
continue
if key not in before and key not in diff and before.get(key) != value:
diff[key] = {"previous_value": before.get(key), "new_value": value}
return sanitize_item(diff)
@@ -95,6 +99,7 @@ class EnterpriseAuditMiddleware(AuditMiddleware):
instance: Model,
created: bool,
thread_kwargs: dict | None = None,
update_fields: list[str] | None = None,
**_,
):
if not self.enabled:
@@ -108,7 +113,7 @@ class EnterpriseAuditMiddleware(AuditMiddleware):
prev_state = {}
# Get current state
new_state = self.serialize_simple(instance)
diff = self.diff(prev_state, new_state)
diff = self.diff(prev_state, new_state, update_fields)
thread_kwargs["diff"] = diff
return super().post_save_handler(request, sender, instance, created, thread_kwargs, **_)

View File

@@ -7,6 +7,7 @@ from rest_framework.test import APITestCase
from authentik.core.models import Group, User
from authentik.core.tests.utils import create_test_admin_user
from authentik.enterprise.audit.middleware import EnterpriseAuditMiddleware
from authentik.events.models import Event, EventAction
from authentik.events.utils import sanitize_item
from authentik.lib.generators import generate_id
@@ -208,3 +209,23 @@ class TestEnterpriseAudit(APITestCase):
diff,
{"users": {"remove": [user.pk]}},
)
@patch(
"authentik.enterprise.audit.middleware.EnterpriseAuditMiddleware.enabled",
PropertyMock(return_value=True),
)
def test_diff_update_fields(self):
"""Test update audit log"""
self.client.force_login(self.user)
diff = EnterpriseAuditMiddleware(None).diff(
{
"foo": "bar",
"is_active": False,
},
{
"foo": "baz",
"is_active": True,
},
update_fields=["is_active"],
)
self.assertEqual(diff, {"is_active": {"new_value": True, "previous_value": False}})

View File

@@ -6,7 +6,7 @@ from djangoql.ast import Name
from djangoql.exceptions import DjangoQLError
from djangoql.queryset import apply_search
from djangoql.schema import DjangoQLSchema
from rest_framework.filters import BaseFilterBackend, SearchFilter
from rest_framework.filters import SearchFilter
from rest_framework.request import Request
from structlog.stdlib import get_logger
@@ -39,7 +39,7 @@ class BaseSchema(DjangoQLSchema):
return super().resolve_name(name)
class QLSearch(BaseFilterBackend):
class QLSearch(SearchFilter):
"""rest_framework search filter which uses DjangoQL"""
def __init__(self):

View File

@@ -16,7 +16,7 @@ from authentik.stages.authenticator.models import Device
class AuthenticatorEndpointGDTCStage(ConfigurableStage, FriendlyNamedStage, Stage):
"""Setup Google Chrome Device-trust connection"""
"""Setup Google Chrome Device Trust connection"""
credentials = models.JSONField()

View File

@@ -17,6 +17,7 @@ from authentik.enterprise.stages.authenticator_endpoint_gdtc.models import (
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
from authentik.stages.user_login.stage import PLAN_CONTEXT_METHOD_ARGS_KNOWN_DEVICE
# Header we get from chrome that initiates verified access
HEADER_DEVICE_TRUST = "X-Device-Trust"
@@ -27,6 +28,8 @@ HEADER_ACCESS_CHALLENGE_RESPONSE = "X-Verified-Access-Challenge-Response"
# Header value for x-device-trust that initiates the flow
DEVICE_TRUST_VERIFIED_ACCESS = "VerifiedAccess"
PLAN_CONTEXT_METHOD_ARGS_ENDPOINTS = "endpoints"
@method_decorator(xframe_options_sameorigin, name="dispatch")
class GoogleChromeDeviceTrustConnector(View):
@@ -81,7 +84,14 @@ class GoogleChromeDeviceTrustConnector(View):
)
flow_plan.context.setdefault(PLAN_CONTEXT_METHOD, "trusted_endpoint")
flow_plan.context.setdefault(PLAN_CONTEXT_METHOD_ARGS, {})
flow_plan.context[PLAN_CONTEXT_METHOD_ARGS].setdefault("endpoints", [])
flow_plan.context[PLAN_CONTEXT_METHOD_ARGS]["endpoints"].append(response)
flow_plan.context[PLAN_CONTEXT_METHOD_ARGS].setdefault(
PLAN_CONTEXT_METHOD_ARGS_ENDPOINTS, []
)
flow_plan.context[PLAN_CONTEXT_METHOD_ARGS][PLAN_CONTEXT_METHOD_ARGS_ENDPOINTS].append(
response
)
flow_plan.context[PLAN_CONTEXT_METHOD_ARGS].setdefault(
PLAN_CONTEXT_METHOD_ARGS_KNOWN_DEVICE, True
)
request.session[SESSION_KEY_PLAN] = flow_plan
return TemplateResponse(request, "stages/authenticator_endpoint/google_chrome_dtc.html")

View File

@@ -20,7 +20,7 @@ from authentik.core.models import Group, User
from authentik.events.models import Event, EventAction, Notification
from authentik.events.utils import model_to_dict
from authentik.lib.sentry import should_ignore_exception
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.errors import exception_to_dict
from authentik.stages.authenticator_static.models import StaticToken
IGNORED_MODELS = tuple(
@@ -170,14 +170,16 @@ class AuditMiddleware:
thread = EventNewThread(
EventAction.SUSPICIOUS_REQUEST,
request,
message=exception_to_string(exception),
message=str(exception),
exception=exception_to_dict(exception),
)
thread.run()
elif not should_ignore_exception(exception):
thread = EventNewThread(
EventAction.SYSTEM_EXCEPTION,
request,
message=exception_to_string(exception),
message=str(exception),
exception=exception_to_dict(exception),
)
thread.run()

View File

@@ -38,6 +38,7 @@ from authentik.events.utils import (
)
from authentik.lib.models import DomainlessURLValidator, SerializerModel
from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.utils.errors import exception_to_dict
from authentik.lib.utils.http import get_http_session
from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.models import PolicyBindingModel
@@ -163,6 +164,12 @@ class Event(SerializerModel, ExpiringModel):
event = Event(action=action, app=app, context=cleaned_kwargs)
return event
def with_exception(self, exc: Exception) -> "Event":
"""Add data from 'exc' to the event in a database-saveable format"""
self.context.setdefault("message", str(exc))
self.context["exception"] = exception_to_dict(exc)
return self
def set_user(self, user: User) -> "Event":
"""Set `.user` based on user, ensuring the correct attributes are copied.
This should only be used when self.from_http is *not* used."""

View File

@@ -127,8 +127,8 @@ class SystemTask(TenantTask):
)
Event.new(
EventAction.SYSTEM_TASK_EXCEPTION,
message=f"Task {self.__name__} encountered an error: {exception_to_string(exc)}",
).save()
message=f"Task {self.__name__} encountered an error",
).with_exception(exc).save()
def run(self, *args, **kwargs):
raise NotImplementedError

View File

@@ -62,6 +62,7 @@ def event_trigger_handler(event_uuid: str, trigger_name: str):
policy_engine.mode = PolicyEngineMode.MODE_ANY
policy_engine.empty_result = False
policy_engine.use_cache = False
policy_engine.request.obj = event
policy_engine.request.context["event"] = event
policy_engine.build()
result = policy_engine.result

View File

@@ -56,7 +56,6 @@ from authentik.flows.planner import (
)
from authentik.flows.stage import AccessDeniedStage, StageView
from authentik.lib.sentry import SentryIgnoredException, should_ignore_exception
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.reflection import all_subclasses, class_to_path
from authentik.lib.utils.urls import is_url_absolute, redirect_with_qs
from authentik.policies.engine import PolicyEngine
@@ -239,8 +238,8 @@ class FlowExecutorView(APIView):
capture_exception(exc)
Event.new(
action=EventAction.SYSTEM_EXCEPTION,
message=exception_to_string(exc),
).from_http(self.request)
message="System exception during flow execution.",
).with_exception(exc).from_http(self.request)
challenge = FlowErrorChallenge(self.request, exc)
challenge.is_valid(raise_exception=True)
return to_stage_response(self.request, HttpChallengeResponse(challenge))

View File

@@ -367,6 +367,8 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
# See https://github.com/goauthentik/authentik/issues/14320
pool_options = False
conn_options = config.get_dict_from_b64_json("postgresql.conn_options", default={})
db = {
"default": {
"ENGINE": "authentik.root.db",
@@ -381,6 +383,7 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
"sslcert": config.get("postgresql.sslcert"),
"sslkey": config.get("postgresql.sslkey"),
"pool": pool_options,
**conn_options,
},
"CONN_MAX_AGE": config.get_optional_int("postgresql.conn_max_age", 0),
"CONN_HEALTH_CHECKS": config.get_bool("postgresql.conn_health_checks", False),
@@ -410,8 +413,14 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
if conn_max_age is not UNSET:
db["default"]["CONN_MAX_AGE"] = conn_max_age
all_replica_conn_options = config.get_dict_from_b64_json(
"postgresql.replica_conn_options",
default={},
)
for replica in config.get_keys("postgresql.read_replicas"):
_database = deepcopy(db["default"])
for setting, current_value in db["default"].items():
if isinstance(current_value, dict):
continue
@@ -420,12 +429,23 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
)
if override is not UNSET:
_database[setting] = override
for option in conn_options.keys():
_database["OPTIONS"].pop(option, None)
for setting in db["default"]["OPTIONS"].keys():
override = config.get(
f"postgresql.read_replicas.{replica}.{setting.lower()}", default=UNSET
)
if override is not UNSET:
_database["OPTIONS"][setting] = override
_database["OPTIONS"].update(all_replica_conn_options)
replica_conn_options = config.get_dict_from_b64_json(
f"postgresql.read_replicas.{replica}.conn_options", default={}
)
_database["OPTIONS"].update(replica_conn_options)
db[f"replica_{replica}"] = _database
return db

View File

@@ -8,9 +8,9 @@
# make gen-dev-config
# ```
#
# You may edit the generated file to override the configuration below.
# You may edit the generated file to override the configuration below.
#
# When making modifying the default configuration file,
# 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.

View File

@@ -14,7 +14,6 @@ from authentik.events.models import Event, EventAction
from authentik.lib.expression.exceptions import ControlFlowException
from authentik.lib.sync.mapper import PropertyMappingManager
from authentik.lib.sync.outgoing.exceptions import NotFoundSyncException, StopSync
from authentik.lib.utils.errors import exception_to_string
if TYPE_CHECKING:
from django.db.models import Model
@@ -106,9 +105,9 @@ class BaseOutgoingSyncClient[
# Value error can be raised when assigning invalid data to an attribute
Event.new(
EventAction.CONFIGURATION_ERROR,
message=f"Failed to evaluate property-mapping {exception_to_string(exc)}",
message="Failed to evaluate property-mapping",
mapping=exc.mapping,
).save()
).with_exception(exc).save()
raise StopSync(exc, obj, exc.mapping) from exc
if not raw_final_object:
raise StopSync(ValueError("No mappings configured"), obj)

View File

@@ -494,6 +494,65 @@ class TestConfig(TestCase):
},
)
def test_db_conn_options(self):
config = ConfigLoader()
config.set(
"postgresql.conn_options",
base64.b64encode(
dumps(
{
"connect_timeout": "10",
}
).encode()
).decode(),
)
config.set("postgresql.read_replicas.0.host", "bar")
conf = django_db_config(config)
self.assertEqual(
conf["default"]["OPTIONS"]["connect_timeout"],
"10",
)
self.assertNotIn("connect_timeout", conf["replica_0"]["OPTIONS"])
def test_db_conn_options_read_replicas(self):
config = ConfigLoader()
config.set(
"postgresql.replica_conn_options",
base64.b64encode(
dumps(
{
"connect_timeout": "10",
}
).encode()
).decode(),
)
config.set("postgresql.read_replicas.0.host", "bar")
config.set("postgresql.read_replicas.1.host", "bar")
config.set(
"postgresql.read_replicas.1.conn_options",
base64.b64encode(
dumps(
{
"connect_timeout": "20",
}
).encode()
).decode(),
)
conf = django_db_config(config)
self.assertNotIn("connect_timeout", conf["default"]["OPTIONS"])
self.assertEqual(
conf["replica_0"]["OPTIONS"]["connect_timeout"],
"10",
)
self.assertEqual(
conf["replica_1"]["OPTIONS"]["connect_timeout"],
"20",
)
# FIXME: Temporarily force pool to be deactivated.
# See https://github.com/goauthentik/authentik/issues/14320
# def test_db_pool(self):

View File

@@ -2,6 +2,8 @@
from traceback import extract_tb
from structlog.tracebacks import ExceptionDictTransformer
from authentik.lib.utils.reflection import class_to_path
TRACEBACK_HEADER = "Traceback (most recent call last):"
@@ -17,3 +19,8 @@ def exception_to_string(exc: Exception) -> str:
f"{class_to_path(exc.__class__)}: {str(exc)}",
]
)
def exception_to_dict(exc: Exception) -> dict:
"""Format exception as a dictionary"""
return ExceptionDictTransformer()((type(exc), exc, exc.__traceback__))

View File

@@ -35,7 +35,6 @@ from authentik.events.models import Event, EventAction
from authentik.lib.config import CONFIG
from authentik.lib.models import InheritanceForeignKey, SerializerModel
from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.utils.errors import exception_to_string
from authentik.outposts.controllers.k8s.utils import get_namespace
OUR_VERSION = parse(__version__)
@@ -326,9 +325,8 @@ class Outpost(SerializerModel, ManagedModel):
"While setting the permissions for the service-account, a "
"permission was not found: Check "
"https://goauthentik.io/docs/troubleshooting/missing_permission"
)
+ exception_to_string(exc),
).set_user(user).save()
),
).with_exception(exc).set_user(user).save()
else:
app_label, perm = model_or_perm.split(".")
permission = Permission.objects.filter(

View File

@@ -1,11 +1,11 @@
"""authentik policy engine"""
from collections.abc import Iterator
from collections.abc import Iterable
from multiprocessing import Pipe, current_process
from multiprocessing.connection import Connection
from time import perf_counter
from django.core.cache import cache
from django.db.models import Count, Q, QuerySet
from django.http import HttpRequest
from sentry_sdk import start_span
from sentry_sdk.tracing import Span
@@ -67,14 +67,11 @@ class PolicyEngine:
self.__processes: list[PolicyProcessInfo] = []
self.use_cache = True
self.__expected_result_count = 0
self.__static_result: PolicyResult | None = None
def iterate_bindings(self) -> Iterator[PolicyBinding]:
def bindings(self) -> QuerySet[PolicyBinding] | Iterable[PolicyBinding]:
"""Make sure all Policies are their respective classes"""
return (
PolicyBinding.objects.filter(target=self.__pbm, enabled=True)
.order_by("order")
.iterator()
)
return PolicyBinding.objects.filter(target=self.__pbm, enabled=True).order_by("order")
def _check_policy_type(self, binding: PolicyBinding):
"""Check policy type, make sure it's not the root class as that has no logic implemented"""
@@ -84,30 +81,66 @@ class PolicyEngine:
def _check_cache(self, binding: PolicyBinding):
if not self.use_cache:
return False
before = perf_counter()
key = cache_key(binding, self.request)
cached_policy = cache.get(key, None)
duration = max(perf_counter() - before, 0)
if not cached_policy:
return False
self.logger.debug(
"P_ENG: Taking result from cache",
binding=binding,
cache_key=key,
request=self.request,
)
HIST_POLICIES_EXECUTION_TIME.labels(
# It's a bit silly to time this, but
with HIST_POLICIES_EXECUTION_TIME.labels(
binding_order=binding.order,
binding_target_type=binding.target_type,
binding_target_name=binding.target_name,
object_pk=str(self.request.obj.pk),
object_type=class_to_path(self.request.obj.__class__),
mode="cache_retrieve",
).observe(duration)
# It's a bit silly to time this, but
).time():
key = cache_key(binding, self.request)
cached_policy = cache.get(key, None)
if not cached_policy:
return False
self.logger.debug(
"P_ENG: Taking result from cache",
binding=binding,
cache_key=key,
request=self.request,
)
self.__cached_policies.append(cached_policy)
return True
def compute_static_bindings(self, bindings: QuerySet[PolicyBinding]):
"""Check static bindings if possible"""
aggrs = {
"total": Count(
"pk", filter=Q(Q(group__isnull=False) | Q(user__isnull=False), policy=None)
),
}
if self.request.user.pk:
all_groups = self.request.user.all_groups()
aggrs["passing"] = Count(
"pk",
filter=Q(
Q(
Q(user=self.request.user) | Q(group__in=all_groups),
negate=False,
)
| Q(
Q(~Q(user=self.request.user), user__isnull=False)
| Q(~Q(group__in=all_groups), group__isnull=False),
negate=True,
),
enabled=True,
),
)
matched_bindings = bindings.aggregate(**aggrs)
passing = False
if matched_bindings["total"] == 0 and matched_bindings.get("passing", 0) == 0:
# If we didn't find any static bindings, do nothing
return
self.logger.debug("P_ENG: Found static bindings", **matched_bindings)
if matched_bindings.get("passing", 0) > 0:
# Any passing static binding -> passing
passing = True
elif matched_bindings["total"] > 0 and matched_bindings.get("passing", 0) < 1:
# No matching static bindings but at least one is configured -> not passing
passing = False
self.__static_result = PolicyResult(passing)
def build(self) -> "PolicyEngine":
"""Build wrapper which monitors performance"""
with (
@@ -123,7 +156,12 @@ class PolicyEngine:
span: Span
span.set_data("pbm", self.__pbm)
span.set_data("request", self.request)
for binding in self.iterate_bindings():
bindings = self.bindings()
policy_bindings = bindings
if isinstance(bindings, QuerySet):
self.compute_static_bindings(bindings)
policy_bindings = [x for x in bindings if x.policy]
for binding in policy_bindings:
self.__expected_result_count += 1
self._check_policy_type(binding)
@@ -153,10 +191,13 @@ class PolicyEngine:
@property
def result(self) -> PolicyResult:
"""Get policy-checking result"""
self.__processes.sort(key=lambda x: x.binding.order)
process_results: list[PolicyResult] = [x.result for x in self.__processes if x.result]
all_results = list(process_results + self.__cached_policies)
if len(all_results) < self.__expected_result_count: # pragma: no cover
raise AssertionError("Got less results than polices")
if self.__static_result:
all_results.append(self.__static_result)
# No results, no policies attached -> passing
if len(all_results) == 0:
return PolicyResult(self.empty_result)

View File

@@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Optional
from django.http import HttpRequest
from structlog.stdlib import get_logger
from authentik.events.models import Event
from authentik.flows.planner import PLAN_CONTEXT_SSO
from authentik.lib.expression.evaluator import BaseEvaluator
from authentik.policies.exceptions import PolicyException
@@ -45,6 +46,10 @@ class PolicyEvaluator(BaseEvaluator):
self.set_http_request(request.http_request)
self._context["request"] = request
self._context["context"] = request.context
if request.obj and isinstance(request.obj, Event):
self._context["ak_client_ip"] = ip_address(
request.obj.client_ip or ClientIPMiddleware.default_ip
)
def set_http_request(self, request: HttpRequest):
"""Update context based on http request"""

View File

@@ -10,7 +10,7 @@ from structlog.stdlib import get_logger
from authentik.events.models import Event, EventAction
from authentik.lib.config import CONFIG
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.errors import exception_to_dict
from authentik.lib.utils.reflection import class_to_path
from authentik.policies.apps import HIST_POLICIES_EXECUTION_TIME
from authentik.policies.exceptions import PolicyException
@@ -95,10 +95,13 @@ class PolicyProcess(PROCESS_CLASS):
except PolicyException as exc:
# Either use passed original exception or whatever we have
src_exc = exc.src_exc if exc.src_exc else exc
error_string = exception_to_string(src_exc)
# Create policy exception event, only when we're not debugging
if not self.request.debug:
self.create_event(EventAction.POLICY_EXCEPTION, message=error_string)
self.create_event(
EventAction.POLICY_EXCEPTION,
message="Policy failed to execute",
exception=exception_to_dict(src_exc),
)
LOGGER.debug("P_ENG(proc): error, using failure result", exc=src_exc)
policy_result = PolicyResult(self.binding.failure_result, str(src_exc))
policy_result.source_binding = self.binding
@@ -143,5 +146,5 @@ class PolicyProcess(PROCESS_CLASS):
try:
self.connection.send(self.profiling_wrapper())
except Exception as exc:
LOGGER.warning("Policy failed to run", exc=exception_to_string(exc))
LOGGER.warning("Policy failed to run", exc=exc)
self.connection.send(PolicyResult(False, str(exc)))

View File

@@ -1,9 +1,12 @@
"""policy engine tests"""
from django.core.cache import cache
from django.db import connections
from django.test import TestCase
from django.test.utils import CaptureQueriesContext
from authentik.core.tests.utils import create_test_admin_user
from authentik.core.models import Group
from authentik.core.tests.utils import create_test_user
from authentik.lib.generators import generate_id
from authentik.policies.dummy.models import DummyPolicy
from authentik.policies.engine import PolicyEngine
@@ -19,7 +22,7 @@ class TestPolicyEngine(TestCase):
def setUp(self):
clear_policy_cache()
self.user = create_test_admin_user()
self.user = create_test_user()
self.policy_false = DummyPolicy.objects.create(
name=generate_id(), result=False, wait_min=0, wait_max=1
)
@@ -127,3 +130,58 @@ class TestPolicyEngine(TestCase):
self.assertEqual(len(cache.keys(f"{CACHE_PREFIX}{binding.policy_binding_uuid.hex}*")), 1)
self.assertEqual(engine.build().passing, False)
self.assertEqual(len(cache.keys(f"{CACHE_PREFIX}{binding.policy_binding_uuid.hex}*")), 1)
def test_engine_static_bindings(self):
"""Test static bindings"""
group_a = Group.objects.create(name=generate_id())
group_b = Group.objects.create(name=generate_id())
group_b.users.add(self.user)
user = create_test_user()
for case in [
{
"message": "Group, not member",
"binding_args": {"group": group_a},
"passing": False,
},
{
"message": "Group, member",
"binding_args": {"group": group_b},
"passing": True,
},
{
"message": "User, other",
"binding_args": {"user": user},
"passing": False,
},
{
"message": "User, same",
"binding_args": {"user": self.user},
"passing": True,
},
]:
with self.subTest():
pbm = PolicyBindingModel.objects.create()
for x in range(1000):
PolicyBinding.objects.create(target=pbm, order=x, **case["binding_args"])
engine = PolicyEngine(pbm, self.user)
engine.use_cache = False
with CaptureQueriesContext(connections["default"]) as ctx:
engine.build()
self.assertLess(ctx.final_queries, 1000)
self.assertEqual(engine.result.passing, case["passing"])
def test_engine_group_complex(self):
"""Test more complex group setups"""
group_a = Group.objects.create(name=generate_id())
group_b = Group.objects.create(name=generate_id(), parent=group_a)
user = create_test_user()
group_b.users.add(user)
pbm = PolicyBindingModel.objects.create()
PolicyBinding.objects.create(target=pbm, order=0, group=group_a)
engine = PolicyEngine(pbm, user)
engine.use_cache = False
with CaptureQueriesContext(connections["default"]) as ctx:
engine.build()
self.assertLess(ctx.final_queries, 1000)
self.assertTrue(engine.result.passing)

View File

@@ -29,13 +29,12 @@ class TestPolicyProcess(TestCase):
def setUp(self):
clear_policy_cache()
self.factory = RequestFactory()
self.user = User.objects.create_user(username="policyuser")
self.user = User.objects.create_user(username=generate_id())
def test_group_passing(self):
"""Test binding to group"""
group = Group.objects.create(name="test-group")
group = Group.objects.create(name=generate_id())
group.users.add(self.user)
group.save()
binding = PolicyBinding(group=group)
request = PolicyRequest(self.user)
@@ -44,8 +43,7 @@ class TestPolicyProcess(TestCase):
def test_group_negative(self):
"""Test binding to group"""
group = Group.objects.create(name="test-group")
group.save()
group = Group.objects.create(name=generate_id())
binding = PolicyBinding(group=group)
request = PolicyRequest(self.user)
@@ -115,8 +113,10 @@ class TestPolicyProcess(TestCase):
def test_exception(self):
"""Test policy execution"""
policy = Policy.objects.create(name="test-execution")
binding = PolicyBinding(policy=policy, target=Application.objects.create(name="test"))
policy = Policy.objects.create(name=generate_id())
binding = PolicyBinding(
policy=policy, target=Application.objects.create(name=generate_id())
)
request = PolicyRequest(self.user)
response = PolicyProcess(binding, request, None).execute()
@@ -125,13 +125,15 @@ class TestPolicyProcess(TestCase):
def test_execution_logging(self):
"""Test policy execution creates event"""
policy = DummyPolicy.objects.create(
name="test-execution-logging",
name=generate_id(),
result=False,
wait_min=0,
wait_max=1,
execution_logging=True,
)
binding = PolicyBinding(policy=policy, target=Application.objects.create(name="test"))
binding = PolicyBinding(
policy=policy, target=Application.objects.create(name=generate_id())
)
http_request = self.factory.get(reverse("authentik_api:user-impersonate-end"))
http_request.user = self.user
@@ -186,13 +188,15 @@ class TestPolicyProcess(TestCase):
def test_execution_logging_anonymous(self):
"""Test policy execution creates event with anonymous user"""
policy = DummyPolicy.objects.create(
name="test-execution-logging-anon",
name=generate_id(),
result=False,
wait_min=0,
wait_max=1,
execution_logging=True,
)
binding = PolicyBinding(policy=policy, target=Application.objects.create(name="test"))
binding = PolicyBinding(
policy=policy, target=Application.objects.create(name=generate_id())
)
user = AnonymousUser()
@@ -219,9 +223,9 @@ class TestPolicyProcess(TestCase):
def test_raises(self):
"""Test policy that raises error"""
policy_raises = ExpressionPolicy.objects.create(name="raises", expression="{{ 0/0 }}")
policy_raises = ExpressionPolicy.objects.create(name=generate_id(), expression="{{ 0/0 }}")
binding = PolicyBinding(
policy=policy_raises, target=Application.objects.create(name="test")
policy=policy_raises, target=Application.objects.create(name=generate_id())
)
request = PolicyRequest(self.user)
@@ -237,4 +241,4 @@ class TestPolicyProcess(TestCase):
self.assertEqual(len(events), 1)
event = events.first()
self.assertEqual(event.user["username"], self.user.username)
self.assertIn("division by zero", event.context["message"])
self.assertIn("Policy failed to execute", event.context["message"])

View File

@@ -15,12 +15,14 @@ class OAuth2Error(SentryIgnoredException):
error: str
description: str
cause: str | None = None
def create_dict(self):
def create_dict(self, request: HttpRequest):
"""Return error as dict for JSON Rendering"""
return {
"error": self.error,
"error_description": self.description,
"request_id": request.request_id,
}
def __repr__(self) -> str:
@@ -31,9 +33,15 @@ class OAuth2Error(SentryIgnoredException):
return Event.new(
EventAction.CONFIGURATION_ERROR,
message=message or self.description,
cause=self.cause,
error=self.error,
**kwargs,
)
def with_cause(self, cause: str):
self.cause = cause
return self
class RedirectUriError(OAuth2Error):
"""The request fails due to a missing, invalid, or mismatching
@@ -243,13 +251,14 @@ class TokenRevocationError(OAuth2Error):
self.description = self.errors[error]
class DeviceCodeError(OAuth2Error):
class DeviceCodeError(TokenError):
"""
Device-code flow errors
See https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
Can also use codes form TokenError
"""
errors = {
errors = TokenError.errors | {
"authorization_pending": (
"The authorization request is still pending as the end user hasn't "
"yet completed the user-interaction steps"
@@ -261,10 +270,15 @@ class DeviceCodeError(OAuth2Error):
"authorization request but SHOULD wait for user interaction before "
"restarting to avoid unnecessary polling."
),
"slow_down": (
'A variant of "authorization_pending", the authorization request is'
"still pending and polling should continue, but the interval MUST"
"be increased by 5 seconds for this and all subsequent requests."
),
}
def __init__(self, error: str):
super().__init__()
super().__init__(error)
self.error = error
self.description = self.errors[error]

View File

@@ -12,7 +12,7 @@ from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.events.models import Event, EventAction
from authentik.lib.generators import generate_id
from authentik.lib.utils.time import timedelta_from_string
from authentik.providers.oauth2.constants import TOKEN_TYPE
from authentik.providers.oauth2.constants import SCOPE_OFFLINE_ACCESS, SCOPE_OPENID, TOKEN_TYPE
from authentik.providers.oauth2.errors import AuthorizeError, ClientIdError, RedirectUriError
from authentik.providers.oauth2.models import (
AccessToken,
@@ -43,7 +43,7 @@ class TestAuthorize(OAuthTestCase):
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid/Foo")],
)
with self.assertRaises(AuthorizeError):
with self.assertRaises(AuthorizeError) as cm:
request = self.factory.get(
"/",
data={
@@ -53,6 +53,7 @@ class TestAuthorize(OAuthTestCase):
},
)
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.error, "unsupported_response_type")
def test_invalid_client_id(self):
"""Test invalid client ID"""
@@ -68,7 +69,7 @@ class TestAuthorize(OAuthTestCase):
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid/Foo")],
)
with self.assertRaises(AuthorizeError):
with self.assertRaises(AuthorizeError) as cm:
request = self.factory.get(
"/",
data={
@@ -79,19 +80,30 @@ class TestAuthorize(OAuthTestCase):
},
)
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.error, "request_not_supported")
def test_invalid_redirect_uri(self):
"""test missing/invalid redirect URI"""
def test_invalid_redirect_uri_missing(self):
"""test missing redirect URI"""
OAuth2Provider.objects.create(
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
)
with self.assertRaises(RedirectUriError):
with self.assertRaises(RedirectUriError) as cm:
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
OAuthAuthorizationParams.from_request(request)
with self.assertRaises(RedirectUriError):
self.assertEqual(cm.exception.cause, "redirect_uri_missing")
def test_invalid_redirect_uri(self):
"""test invalid redirect URI"""
OAuth2Provider.objects.create(
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
)
with self.assertRaises(RedirectUriError) as cm:
request = self.factory.get(
"/",
data={
@@ -101,6 +113,7 @@ class TestAuthorize(OAuthTestCase):
},
)
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.cause, "redirect_uri_no_match")
def test_blocked_redirect_uri(self):
"""test missing/invalid redirect URI"""
@@ -108,9 +121,9 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "data:local.invalid")],
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "data:localhost")],
)
with self.assertRaises(RedirectUriError):
with self.assertRaises(RedirectUriError) as cm:
request = self.factory.get(
"/",
data={
@@ -120,6 +133,7 @@ class TestAuthorize(OAuthTestCase):
},
)
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.cause, "redirect_uri_forbidden_scheme")
def test_invalid_redirect_uri_empty(self):
"""test missing/invalid redirect URI"""
@@ -129,9 +143,6 @@ class TestAuthorize(OAuthTestCase):
authorization_flow=create_test_flow(),
redirect_uris=[],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
OAuthAuthorizationParams.from_request(request)
request = self.factory.get(
"/",
data={
@@ -150,12 +161,9 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid?")],
redirect_uris=[RedirectURI(RedirectURIMatchingMode.REGEX, "http://local.invalid?")],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
OAuthAuthorizationParams.from_request(request)
with self.assertRaises(RedirectUriError):
with self.assertRaises(RedirectUriError) as cm:
request = self.factory.get(
"/",
data={
@@ -165,6 +173,7 @@ class TestAuthorize(OAuthTestCase):
},
)
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.cause, "redirect_uri_no_match")
def test_redirect_uri_invalid_regex(self):
"""test missing/invalid redirect URI (invalid regex)"""
@@ -172,12 +181,9 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "+")],
redirect_uris=[RedirectURI(RedirectURIMatchingMode.REGEX, "+")],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
OAuthAuthorizationParams.from_request(request)
with self.assertRaises(RedirectUriError):
with self.assertRaises(RedirectUriError) as cm:
request = self.factory.get(
"/",
data={
@@ -187,23 +193,22 @@ class TestAuthorize(OAuthTestCase):
},
)
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.cause, "redirect_uri_no_match")
def test_empty_redirect_uri(self):
"""test empty redirect URI (configure in provider)"""
def test_redirect_uri_regex(self):
"""test valid redirect URI (regex)"""
OAuth2Provider.objects.create(
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.REGEX, ".+")],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
OAuthAuthorizationParams.from_request(request)
request = self.factory.get(
"/",
data={
"response_type": "code",
"client_id": "test",
"redirect_uri": "http://localhost",
"redirect_uri": "http://foo.bar.baz",
},
)
OAuthAuthorizationParams.from_request(request)
@@ -258,7 +263,7 @@ class TestAuthorize(OAuthTestCase):
GrantTypes.IMPLICIT,
)
# Implicit without openid scope
with self.assertRaises(AuthorizeError):
with self.assertRaises(AuthorizeError) as cm:
request = self.factory.get(
"/",
data={
@@ -285,7 +290,7 @@ class TestAuthorize(OAuthTestCase):
self.assertEqual(
OAuthAuthorizationParams.from_request(request).grant_type, GrantTypes.HYBRID
)
with self.assertRaises(AuthorizeError):
with self.assertRaises(AuthorizeError) as cm:
request = self.factory.get(
"/",
data={
@@ -295,6 +300,7 @@ class TestAuthorize(OAuthTestCase):
},
)
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.error, "unsupported_response_type")
def test_full_code(self):
"""Test full authorization"""
@@ -613,3 +619,54 @@ class TestAuthorize(OAuthTestCase):
},
},
)
def test_openid_missing_invalid(self):
"""test request requiring an OpenID scope to be set"""
OAuth2Provider.objects.create(
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
)
request = self.factory.get(
"/",
data={
"response_type": "id_token",
"client_id": "test",
"redirect_uri": "http://localhost",
"scope": "",
},
)
with self.assertRaises(AuthorizeError) as cm:
OAuthAuthorizationParams.from_request(request)
self.assertEqual(cm.exception.cause, "scope_openid_missing")
@apply_blueprint("system/providers-oauth2.yaml")
def test_offline_access_invalid(self):
"""test request for offline_access with invalid response type"""
provider = OAuth2Provider.objects.create(
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
managed__in=[
"goauthentik.io/providers/oauth2/scope-openid",
"goauthentik.io/providers/oauth2/scope-offline_access",
]
)
)
request = self.factory.get(
"/",
data={
"response_type": "id_token",
"client_id": "test",
"redirect_uri": "http://localhost",
"scope": f"{SCOPE_OPENID} {SCOPE_OFFLINE_ACCESS}",
"nonce": generate_id(),
},
)
parsed = OAuthAuthorizationParams.from_request(request)
self.assertNotIn(SCOPE_OFFLINE_ACCESS, parsed.scope)

View File

@@ -68,7 +68,11 @@ class TestTokenClientCredentialsStandard(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_no_provider(self):
@@ -87,7 +91,11 @@ class TestTokenClientCredentialsStandard(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_permission_denied(self):
@@ -110,7 +118,11 @@ class TestTokenClientCredentialsStandard(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_incorrect_scopes(self):

View File

@@ -68,7 +68,11 @@ class TestTokenClientCredentialsStandardCompat(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_wrong_token(self):
@@ -85,7 +89,11 @@ class TestTokenClientCredentialsStandardCompat(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_no_provider(self):
@@ -104,7 +112,11 @@ class TestTokenClientCredentialsStandardCompat(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_permission_denied(self):
@@ -127,7 +139,11 @@ class TestTokenClientCredentialsStandardCompat(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_successful(self):

View File

@@ -68,7 +68,11 @@ class TestTokenClientCredentialsUserNamePassword(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_wrong_token(self):
@@ -86,7 +90,11 @@ class TestTokenClientCredentialsUserNamePassword(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_no_provider(self):
@@ -106,7 +114,11 @@ class TestTokenClientCredentialsUserNamePassword(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_permission_denied(self):
@@ -130,7 +142,11 @@ class TestTokenClientCredentialsUserNamePassword(OAuthTestCase):
self.assertEqual(response.status_code, 400)
self.assertJSONEqual(
response.content.decode(),
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
{
"error": "invalid_grant",
"error_description": TokenError.errors["invalid_grant"],
"request_id": response.headers["X-authentik-id"],
},
)
def test_successful(self):

View File

@@ -80,6 +80,7 @@ class TestTokenPKCE(OAuthTestCase):
"revoked, does not match the redirection URI used in the authorization "
"request, or was issued to another client"
),
"request_id": response.headers["X-authentik-id"],
},
)
self.assertEqual(response.status_code, 400)
@@ -136,6 +137,7 @@ class TestTokenPKCE(OAuthTestCase):
"revoked, does not match the redirection URI used in the authorization "
"request, or was issued to another client"
),
"request_id": response.headers["X-authentik-id"],
},
)
self.assertEqual(response.status_code, 400)

View File

@@ -6,6 +6,7 @@ from django.urls import include, path
from authentik.providers.oauth2.views.authorize import AuthorizationFlowInitView
from authentik.providers.oauth2.views.device_init import DeviceEntryView
from authentik.providers.oauth2.views.github import GitHubUserTeamsView, GitHubUserView
from authentik.providers.oauth2.views.provider import ProviderInfoView
from authentik.providers.oauth2.views.token import TokenView
github_urlpatterns = [
@@ -40,4 +41,9 @@ urlpatterns = [
),
name="device-login",
),
path(
".well-known/oauth-authorization-server/application/o/<slug:application_slug>/",
ProviderInfoView.as_view(),
name="providers-oauth2-authorization-server-metadata",
),
]

View File

@@ -190,7 +190,7 @@ class OAuthAuthorizationParams:
allowed_redirect_urls = self.provider.redirect_uris
if not self.redirect_uri:
LOGGER.warning("Missing redirect uri.")
raise RedirectUriError("", allowed_redirect_urls)
raise RedirectUriError("", allowed_redirect_urls).with_cause("redirect_uri_missing")
if len(allowed_redirect_urls) < 1:
LOGGER.info("Setting redirect for blank redirect_uris", redirect=self.redirect_uri)
@@ -219,10 +219,14 @@ class OAuthAuthorizationParams:
provider=self.provider,
)
if not match_found:
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls)
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls).with_cause(
"redirect_uri_no_match"
)
# Check against forbidden schemes
if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES:
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls)
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls).with_cause(
"redirect_uri_forbidden_scheme"
)
def check_scope(self, github_compat=False):
"""Ensure openid scope is set in Hybrid flows, or when requesting an id_token"""
@@ -251,7 +255,9 @@ class OAuthAuthorizationParams:
or self.response_type in [ResponseTypes.ID_TOKEN, ResponseTypes.ID_TOKEN_TOKEN]
):
LOGGER.warning("Missing 'openid' scope.")
raise AuthorizeError(self.redirect_uri, "invalid_scope", self.grant_type, self.state)
raise AuthorizeError(
self.redirect_uri, "invalid_scope", self.grant_type, self.state
).with_cause("scope_openid_missing")
if SCOPE_OFFLINE_ACCESS in self.scope:
# https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
# Don't explicitly request consent with offline_access, as the spec allows for
@@ -286,7 +292,9 @@ class OAuthAuthorizationParams:
return
if not self.nonce:
LOGGER.warning("Missing nonce for OpenID Request")
raise AuthorizeError(self.redirect_uri, "invalid_request", self.grant_type, self.state)
raise AuthorizeError(
self.redirect_uri, "invalid_request", self.grant_type, self.state
).with_cause("nonce_missing")
def check_code_challenge(self):
"""PKCE validation of the transformation method."""
@@ -345,10 +353,10 @@ class AuthorizationFlowInitView(PolicyAccessView):
self.request, github_compat=self.github_compat
)
except AuthorizeError as error:
LOGGER.warning(error.description, redirect_uri=error.redirect_uri)
LOGGER.warning(error.description, redirect_uri=error.redirect_uri, cause=error.cause)
raise RequestValidationError(error.get_response(self.request)) from None
except OAuth2Error as error:
LOGGER.warning(error.description)
LOGGER.warning(error.description, cause=error.cause)
raise RequestValidationError(
bad_request_message(self.request, error.description, title=error.error)
) from None

View File

@@ -2,7 +2,7 @@
from urllib.parse import urlencode
from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest, JsonResponse
from django.http import HttpRequest, HttpResponse
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.timezone import now
@@ -14,7 +14,9 @@ from structlog.stdlib import get_logger
from authentik.core.models import Application
from authentik.lib.config import CONFIG
from authentik.lib.utils.time import timedelta_from_string
from authentik.providers.oauth2.errors import DeviceCodeError
from authentik.providers.oauth2.models import DeviceToken, OAuth2Provider
from authentik.providers.oauth2.utils import TokenResponse
from authentik.providers.oauth2.views.device_init import QS_KEY_CODE
LOGGER = get_logger()
@@ -28,38 +30,36 @@ class DeviceView(View):
provider: OAuth2Provider
scopes: list[str] = []
def parse_request(self) -> HttpResponse | None:
def parse_request(self):
"""Parse incoming request"""
client_id = self.request.POST.get("client_id", None)
if not client_id:
return HttpResponseBadRequest()
provider = OAuth2Provider.objects.filter(
client_id=client_id,
).first()
raise DeviceCodeError("invalid_client")
provider = OAuth2Provider.objects.filter(client_id=client_id).first()
if not provider:
return HttpResponseBadRequest()
raise DeviceCodeError("invalid_client")
try:
_ = provider.application
except Application.DoesNotExist:
return HttpResponseBadRequest()
raise DeviceCodeError("invalid_client") from None
self.provider = provider
self.client_id = client_id
self.scopes = self.request.POST.get("scope", "").split(" ")
return None
def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
throttle = AnonRateThrottle()
throttle.rate = CONFIG.get("throttle.providers.oauth2.device", "20/hour")
throttle.num_requests, throttle.duration = throttle.parse_rate(throttle.rate)
if not throttle.allow_request(request, self):
return HttpResponse(status=429)
return TokenResponse(DeviceCodeError("slow_down").create_dict(request), status=429)
return super().dispatch(request, *args, **kwargs)
def post(self, request: HttpRequest) -> HttpResponse:
"""Generate device token"""
resp = self.parse_request()
if resp:
return resp
try:
self.parse_request()
except DeviceCodeError as exc:
return TokenResponse(exc.create_dict(request), status=400)
until = timedelta_from_string(self.provider.access_code_validity)
token: DeviceToken = DeviceToken.objects.create(
expires=now() + until, provider=self.provider, _scope=" ".join(self.scopes)
@@ -67,7 +67,7 @@ class DeviceView(View):
device_url = self.request.build_absolute_uri(
reverse("authentik_providers_oauth2_root:device-login")
)
return JsonResponse(
return TokenResponse(
{
"device_code": token.device_code,
"verification_uri": device_url,

View File

@@ -598,9 +598,9 @@ class TokenView(View):
return TokenResponse(self.create_device_code_response())
raise TokenError("unsupported_grant_type")
except (TokenError, DeviceCodeError) as error:
return TokenResponse(error.create_dict(), status=400)
return TokenResponse(error.create_dict(request), status=400)
except UserAuthError as error:
return TokenResponse(error.create_dict(), status=403)
return TokenResponse(error.create_dict(request), status=403)
def create_code_response(self) -> dict[str, Any]:
"""See https://datatracker.ietf.org/doc/html/rfc6749#section-4.1"""

View File

@@ -65,7 +65,7 @@ class TokenRevokeView(View):
return TokenResponse(data={}, status=200)
except TokenRevocationError as exc:
return TokenResponse(exc.create_dict(), status=401)
return TokenResponse(exc.create_dict(request), status=401)
except Http404:
# Token not found should return a HTTP 200
# https://datatracker.ietf.org/doc/html/rfc7009#section-2.2

View File

@@ -102,6 +102,7 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]):
# Buffer sizes for large headers with JWTs
"nginx.ingress.kubernetes.io/proxy-buffers-number": "4",
"nginx.ingress.kubernetes.io/proxy-buffer-size": "16k",
"nginx.ingress.kubernetes.io/proxy-busy-buffers-size": "32k",
# Enable TLS in traefik
"traefik.ingress.kubernetes.io/router.tls": "true",
}

View File

@@ -23,7 +23,6 @@ from authentik.core.models import Application
from authentik.events.models import Event, EventAction
from authentik.lib.expression.exceptions import ControlFlowException
from authentik.lib.sync.mapper import PropertyMappingManager
from authentik.lib.utils.errors import exception_to_string
from authentik.policies.api.exec import PolicyTestResultSerializer
from authentik.policies.engine import PolicyEngine
from authentik.policies.types import PolicyResult
@@ -142,9 +141,9 @@ class RadiusOutpostConfigViewSet(ListModelMixin, GenericViewSet):
# Value error can be raised when assigning invalid data to an attribute
Event.new(
EventAction.CONFIGURATION_ERROR,
message=f"Failed to evaluate property-mapping {exception_to_string(exc)}",
message="Failed to evaluate property-mapping",
mapping=exc.mapping,
).save()
).with_exception(exc).save()
return None
return b64encode(packet.RequestPacket()).decode()

View File

@@ -2,7 +2,7 @@
from enum import Enum
from pydantic import Field
from pydantic import AnyUrl, BaseModel, ConfigDict, Field
from pydanticscim.group import Group as BaseGroup
from pydanticscim.responses import PatchOperation as BasePatchOperation
from pydanticscim.responses import PatchRequest as BasePatchRequest
@@ -12,19 +12,95 @@ from pydanticscim.service_provider import ChangePassword, Filter, Patch, Sort
from pydanticscim.service_provider import (
ServiceProviderConfiguration as BaseServiceProviderConfiguration,
)
from pydanticscim.user import AddressKind
from pydanticscim.user import User as BaseUser
SCIM_USER_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:User"
SCIM_GROUP_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:Group"
class Address(BaseModel):
formatted: str | None = Field(
None,
description="The full mailing address, formatted for display "
"or use with a mailing label. This attribute MAY contain newlines.",
)
streetAddress: str | None = Field(
None,
description="The full street address component, which may "
"include house number, street name, P.O. box, and multi-line "
"extended street address information. This attribute MAY contain newlines.",
)
locality: str | None = Field(None, description="The city or locality component.")
region: str | None = Field(None, description="The state or region component.")
postalCode: str | None = Field(None, description="The zip code or postal code component.")
country: str | None = Field(None, description="The country name component.")
type: AddressKind | None = Field(
None,
description="A label indicating the attribute's function, e.g., 'work' or 'home'.",
)
primary: bool | None = None
class Manager(BaseModel):
value: str | None = Field(
None,
description="The id of the SCIM resource representingthe User's manager. REQUIRED.",
)
ref: AnyUrl | None = Field(
None,
alias="$ref",
description="The URI of the SCIM resource representing the User's manager. REQUIRED.",
)
displayName: str | None = Field(
None,
description="The displayName of the User's manager. OPTIONAL and READ-ONLY.",
)
class EnterpriseUser(BaseModel):
employeeNumber: str | None = Field(
None,
description="Numeric or alphanumeric identifier assigned to a person, "
"typically based on order of hire or association with anorganization.",
)
costCenter: str | None = Field(None, description="Identifies the name of a cost center.")
organization: str | None = Field(None, description="Identifies the name of an organization.")
division: str | None = Field(None, description="Identifies the name of a division.")
department: str | None = Field(
None,
description="Numeric or alphanumeric identifier assigned to a person,"
" typically based on order of hire or association with anorganization.",
)
manager: Manager | None = Field(
None,
description="The User's manager. A complex type that optionally allows "
"service providers to represent organizational hierarchy by referencing"
" the 'id' attribute of another User.",
)
class User(BaseUser):
"""Modified User schema with added externalId field"""
model_config = ConfigDict(serialize_by_alias=True)
id: str | int | None = None
schemas: list[str] = [SCIM_USER_SCHEMA]
externalId: str | None = None
meta: dict | None = None
addresses: list[Address] | None = Field(
None,
description=(
"A physical mailing address for this User. Canonical type "
"values of 'work', 'home', and 'other'."
),
)
enterprise_user: EnterpriseUser | None = Field(
default=None,
alias="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
serialization_alias="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
)
class Group(BaseGroup):
@@ -92,7 +168,7 @@ class PatchOperation(BasePatchOperation):
"""PatchOperation with optional path"""
op: PatchOp
path: str | None
path: str | None = None
class SCIMError(BaseSCIMError):

View File

@@ -28,7 +28,6 @@ from tenant_schemas_celery.app import CeleryApp as TenantAwareCeleryApp
from authentik import get_full_version
from authentik.lib.sentry import should_ignore_exception
from authentik.lib.utils.errors import exception_to_string
# set the default Django settings module for the 'celery' program.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
@@ -83,8 +82,8 @@ def task_error_hook(task_id: str, exception: Exception, traceback, *args, **kwar
CTX_TASK_ID.set(...)
if not should_ignore_exception(exception):
Event.new(
EventAction.SYSTEM_EXCEPTION, message=exception_to_string(exception), task_id=task_id
).save()
EventAction.SYSTEM_EXCEPTION, message="Failed to execute task", task_id=task_id
).with_exception(exception).save()
def _get_startup_tasks_default_tenant() -> list[Callable]:

View File

@@ -49,6 +49,8 @@ class ReadyView(View):
def dispatch(self, request: HttpRequest) -> HttpResponse:
try:
for db_conn in connections.all():
# Force connection reload
db_conn.connect()
_ = db_conn.cursor()
except OperationalError: # pragma: no cover
return HttpResponse(status=503)

View File

@@ -156,16 +156,17 @@ SPECTACULAR_SETTINGS = {
},
"ENUM_NAME_OVERRIDES": {
"CountryCodeEnum": "django_countries.countries",
"DeviceClassesEnum": "authentik.stages.authenticator_validate.models.DeviceClasses",
"EventActions": "authentik.events.models.EventAction",
"FlowDesignationEnum": "authentik.flows.models.FlowDesignation",
"FlowLayoutEnum": "authentik.flows.models.FlowLayout",
"PolicyEngineMode": "authentik.policies.models.PolicyEngineMode",
"ProxyMode": "authentik.providers.proxy.models.ProxyMode",
"PromptTypeEnum": "authentik.stages.prompt.models.FieldTypes",
"LDAPAPIAccessMode": "authentik.providers.ldap.models.APIAccessMode",
"UserVerificationEnum": "authentik.stages.authenticator_webauthn.models.UserVerification",
"UserTypeEnum": "authentik.core.models.UserTypes",
"OutgoingSyncDeleteAction": "authentik.lib.sync.outgoing.models.OutgoingSyncDeleteAction",
"PolicyEngineMode": "authentik.policies.models.PolicyEngineMode",
"PromptTypeEnum": "authentik.stages.prompt.models.FieldTypes",
"ProxyMode": "authentik.providers.proxy.models.ProxyMode",
"UserTypeEnum": "authentik.core.models.UserTypes",
"UserVerificationEnum": "authentik.stages.authenticator_webauthn.models.UserVerification",
},
"ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE": False,
"ENUM_GENERATE_CHOICE_DESCRIPTION": False,

View File

@@ -4,11 +4,11 @@ from pathlib import Path
from secrets import token_urlsafe
from tempfile import gettempdir
from django.test import TestCase
from django.test import TransactionTestCase
from django.urls import reverse
class TestRoot(TestCase):
class TestRoot(TransactionTestCase):
"""Test root application"""
def setUp(self):

View File

@@ -8,7 +8,6 @@ from authentik.events.models import TaskStatus
from authentik.events.system_tasks import SystemTask
from authentik.lib.config import CONFIG
from authentik.lib.sync.outgoing.exceptions import StopSync
from authentik.lib.utils.errors import exception_to_string
from authentik.root.celery import CELERY_APP
from authentik.sources.kerberos.models import KerberosSource
from authentik.sources.kerberos.sync import KerberosSync
@@ -64,5 +63,5 @@ def kerberos_sync_single(self, source_pk: str):
syncer.sync()
self.set_status(TaskStatus.SUCCESSFUL, *syncer.messages)
except StopSync as exc:
LOGGER.warning(exception_to_string(exc))
LOGGER.warning("Error syncing kerberos", exc=exc, source=source)
self.set_error(exc)

View File

@@ -12,7 +12,6 @@ from authentik.events.models import TaskStatus
from authentik.events.system_tasks import SystemTask
from authentik.lib.config import CONFIG
from authentik.lib.sync.outgoing.exceptions import StopSync
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.reflection import class_to_path, path_to_class
from authentik.root.celery import CELERY_APP
from authentik.sources.ldap.models import LDAPSource
@@ -149,5 +148,5 @@ def ldap_sync(self: SystemTask, source_pk: str, sync_class: str, page_cache_key:
cache.delete(page_cache_key)
except (LDAPException, StopSync) as exc:
# No explicit event is created here as .set_status with an error will do that
LOGGER.warning(exception_to_string(exc))
LOGGER.warning("Failed to sync LDAP", exc=exc, source=source)
self.set_error(exc)

View File

@@ -10,6 +10,7 @@ AUTHENTIK_SOURCES_OAUTH_TYPES = [
"authentik.sources.oauth.types.apple",
"authentik.sources.oauth.types.azure_ad",
"authentik.sources.oauth.types.discord",
"authentik.sources.oauth.types.entra_id",
"authentik.sources.oauth.types.facebook",
"authentik.sources.oauth.types.github",
"authentik.sources.oauth.types.gitlab",

View File

@@ -232,7 +232,7 @@ class GoogleOAuthSource(CreatableType, OAuthSource):
class AzureADOAuthSource(CreatableType, OAuthSource):
"""Social Login using Azure AD."""
"""(Deprecated) Social Login using Azure AD."""
class Meta:
abstract = True
@@ -240,6 +240,17 @@ class AzureADOAuthSource(CreatableType, OAuthSource):
verbose_name_plural = _("Azure AD OAuth Sources")
# TODO: When removing this, add a migration for OAuthSource that sets
# provider_type to `entraid` if it is currently `azuread`
class EntraIDOAuthSource(CreatableType, OAuthSource):
"""Social Login using Entra ID."""
class Meta:
abstract = True
verbose_name = _("Entra ID OAuth Source")
verbose_name_plural = _("Entra ID OAuth Sources")
class OpenIDConnectOAuthSource(CreatableType, OAuthSource):
"""Login using a Generic OpenID-Connect compliant provider."""

View File

@@ -1,12 +1,12 @@
"""azure ad Type tests"""
"""Entra ID Type tests"""
from django.test import TestCase
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.azure_ad import AzureADOAuthCallback, AzureADType
from authentik.sources.oauth.types.entra_id import EntraIDOAuthCallback, EntraIDType
# https://docs.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http#response-2
AAD_USER = {
EID_USER = {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"@odata.id": (
"https://graph.microsoft.com/v2/7ce9b89e-646a-41d2-9fa6-8371c6a8423d/"
@@ -41,11 +41,11 @@ class TestTypeAzureAD(TestCase):
def test_enroll_context(self):
"""Test azure_ad Enrollment context"""
ak_context = AzureADType().get_base_user_properties(source=self.source, info=AAD_USER)
self.assertEqual(ak_context["username"], AAD_USER["userPrincipalName"])
self.assertEqual(ak_context["email"], AAD_USER["mail"])
self.assertEqual(ak_context["name"], AAD_USER["displayName"])
ak_context = EntraIDType().get_base_user_properties(source=self.source, info=EID_USER)
self.assertEqual(ak_context["username"], EID_USER["userPrincipalName"])
self.assertEqual(ak_context["email"], EID_USER["mail"])
self.assertEqual(ak_context["name"], EID_USER["displayName"])
def test_user_id(self):
"""Test azure AD user ID"""
self.assertEqual(AzureADOAuthCallback().get_user_id(AAD_USER), AAD_USER["id"])
"""Test Entra ID user ID"""
self.assertEqual(EntraIDOAuthCallback().get_user_id(EID_USER), EID_USER["id"])

View File

@@ -1,105 +1,17 @@
"""AzureAD OAuth2 Views"""
from typing import Any
from authentik.sources.oauth.types.entra_id import EntraIDType
from authentik.sources.oauth.types.registry import registry
from requests import RequestException
from structlog.stdlib import get_logger
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod
from authentik.sources.oauth.types.oidc import OpenIDConnectOAuth2Callback
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.redirect import OAuthRedirect
LOGGER = get_logger()
class AzureADOAuthRedirect(OAuthRedirect):
"""Azure AD OAuth2 Redirect"""
def get_additional_parameters(self, source): # pragma: no cover
return {
"scope": ["openid", "https://graph.microsoft.com/User.Read"],
}
class AzureADClient(UserprofileHeaderAuthClient):
"""Fetch AzureAD group information"""
def get_profile_info(self, token):
profile_data = super().get_profile_info(token)
if "https://graph.microsoft.com/GroupMember.Read.All" not in self.source.additional_scopes:
return profile_data
group_response = self.session.request(
"get",
"https://graph.microsoft.com/v1.0/me/memberOf",
headers={"Authorization": f"{token['token_type']} {token['access_token']}"},
)
try:
group_response.raise_for_status()
except RequestException as exc:
LOGGER.warning(
"Unable to fetch user profile",
exc=exc,
response=exc.response.text if exc.response else str(exc),
)
return None
profile_data["raw_groups"] = group_response.json()
return profile_data
class AzureADOAuthCallback(OpenIDConnectOAuth2Callback):
"""AzureAD OAuth2 Callback"""
client_class = AzureADClient
def get_user_id(self, info: dict[str, str]) -> str:
# Default try to get `id` for the Graph API endpoint
# fallback to OpenID logic in case the profile URL was changed
return info.get("id", super().get_user_id(info))
# TODO: When removing this, add a migration for OAuthSource that sets
# provider_type to `entraid` if it is currently `azuread`
@registry.register()
class AzureADType(SourceType):
class AzureADType(EntraIDType):
"""Azure AD Type definition"""
callback_view = AzureADOAuthCallback
redirect_view = AzureADOAuthRedirect
verbose_name = "Azure AD"
name = "azuread"
urls_customizable = True
authorization_url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
access_token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec
profile_url = "https://graph.microsoft.com/v1.0/me"
oidc_well_known_url = (
"https://login.microsoftonline.com/common/.well-known/openid-configuration"
)
oidc_jwks_url = "https://login.microsoftonline.com/common/discovery/keys"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
mail = info.get("mail", None) or info.get("otherMails", [None])[0]
# Format group info
groups = []
group_id_dict = {}
for group in info.get("raw_groups", {}).get("value", []):
if group["@odata.type"] != "#microsoft.graph.group":
continue
groups.append(group["id"])
group_id_dict[group["id"]] = group
info["raw_groups"] = group_id_dict
return {
"username": info.get("userPrincipalName"),
"email": mail,
"name": info.get("displayName"),
"groups": groups,
}
def get_base_group_properties(self, source, group_id, **kwargs):
raw_group = kwargs["info"]["raw_groups"][group_id]
return {
"name": raw_group["displayName"],
}

View File

@@ -0,0 +1,102 @@
"""EntraID OAuth2 Views"""
from typing import Any
from requests import RequestException
from structlog.stdlib import get_logger
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.models import AuthorizationCodeAuthMethod
from authentik.sources.oauth.types.oidc import OpenIDConnectOAuth2Callback
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.redirect import OAuthRedirect
LOGGER = get_logger()
class EntraIDOAuthRedirect(OAuthRedirect):
"""Entra ID OAuth2 Redirect"""
def get_additional_parameters(self, source): # pragma: no cover
return {
"scope": ["openid", "https://graph.microsoft.com/User.Read"],
}
class EntraIDClient(UserprofileHeaderAuthClient):
"""Fetch EntraID group information"""
def get_profile_info(self, token):
profile_data = super().get_profile_info(token)
if "https://graph.microsoft.com/GroupMember.Read.All" not in self.source.additional_scopes:
return profile_data
group_response = self.session.request(
"get",
"https://graph.microsoft.com/v1.0/me/memberOf",
headers={"Authorization": f"{token['token_type']} {token['access_token']}"},
)
try:
group_response.raise_for_status()
except RequestException as exc:
LOGGER.warning(
"Unable to fetch user profile",
exc=exc,
response=exc.response.text if exc.response else str(exc),
)
return None
profile_data["raw_groups"] = group_response.json()
return profile_data
class EntraIDOAuthCallback(OpenIDConnectOAuth2Callback):
"""EntraID OAuth2 Callback"""
client_class = EntraIDClient
def get_user_id(self, info: dict[str, str]) -> str:
# Default try to get `id` for the Graph API endpoint
# fallback to OpenID logic in case the profile URL was changed
return info.get("id", super().get_user_id(info))
@registry.register()
class EntraIDType(SourceType):
"""Entra ID Type definition"""
callback_view = EntraIDOAuthCallback
redirect_view = EntraIDOAuthRedirect
verbose_name = "Entra ID"
name = "entraid"
urls_customizable = True
authorization_url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
access_token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec
profile_url = "https://graph.microsoft.com/v1.0/me"
oidc_jwks_url = "https://login.microsoftonline.com/common/discovery/keys"
authorization_code_auth_method = AuthorizationCodeAuthMethod.POST_BODY
def get_base_user_properties(self, info: dict[str, Any], **kwargs) -> dict[str, Any]:
mail = info.get("mail", None) or info.get("otherMails", [None])[0]
# Format group info
groups = []
group_id_dict = {}
for group in info.get("raw_groups", {}).get("value", []):
if group["@odata.type"] != "#microsoft.graph.group":
continue
groups.append(group["id"])
group_id_dict[group["id"]] = group
info["raw_groups"] = group_id_dict
return {
"username": info.get("userPrincipalName"),
"email": mail,
"name": info.get("displayName"),
"groups": groups,
}
def get_base_group_properties(self, source, group_id, **kwargs):
raw_group = kwargs["info"]["raw_groups"][group_id]
return {
"name": raw_group["displayName"],
}

View File

@@ -0,0 +1,35 @@
from django.db import migrations
def create_missing_groupplexsourceconnection(apps, schema_editor):
db_alias = schema_editor.connection.alias
GroupSourceConnection = apps.get_model("authentik_core", "GroupSourceConnection")
PlexSource = apps.get_model("authentik_sources_plex", "PlexSource")
GroupPlexSourceConnection = apps.get_model(
"authentik_sources_plex", "GroupPlexSourceConnection"
)
for source in PlexSource.objects.using(db_alias).all():
for gsc in GroupSourceConnection.objects.using(db_alias).filter(source=source):
if GroupPlexSourceConnection.objects.using(db_alias).filter(pk=gsc.pk).exists():
continue
gpsc = GroupPlexSourceConnection(pk=gsc.pk)
gpsc.save(using=db_alias)
class Migration(migrations.Migration):
dependencies = [
(
"authentik_sources_plex",
"0005_migrate_userplexsourceconnection_identifier",
),
("authentik_core", "0044_usersourceconnection_new_identifier"),
]
operations = [
migrations.RunPython(
code=create_missing_groupplexsourceconnection, reverse_code=migrations.RunPython.noop
),
]

View File

@@ -9,7 +9,11 @@ from structlog.stdlib import get_logger
from authentik import __version__
from authentik.core.sources.flow_manager import SourceFlowManager
from authentik.lib.utils.http import get_http_session
from authentik.sources.plex.models import PlexSource, UserPlexSourceConnection
from authentik.sources.plex.models import (
GroupPlexSourceConnection,
PlexSource,
UserPlexSourceConnection,
)
LOGGER = get_logger()
@@ -110,6 +114,7 @@ class PlexSourceFlowManager(SourceFlowManager):
"""Flow manager for plex sources"""
user_connection_type = UserPlexSourceConnection
group_connection_type = GroupPlexSourceConnection
def update_user_connection(
self, connection: UserPlexSourceConnection, **kwargs

View File

@@ -18,6 +18,7 @@ class SCIMSourceGroupSerializer(SourceSerializer):
model = SCIMSourceGroup
fields = [
"id",
"external_id",
"group",
"group_obj",
"source",
@@ -31,5 +32,5 @@ class SCIMSourceGroupViewSet(UsedByMixin, ModelViewSet):
queryset = SCIMSourceGroup.objects.all().select_related("group")
serializer_class = SCIMSourceGroupSerializer
filterset_fields = ["source__slug", "group__name", "group__group_uuid"]
search_fields = ["source__slug", "group__name", "attributes"]
search_fields = ["source__slug", "group__name", "attributes", "external_id"]
ordering = ["group__name"]

View File

@@ -18,6 +18,7 @@ class SCIMSourceUserSerializer(SourceSerializer):
model = SCIMSourceUser
fields = [
"id",
"external_id",
"user",
"user_obj",
"source",
@@ -31,5 +32,5 @@ class SCIMSourceUserViewSet(UsedByMixin, ModelViewSet):
queryset = SCIMSourceUser.objects.all().select_related("user")
serializer_class = SCIMSourceUserSerializer
filterset_fields = ["source__slug", "user__username", "user__id"]
search_fields = ["source__slug", "user__username", "attributes"]
search_fields = ["source__slug", "user__username", "attributes", "user__uuid", "external_id"]
ordering = ["user__username"]

View File

@@ -0,0 +1,4 @@
SCIM_URN_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:Schema"
SCIM_URN_GROUP = "urn:ietf:params:scim:schemas:core:2.0:Group"
SCIM_URN_USER = "urn:ietf:params:scim:schemas:core:2.0:User"
SCIM_URN_USER_ENTERPRISE = "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"

View File

@@ -1,8 +0,0 @@
"""SCIM Errors"""
from authentik.lib.sentry import SentryIgnoredException
class PatchError(SentryIgnoredException):
"""Error raised within an atomic block when an error happened
so nothing is saved"""

View File

@@ -0,0 +1,98 @@
# Generated by Django 5.1.11 on 2025-07-13 01:07
import uuid
from django.db import migrations, models
from django.apps.registry import Apps
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def migrate_ext_id(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
SCIMSourceUser = apps.get_model("authentik_sources_scim", "SCIMSourceUser")
SCIMSourceGroup = apps.get_model("authentik_sources_scim", "SCIMSourceGroup")
db_alias = schema_editor.connection.alias
for user in SCIMSourceUser.objects.using(db_alias).all():
user.external_id = user.id
user.save(update_fields=["external_id"])
for group in SCIMSourceGroup.objects.using(db_alias).all():
group.external_id = group.id
group.save(update_fields=["external_id"])
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_scim", "0002_scimsourcepropertymapping"),
]
operations = [
migrations.AlterUniqueTogether(
name="scimsourcegroup",
unique_together=set(),
),
migrations.AlterUniqueTogether(
name="scimsourceuser",
unique_together=set(),
),
migrations.AddField(
model_name="scimsourcegroup",
name="external_id",
field=models.TextField(default=None, null=True),
preserve_default=False,
),
migrations.AddField(
model_name="scimsourceuser",
name="external_id",
field=models.TextField(default=None, null=True),
preserve_default=False,
),
migrations.AlterUniqueTogether(
name="scimsourcegroup",
unique_together={("external_id", "source")},
),
migrations.AlterUniqueTogether(
name="scimsourceuser",
unique_together={("external_id", "source")},
),
migrations.RunPython(migrate_ext_id, migrations.RunPython.noop),
migrations.AlterField(
model_name="scimsourcegroup",
name="external_id",
field=models.TextField(),
preserve_default=False,
),
migrations.AlterField(
model_name="scimsourceuser",
name="external_id",
field=models.TextField(),
preserve_default=False,
),
migrations.AddIndex(
model_name="scimsourcegroup",
index=models.Index(fields=["external_id"], name="authentik_s_externa_05e346_idx"),
),
migrations.AddIndex(
model_name="scimsourceuser",
index=models.Index(fields=["external_id"], name="authentik_s_externa_4bd760_idx"),
),
migrations.AlterField(
model_name="scimsourcegroup",
name="id",
field=models.TextField(default=uuid.uuid4, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name="scimsourceuser",
name="id",
field=models.TextField(default=uuid.uuid4, primary_key=True, serialize=False),
),
migrations.AddField(
model_name="scimsourcegroup",
name="last_update",
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name="scimsourceuser",
name="last_update",
field=models.DateTimeField(auto_now=True),
),
]

View File

@@ -1,6 +1,7 @@
"""SCIM Source"""
from typing import Any
from uuid import uuid4
from django.db import models
from django.templatetags.static import static
@@ -103,10 +104,12 @@ class SCIMSourcePropertyMapping(PropertyMapping):
class SCIMSourceUser(SerializerModel):
"""Mapping of a user and source to a SCIM user ID"""
id = models.TextField(primary_key=True)
id = models.TextField(primary_key=True, default=uuid4)
external_id = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
source = models.ForeignKey(SCIMSource, on_delete=models.CASCADE)
attributes = models.JSONField(default=dict)
last_update = models.DateTimeField(auto_now=True)
@property
def serializer(self) -> BaseSerializer:
@@ -115,7 +118,10 @@ class SCIMSourceUser(SerializerModel):
return SCIMSourceUserSerializer
class Meta:
unique_together = (("id", "user", "source"),)
unique_together = (("external_id", "source"),)
indexes = [
models.Index(fields=["external_id"]),
]
def __str__(self) -> str:
return f"SCIM User {self.user_id} to {self.source_id}"
@@ -124,10 +130,12 @@ class SCIMSourceUser(SerializerModel):
class SCIMSourceGroup(SerializerModel):
"""Mapping of a group and source to a SCIM user ID"""
id = models.TextField(primary_key=True)
id = models.TextField(primary_key=True, default=uuid4)
external_id = models.TextField()
group = models.ForeignKey(Group, on_delete=models.CASCADE)
source = models.ForeignKey(SCIMSource, on_delete=models.CASCADE)
attributes = models.JSONField(default=dict)
last_update = models.DateTimeField(auto_now=True)
@property
def serializer(self) -> BaseSerializer:
@@ -136,7 +144,10 @@ class SCIMSourceGroup(SerializerModel):
return SCIMSourceGroupSerializer
class Meta:
unique_together = (("id", "group", "source"),)
unique_together = (("external_id", "source"),)
indexes = [
models.Index(fields=["external_id"]),
]
def __str__(self) -> str:
return f"SCIM Group {self.group_id} to {self.source_id}"

View File

View File

@@ -0,0 +1,180 @@
from dataclasses import dataclass
from enum import Enum
from authentik.sources.scim.constants import (
SCIM_URN_GROUP,
SCIM_URN_SCHEMA,
SCIM_URN_USER,
SCIM_URN_USER_ENTERPRISE,
)
# Token types for SCIM path parsing
class TokenType(Enum):
ATTRIBUTE = "ATTRIBUTE"
DOT = "DOT"
LBRACKET = "LBRACKET"
RBRACKET = "RBRACKET"
LPAREN = "LPAREN"
RPAREN = "RPAREN"
STRING = "STRING"
NUMBER = "NUMBER"
BOOLEAN = "BOOLEAN"
NULL = "NULL"
OPERATOR = "OPERATOR"
AND = "AND"
OR = "OR"
NOT = "NOT"
EOF = "EOF"
@dataclass
class Token:
type: TokenType
value: str
position: int = 0
class SCIMPathLexer:
"""Lexer for SCIM paths and filter expressions"""
OPERATORS = ["eq", "ne", "co", "sw", "ew", "gt", "lt", "ge", "le", "pr"]
def __init__(self, text: str):
self.schema_urns = [
SCIM_URN_SCHEMA,
SCIM_URN_GROUP,
SCIM_URN_USER,
SCIM_URN_USER_ENTERPRISE,
]
self.text = text
self.pos = 0
self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
def advance(self):
"""Move to next character"""
self.pos += 1
self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
def skip_whitespace(self):
"""Skip whitespace characters"""
while self.current_char and self.current_char.isspace():
self.advance()
def read_string(self, quote_char):
"""Read a quoted string"""
value = ""
self.advance() # Skip opening quote
while self.current_char and self.current_char != quote_char:
if self.current_char == "\\":
self.advance()
if self.current_char:
value += self.current_char
self.advance()
else:
value += self.current_char
self.advance()
if self.current_char == quote_char:
self.advance() # Skip closing quote
return value
def read_number(self):
"""Read a number (integer or float)"""
value = ""
while self.current_char and (self.current_char.isdigit() or self.current_char == "."):
value += self.current_char
self.advance()
return value
def read_identifier(self):
"""Read an identifier (attribute name or operator) - supports URN format"""
value = ""
while self.current_char and (self.current_char.isalnum() or self.current_char in "_-:"):
value += self.current_char
self.advance()
# If the identifier value so far is a schema URN, take that as the identifier and
# treat the next part as a sub_attribute
if value in self.schema_urns:
self.current_char = "."
return value
# Handle dots within URN identifiers (like "2.0")
# A dot is part of the identifier if it's followed by a digit
if (
self.current_char == "."
and self.pos + 1 < len(self.text)
and self.text[self.pos + 1].isdigit()
):
value += self.current_char
self.advance()
# Continue reading digits after the dot
while self.current_char and self.current_char.isdigit():
value += self.current_char
self.advance()
return value
def get_next_token(self) -> Token: # noqa PLR0911
"""Get the next token from the input"""
while self.current_char:
if self.current_char.isspace():
self.skip_whitespace()
continue
if self.current_char == ".":
self.advance()
return Token(TokenType.DOT, ".")
if self.current_char == "[":
self.advance()
return Token(TokenType.LBRACKET, "[")
if self.current_char == "]":
self.advance()
return Token(TokenType.RBRACKET, "]")
if self.current_char == "(":
self.advance()
return Token(TokenType.LPAREN, "(")
if self.current_char == ")":
self.advance()
return Token(TokenType.RPAREN, ")")
if self.current_char in "\"'":
quote_char = self.current_char
value = self.read_string(quote_char)
return Token(TokenType.STRING, value)
if self.current_char.isdigit():
value = self.read_number()
return Token(TokenType.NUMBER, value)
if self.current_char.isalpha() or self.current_char == "_":
value = self.read_identifier()
# Check for special keywords
if value.lower() == "true":
return Token(TokenType.BOOLEAN, True)
elif value.lower() == "false":
return Token(TokenType.BOOLEAN, False)
elif value.lower() == "null":
return Token(TokenType.NULL, None)
elif value.lower() == "and":
return Token(TokenType.AND, "and")
elif value.lower() == "or":
return Token(TokenType.OR, "or")
elif value.lower() == "not":
return Token(TokenType.NOT, "not")
elif value.lower() in self.OPERATORS:
return Token(TokenType.OPERATOR, value.lower())
else:
return Token(TokenType.ATTRIBUTE, value)
# Skip unknown characters
self.advance()
return Token(TokenType.EOF, "")

View File

@@ -0,0 +1,131 @@
from typing import Any
from authentik.sources.scim.patch.lexer import SCIMPathLexer, TokenType
class SCIMPathParser:
"""Parser for SCIM paths including filter expressions"""
def __init__(self):
self.lexer = None
self.current_token = None
def parse_path(self, path: str | None) -> list[dict[str, Any]]:
"""Parse a SCIM path into components"""
self.lexer = SCIMPathLexer(path)
self.current_token = self.lexer.get_next_token()
components = []
while self.current_token.type != TokenType.EOF:
component = self._parse_path_component()
if component:
components.append(component)
return components
def _parse_path_component(self) -> dict[str, Any] | None:
"""Parse a single path component"""
if self.current_token.type != TokenType.ATTRIBUTE:
return None
attribute = self.current_token.value
self._consume(TokenType.ATTRIBUTE)
filter_expr = None
sub_attribute = None
# Check for filter expression
if self.current_token.type == TokenType.LBRACKET:
self._consume(TokenType.LBRACKET)
filter_expr = self._parse_filter_expression()
self._consume(TokenType.RBRACKET)
# Check for sub-attribute
if self.current_token.type == TokenType.DOT:
self._consume(TokenType.DOT)
if self.current_token.type == TokenType.ATTRIBUTE:
sub_attribute = self.current_token.value
self._consume(TokenType.ATTRIBUTE)
return {"attribute": attribute, "filter": filter_expr, "sub_attribute": sub_attribute}
def _parse_filter_expression(self) -> dict[str, Any] | None:
"""Parse a filter expression like 'primary eq true' or
'type eq "work" and primary eq true'"""
return self._parse_or_expression()
def _parse_or_expression(self) -> dict[str, Any] | None:
"""Parse OR expressions"""
left = self._parse_and_expression()
while self.current_token.type == TokenType.OR:
self._consume(TokenType.OR)
right = self._parse_and_expression()
left = {"type": "logical", "operator": "or", "left": left, "right": right}
return left
def _parse_and_expression(self) -> dict[str, Any] | None:
"""Parse AND expressions"""
left = self._parse_primary_expression()
while self.current_token.type == TokenType.AND:
self._consume(TokenType.AND)
right = self._parse_primary_expression()
left = {"type": "logical", "operator": "and", "left": left, "right": right}
return left
def _parse_primary_expression(self) -> dict[str, Any] | None:
"""Parse primary expressions (attribute operator value)"""
if self.current_token.type == TokenType.LPAREN:
self._consume(TokenType.LPAREN)
expr = self._parse_or_expression()
self._consume(TokenType.RPAREN)
return expr
if self.current_token.type == TokenType.NOT:
self._consume(TokenType.NOT)
expr = self._parse_primary_expression()
return {"type": "logical", "operator": "not", "operand": expr}
if self.current_token.type != TokenType.ATTRIBUTE:
return None
attribute = self.current_token.value
self._consume(TokenType.ATTRIBUTE)
if self.current_token.type != TokenType.OPERATOR:
return None
operator = self.current_token.value
self._consume(TokenType.OPERATOR)
# Parse value
value = None
if self.current_token.type == TokenType.STRING:
value = self.current_token.value
self._consume(TokenType.STRING)
elif self.current_token.type == TokenType.NUMBER:
value = (
float(self.current_token.value)
if "." in self.current_token.value
else int(self.current_token.value)
)
self._consume(TokenType.NUMBER)
elif self.current_token.type == TokenType.BOOLEAN:
value = self.current_token.value
self._consume(TokenType.BOOLEAN)
elif self.current_token.type == TokenType.NULL:
value = None
self._consume(TokenType.NULL)
return {"type": "comparison", "attribute": attribute, "operator": operator, "value": value}
def _consume(self, expected_type: TokenType):
"""Consume a token of the expected type"""
if self.current_token.type == expected_type:
self.current_token = self.lexer.get_next_token()
else:
raise ValueError(f"Expected {expected_type}, got {self.current_token.type}")

View File

@@ -0,0 +1,246 @@
from typing import Any
from authentik.providers.scim.clients.schema import PatchOp, PatchOperation
from authentik.sources.scim.constants import SCIM_URN_USER_ENTERPRISE
from authentik.sources.scim.patch.parser import SCIMPathParser
class SCIMPatchProcessor:
"""Processes SCIM patch operations on Python dictionaries"""
def __init__(self):
self.parser = SCIMPathParser()
def apply_patches(self, data: dict[str, Any], patches: list[PatchOperation]) -> dict[str, Any]:
"""Apply a list of patch operations to the data"""
result = data.copy()
for _patch in patches:
patch = PatchOperation.model_validate(_patch)
if patch.path is None:
# Handle operations with no path - value contains attribute paths as keys
self._apply_bulk_operation(result, patch.op, patch.value)
elif patch.op == PatchOp.add:
self._apply_add(result, patch.path, patch.value)
elif patch.op == PatchOp.remove:
self._apply_remove(result, patch.path)
elif patch.op == PatchOp.replace:
self._apply_replace(result, patch.path, patch.value)
return result
def _apply_bulk_operation(
self, data: dict[str, Any], operation: PatchOp, value: dict[str, Any]
):
"""Apply bulk operations when path is None"""
if not isinstance(value, dict):
return
for path, val in value.items():
if operation == PatchOp.add:
self._apply_add(data, path, val)
elif operation == PatchOp.remove:
self._apply_remove(data, path)
elif operation == PatchOp.replace:
self._apply_replace(data, path, val)
def _apply_add(self, data: dict[str, Any], path: str, value: Any):
"""Apply ADD operation"""
components = self.parser.parse_path(path)
if len(components) == 1 and not components[0]["filter"]:
# Simple path
attr = components[0]["attribute"]
if components[0]["sub_attribute"]:
if attr not in data:
data[attr] = {}
# Somewhat hacky workaround for the manager attribute of the enterprise schema
# ideally we'd do this based on the schema
if attr == SCIM_URN_USER_ENTERPRISE and components[0]["sub_attribute"] == "manager":
data[attr][components[0]["sub_attribute"]] = {"value": value}
else:
data[attr][components[0]["sub_attribute"]] = value
elif attr in data:
data[attr].append(value)
else:
data[attr] = value
else:
# Complex path with filters
self._navigate_and_modify(data, components, value, "add")
def _apply_remove(self, data: dict[str, Any], path: str):
"""Apply REMOVE operation"""
components = self.parser.parse_path(path)
if len(components) == 1 and not components[0]["filter"]:
# Simple path
attr = components[0]["attribute"]
if components[0]["sub_attribute"]:
if attr in data and isinstance(data[attr], dict):
data[attr].pop(components[0]["sub_attribute"], None)
else:
data.pop(attr, None)
else:
# Complex path with filters
self._navigate_and_modify(data, components, None, "remove")
def _apply_replace(self, data: dict[str, Any], path: str, value: Any):
"""Apply REPLACE operation"""
components = self.parser.parse_path(path)
if len(components) == 1 and not components[0]["filter"]:
# Simple path
attr = components[0]["attribute"]
if components[0]["sub_attribute"]:
if attr not in data:
data[attr] = {}
# Somewhat hacky workaround for the manager attribute of the enterprise schema
# ideally we'd do this based on the schema
if attr == SCIM_URN_USER_ENTERPRISE and components[0]["sub_attribute"] == "manager":
data[attr][components[0]["sub_attribute"]] = {"value": value}
else:
data[attr][components[0]["sub_attribute"]] = value
else:
data[attr] = value
else:
# Complex path with filters
self._navigate_and_modify(data, components, value, "replace")
def _navigate_and_modify( # noqa PLR0912
self, data: dict[str, Any], components: list[dict[str, Any]], value: Any, operation: str
):
"""Navigate through complex paths and apply modifications"""
current = data
for i, component in enumerate(components):
attr = component["attribute"]
filter_expr = component["filter"]
sub_attr = component["sub_attribute"]
if filter_expr:
# Handle array with filter
if attr not in current:
if operation == "add":
current[attr] = []
else:
return
if not isinstance(current[attr], list):
return
# Find matching items
matching_items = []
for item in current[attr]:
if self._matches_filter(item, filter_expr):
matching_items.append(item)
if not matching_items and operation == "add":
# Create new item if none match (only for simple comparison filters)
if filter_expr.get("type", "comparison") == "comparison":
new_item = {filter_expr["attribute"]: filter_expr["value"]}
current[attr].append(new_item)
matching_items = [new_item]
# Apply operation to matching items
for item in matching_items:
if sub_attr:
if operation in {"add", "replace"}:
item[sub_attr] = value
elif operation == "remove":
item.pop(sub_attr, None)
elif operation in {"add", "replace"}:
if isinstance(value, dict):
item.update(value)
else:
# If value is not a dict, we can't merge it
pass
elif operation == "remove":
# Remove the entire item
if item in current[attr]:
current[attr].remove(item)
# Handle simple attribute
elif i == len(components) - 1:
# Last component
if sub_attr:
if attr not in current:
current[attr] = {}
if operation in {"add", "replace"}:
current[attr][sub_attr] = value
elif operation == "remove":
current[attr].pop(sub_attr, None)
elif operation in {"add", "replace"}:
current[attr] = value
elif operation == "remove":
current.pop(attr, None)
else:
# Navigate deeper
if attr not in current:
current[attr] = {}
current = current[attr]
def _matches_filter(self, item: dict[str, Any], filter_expr: dict[str, Any]) -> bool:
"""Check if an item matches the filter expression"""
if not filter_expr:
return True
filter_type = filter_expr.get("type", "comparison")
if filter_type == "comparison":
return self._matches_comparison(item, filter_expr)
elif filter_type == "logical":
return self._matches_logical(item, filter_expr)
return False
def _matches_comparison( # noqa PLR0912
self, item: dict[str, Any], filter_expr: dict[str, Any]
) -> bool:
"""Check if an item matches a comparison filter"""
attr = filter_expr["attribute"]
operator = filter_expr["operator"]
expected_value = filter_expr["value"]
if attr not in item:
return False
actual_value = item[attr]
if operator == "eq":
return actual_value == expected_value
elif operator == "ne":
return actual_value != expected_value
elif operator == "co":
return str(expected_value) in str(actual_value)
elif operator == "sw":
return str(actual_value).startswith(str(expected_value))
elif operator == "ew":
return str(actual_value).endswith(str(expected_value))
elif operator == "gt":
return actual_value > expected_value
elif operator == "lt":
return actual_value < expected_value
elif operator == "ge":
return actual_value >= expected_value
elif operator == "le":
return actual_value <= expected_value
elif operator == "pr":
return actual_value is not None
return False
def _matches_logical(self, item: dict[str, Any], filter_expr: dict[str, Any]) -> bool:
"""Check if an item matches a logical filter expression"""
operator = filter_expr["operator"]
if operator == "and":
left_result = self._matches_filter(item, filter_expr["left"])
right_result = self._matches_filter(item, filter_expr["right"])
return left_result and right_result
elif operator == "or":
left_result = self._matches_filter(item, filter_expr["left"])
right_result = self._matches_filter(item, filter_expr["right"])
return left_result or right_result
elif operator == "not":
operand_result = self._matches_filter(item, filter_expr["operand"])
return not operand_result
return False

View File

@@ -1101,17 +1101,6 @@
"returned": "default",
"uniqueness": "none"
},
{
"name": "password",
"type": "string",
"multiValued": false,
"description": "The User's cleartext password. This attribute is intended to be used as a means to specify an initial\npassword when creating a new User or to reset an existing User's password.",
"required": false,
"caseExact": false,
"mutability": "writeOnly",
"returned": "never",
"uniqueness": "none"
},
{
"name": "emails",
"type": "complex",

View File

@@ -75,7 +75,9 @@ class TestSCIMGroups(APITestCase):
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, 201)
self.assertTrue(SCIMSourceGroup.objects.filter(source=self.source, id=ext_id).exists())
self.assertTrue(
SCIMSourceGroup.objects.filter(source=self.source, external_id=ext_id).exists()
)
self.assertTrue(
Event.objects.filter(
action=EventAction.MODEL_CREATED, user__username=self.source.token.user.username
@@ -86,6 +88,7 @@ class TestSCIMGroups(APITestCase):
"""Test group create"""
user = create_test_user()
ext_id = generate_id()
name = generate_id()
response = self.client.post(
reverse(
"authentik_sources_scim:v2-groups",
@@ -95,7 +98,7 @@ class TestSCIMGroups(APITestCase):
),
data=dumps(
{
"displayName": generate_id(),
"displayName": name,
"externalId": ext_id,
"members": [{"value": str(user.uuid)}],
}
@@ -104,12 +107,22 @@ class TestSCIMGroups(APITestCase):
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, 201)
self.assertTrue(SCIMSourceGroup.objects.filter(source=self.source, id=ext_id).exists())
connection = SCIMSourceGroup.objects.filter(source=self.source, external_id=ext_id).first()
self.assertIsNotNone(connection)
self.assertTrue(
Event.objects.filter(
action=EventAction.MODEL_CREATED, user__username=self.source.token.user.username
).exists()
)
connection.refresh_from_db()
self.assertEqual(
connection.attributes,
{
"displayName": name,
"externalId": ext_id,
"members": [{"value": str(user.uuid)}],
},
)
def test_group_create_members_empty(self):
"""Test group create"""
@@ -126,7 +139,9 @@ class TestSCIMGroups(APITestCase):
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, 201)
self.assertTrue(SCIMSourceGroup.objects.filter(source=self.source, id=ext_id).exists())
self.assertTrue(
SCIMSourceGroup.objects.filter(source=self.source, external_id=ext_id).exists()
)
self.assertTrue(
Event.objects.filter(
action=EventAction.MODEL_CREATED, user__username=self.source.token.user.username
@@ -136,7 +151,9 @@ class TestSCIMGroups(APITestCase):
def test_group_create_duplicate(self):
"""Test group create (duplicate)"""
group = Group.objects.create(name=generate_id())
existing = SCIMSourceGroup.objects.create(source=self.source, group=group, id=uuid4())
existing = SCIMSourceGroup.objects.create(
source=self.source, group=group, external_id=uuid4()
)
ext_id = generate_id()
response = self.client.post(
reverse(
@@ -165,7 +182,9 @@ class TestSCIMGroups(APITestCase):
def test_group_update(self):
"""Test group update"""
group = Group.objects.create(name=generate_id())
existing = SCIMSourceGroup.objects.create(source=self.source, group=group, id=uuid4())
existing = SCIMSourceGroup.objects.create(
source=self.source, group=group, external_id=uuid4()
)
ext_id = generate_id()
response = self.client.put(
reverse(
@@ -205,12 +224,49 @@ class TestSCIMGroups(APITestCase):
},
)
def test_group_patch_add(self):
def test_group_patch_modify(self):
"""Test group patch"""
group = Group.objects.create(name=generate_id())
connection = SCIMSourceGroup.objects.create(
source=self.source,
group=group,
external_id=uuid4(),
attributes={"displayName": group.name, "members": []},
)
response = self.client.patch(
reverse(
"authentik_sources_scim:v2-groups",
kwargs={"source_slug": self.source.slug, "group_id": group.pk},
),
data=dumps(
{
"Operations": [
{
"op": "Add",
"value": {"externalId": "d85051cb-0557-4aa1-98ca-51eabcee4d40"},
}
]
}
),
content_type=SCIM_CONTENT_TYPE,
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, 200, response.content)
connection = SCIMSourceGroup.objects.filter(id="d85051cb-0557-4aa1-98ca-51eabcee4d40")
self.assertIsNotNone(connection)
def test_group_patch_member_add(self):
"""Test group patch"""
user = create_test_user()
other_user = create_test_user()
group = Group.objects.create(name=generate_id())
SCIMSourceGroup.objects.create(source=self.source, group=group, id=uuid4())
group.users.add(other_user)
connection = SCIMSourceGroup.objects.create(
source=self.source,
group=group,
external_id=uuid4(),
attributes={"displayName": group.name, "members": [{"value": str(other_user.uuid)}]},
)
response = self.client.patch(
reverse(
"authentik_sources_scim:v2-groups",
@@ -222,7 +278,7 @@ class TestSCIMGroups(APITestCase):
{
"op": "Add",
"path": "members",
"value": {"value": str(user.uuid)},
"value": [{"value": str(user.uuid)}],
}
]
}
@@ -230,16 +286,33 @@ class TestSCIMGroups(APITestCase):
content_type=SCIM_CONTENT_TYPE,
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, second=200)
self.assertEqual(response.status_code, 200, response.content)
self.assertTrue(group.users.filter(pk=user.pk).exists())
self.assertTrue(group.users.filter(pk=other_user.pk).exists())
connection.refresh_from_db()
self.assertEqual(
connection.attributes,
{
"displayName": group.name,
"members": sorted(
[{"value": str(other_user.uuid)}, {"value": str(user.uuid)}],
key=lambda u: u["value"],
),
},
)
def test_group_patch_remove(self):
def test_group_patch_member_remove(self):
"""Test group patch"""
user = create_test_user()
group = Group.objects.create(name=generate_id())
group.users.add(user)
SCIMSourceGroup.objects.create(source=self.source, group=group, id=uuid4())
connection = SCIMSourceGroup.objects.create(
source=self.source,
group=group,
external_id=uuid4(),
attributes={"displayName": group.name, "members": []},
)
response = self.client.patch(
reverse(
"authentik_sources_scim:v2-groups",
@@ -251,7 +324,7 @@ class TestSCIMGroups(APITestCase):
{
"op": "remove",
"path": "members",
"value": {"value": str(user.uuid)},
"value": [{"value": str(user.uuid)}],
}
]
}
@@ -259,13 +332,21 @@ class TestSCIMGroups(APITestCase):
content_type=SCIM_CONTENT_TYPE,
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, second=200)
self.assertEqual(response.status_code, 200, response.content)
self.assertFalse(group.users.filter(pk=user.pk).exists())
connection.refresh_from_db()
self.assertEqual(
connection.attributes,
{
"displayName": group.name,
"members": [],
},
)
def test_group_delete(self):
"""Test group delete"""
group = Group.objects.create(name=generate_id())
SCIMSourceGroup.objects.create(source=self.source, group=group, id=uuid4())
SCIMSourceGroup.objects.create(source=self.source, group=group, external_id=uuid4())
response = self.client.delete(
reverse(
"authentik_sources_scim:v2-groups",

View File

@@ -0,0 +1,510 @@
from unittest import TestCase
from authentik.sources.scim.constants import (
SCIM_URN_GROUP,
SCIM_URN_SCHEMA,
SCIM_URN_USER,
SCIM_URN_USER_ENTERPRISE,
)
from authentik.sources.scim.patch.lexer import SCIMPathLexer, Token, TokenType
class TestTokenType(TestCase):
"""Test TokenType enum"""
def test_token_type_values(self):
"""Test that all token types have correct values"""
self.assertEqual(TokenType.ATTRIBUTE.value, "ATTRIBUTE")
self.assertEqual(TokenType.DOT.value, "DOT")
self.assertEqual(TokenType.LBRACKET.value, "LBRACKET")
self.assertEqual(TokenType.RBRACKET.value, "RBRACKET")
self.assertEqual(TokenType.LPAREN.value, "LPAREN")
self.assertEqual(TokenType.RPAREN.value, "RPAREN")
self.assertEqual(TokenType.STRING.value, "STRING")
self.assertEqual(TokenType.NUMBER.value, "NUMBER")
self.assertEqual(TokenType.BOOLEAN.value, "BOOLEAN")
self.assertEqual(TokenType.NULL.value, "NULL")
self.assertEqual(TokenType.OPERATOR.value, "OPERATOR")
self.assertEqual(TokenType.AND.value, "AND")
self.assertEqual(TokenType.OR.value, "OR")
self.assertEqual(TokenType.NOT.value, "NOT")
self.assertEqual(TokenType.EOF.value, "EOF")
class TestToken(TestCase):
"""Test Token dataclass"""
def test_token_creation(self):
"""Test token creation with all parameters"""
token = Token(TokenType.ATTRIBUTE, "userName", 5)
self.assertEqual(token.type, TokenType.ATTRIBUTE)
self.assertEqual(token.value, "userName")
self.assertEqual(token.position, 5)
def test_token_creation_default_position(self):
"""Test token creation with default position"""
token = Token(TokenType.DOT, ".")
self.assertEqual(token.type, TokenType.DOT)
self.assertEqual(token.value, ".")
self.assertEqual(token.position, 0)
class TestSCIMPathLexer(TestCase):
"""Test SCIMPathLexer class"""
def setUp(self):
"""Set up test fixtures"""
self.simple_lexer = SCIMPathLexer("userName")
def test_init(self):
"""Test lexer initialization"""
lexer = SCIMPathLexer("test")
self.assertEqual(lexer.text, "test")
self.assertEqual(lexer.pos, 0)
self.assertEqual(lexer.current_char, "t")
self.assertIn(SCIM_URN_SCHEMA, lexer.schema_urns)
self.assertIn(SCIM_URN_GROUP, lexer.schema_urns)
self.assertIn(SCIM_URN_USER, lexer.schema_urns)
self.assertIn(SCIM_URN_USER_ENTERPRISE, lexer.schema_urns)
self.assertEqual(
lexer.OPERATORS, ["eq", "ne", "co", "sw", "ew", "gt", "lt", "ge", "le", "pr"]
)
def test_init_empty_string(self):
"""Test lexer initialization with empty string"""
lexer = SCIMPathLexer("")
self.assertEqual(lexer.text, "")
self.assertEqual(lexer.pos, 0)
self.assertIsNone(lexer.current_char)
def test_advance(self):
"""Test advance method"""
lexer = SCIMPathLexer("abc")
self.assertEqual(lexer.current_char, "a")
lexer.advance()
self.assertEqual(lexer.pos, 1)
self.assertEqual(lexer.current_char, "b")
lexer.advance()
self.assertEqual(lexer.pos, 2)
self.assertEqual(lexer.current_char, "c")
lexer.advance()
self.assertEqual(lexer.pos, 3)
self.assertIsNone(lexer.current_char)
def test_skip_whitespace(self):
"""Test skip_whitespace method"""
lexer = SCIMPathLexer(" \t\n abc")
lexer.skip_whitespace()
self.assertEqual(lexer.current_char, "a")
def test_skip_whitespace_only_whitespace(self):
"""Test skip_whitespace with only whitespace"""
lexer = SCIMPathLexer(" \t\n ")
lexer.skip_whitespace()
self.assertIsNone(lexer.current_char)
def test_skip_whitespace_no_whitespace(self):
"""Test skip_whitespace with no leading whitespace"""
lexer = SCIMPathLexer("abc")
original_pos = lexer.pos
lexer.skip_whitespace()
self.assertEqual(lexer.pos, original_pos)
self.assertEqual(lexer.current_char, "a")
def test_read_string_double_quotes(self):
"""Test reading double-quoted string"""
lexer = SCIMPathLexer('"hello world"')
result = lexer.read_string('"')
self.assertEqual(result, "hello world")
self.assertIsNone(lexer.current_char) # Should be at end
def test_read_string_single_quotes(self):
"""Test reading single-quoted string"""
lexer = SCIMPathLexer("'hello world'")
result = lexer.read_string("'")
self.assertEqual(result, "hello world")
self.assertIsNone(lexer.current_char)
def test_read_string_with_escapes(self):
"""Test reading string with escape characters"""
lexer = SCIMPathLexer('"hello \\"world\\""')
result = lexer.read_string('"')
self.assertEqual(result, 'hello "world"')
def test_read_string_with_backslash_at_end(self):
"""Test reading string with backslash at end"""
lexer = SCIMPathLexer('"hello\\"')
result = lexer.read_string('"')
self.assertEqual(result, 'hello"')
def test_read_string_unclosed(self):
"""Test reading unclosed string"""
lexer = SCIMPathLexer('"hello world')
result = lexer.read_string('"')
self.assertEqual(result, "hello world")
self.assertIsNone(lexer.current_char)
def test_read_string_empty(self):
"""Test reading empty string"""
lexer = SCIMPathLexer('""')
result = lexer.read_string('"')
self.assertEqual(result, "")
def test_read_number_integer(self):
"""Test reading integer number"""
lexer = SCIMPathLexer("123")
result = lexer.read_number()
self.assertEqual(result, "123")
self.assertIsNone(lexer.current_char)
def test_read_number_float(self):
"""Test reading float number"""
lexer = SCIMPathLexer("123.456")
result = lexer.read_number()
self.assertEqual(result, "123.456")
self.assertIsNone(lexer.current_char)
def test_read_number_with_multiple_dots(self):
"""Test reading number with multiple dots (invalid but handled)"""
lexer = SCIMPathLexer("123.456.789")
result = lexer.read_number()
self.assertEqual(result, "123.456.789")
self.assertIsNone(lexer.current_char)
def test_read_number_starting_with_dot(self):
"""Test reading number starting with dot"""
lexer = SCIMPathLexer(".123")
result = lexer.read_number()
self.assertEqual(result, ".123")
def test_read_identifier_simple(self):
"""Test reading simple identifier"""
lexer = SCIMPathLexer("userName")
result = lexer.read_identifier()
self.assertEqual(result, "userName")
self.assertIsNone(lexer.current_char)
def test_read_identifier_with_underscore(self):
"""Test reading identifier with underscore"""
lexer = SCIMPathLexer("user_name")
result = lexer.read_identifier()
self.assertEqual(result, "user_name")
def test_read_identifier_with_hyphen(self):
"""Test reading identifier with hyphen"""
lexer = SCIMPathLexer("user-name")
result = lexer.read_identifier()
self.assertEqual(result, "user-name")
def test_read_identifier_with_colon(self):
"""Test reading identifier with colon (URN format)"""
lexer = SCIMPathLexer("urn:ietf:params:scim:schemas:core:2.0:User")
result = lexer.read_identifier()
self.assertEqual(result, "urn:ietf:params:scim:schemas:core:2.0:User")
def test_read_identifier_schema_urn(self):
"""Test reading schema URN identifier"""
lexer = SCIMPathLexer(f"{SCIM_URN_USER}.userName")
result = lexer.read_identifier()
self.assertEqual(result, SCIM_URN_USER)
self.assertEqual(lexer.current_char, ".") # Should stop at dot and set current_char to dot
def test_read_identifier_with_version_number(self):
"""Test reading identifier with version number (dots followed by digits)"""
lexer = SCIMPathLexer("urn:ietf:params:scim:schemas:core:2.0:User")
result = lexer.read_identifier()
self.assertEqual(result, "urn:ietf:params:scim:schemas:core:2.0:User")
def test_read_identifier_partial_urn_match(self):
"""Test reading identifier that partially matches URN"""
lexer = SCIMPathLexer("urn:ietf:params:scim:schemas:core:2.0:CustomUser")
result = lexer.read_identifier()
self.assertEqual(result, "urn:ietf:params:scim:schemas:core:2.0:CustomUser")
# Test get_next_token method
def test_get_next_token_dot(self):
"""Test tokenizing dot"""
lexer = SCIMPathLexer(".")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.DOT)
self.assertEqual(token.value, ".")
def test_get_next_token_lbracket(self):
"""Test tokenizing left bracket"""
lexer = SCIMPathLexer("[")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.LBRACKET)
self.assertEqual(token.value, "[")
def test_get_next_token_rbracket(self):
"""Test tokenizing right bracket"""
lexer = SCIMPathLexer("]")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.RBRACKET)
self.assertEqual(token.value, "]")
def test_get_next_token_lparen(self):
"""Test tokenizing left parenthesis"""
lexer = SCIMPathLexer("(")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.LPAREN)
self.assertEqual(token.value, "(")
def test_get_next_token_rparen(self):
"""Test tokenizing right parenthesis"""
lexer = SCIMPathLexer(")")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.RPAREN)
self.assertEqual(token.value, ")")
def test_get_next_token_string_double_quotes(self):
"""Test tokenizing double-quoted string"""
lexer = SCIMPathLexer('"test string"')
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.STRING)
self.assertEqual(token.value, "test string")
def test_get_next_token_string_single_quotes(self):
"""Test tokenizing single-quoted string"""
lexer = SCIMPathLexer("'test string'")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.STRING)
self.assertEqual(token.value, "test string")
def test_get_next_token_number_integer(self):
"""Test tokenizing integer"""
lexer = SCIMPathLexer("123")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.NUMBER)
self.assertEqual(token.value, "123")
def test_get_next_token_number_float(self):
"""Test tokenizing float"""
lexer = SCIMPathLexer("123.45")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.NUMBER)
self.assertEqual(token.value, "123.45")
def test_get_next_token_boolean_true(self):
"""Test tokenizing boolean true"""
lexer = SCIMPathLexer("true")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.BOOLEAN)
self.assertTrue(token.value)
def test_get_next_token_boolean_false(self):
"""Test tokenizing boolean false"""
lexer = SCIMPathLexer("false")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.BOOLEAN)
self.assertFalse(token.value)
def test_get_next_token_boolean_case_insensitive(self):
"""Test tokenizing boolean with different cases"""
for value in ["TRUE", "True", "FALSE", "False"]:
with self.subTest(value=value):
lexer = SCIMPathLexer(value)
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.BOOLEAN)
def test_get_next_token_null(self):
"""Test tokenizing null"""
lexer = SCIMPathLexer("null")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.NULL)
self.assertIsNone(token.value)
def test_get_next_token_null_case_insensitive(self):
"""Test tokenizing null with different cases"""
for value in ["NULL", "Null"]:
with self.subTest(value=value):
lexer = SCIMPathLexer(value)
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.NULL)
def test_get_next_token_and(self):
"""Test tokenizing AND operator"""
lexer = SCIMPathLexer("and")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.AND)
self.assertEqual(token.value, "and")
def test_get_next_token_or(self):
"""Test tokenizing OR operator"""
lexer = SCIMPathLexer("or")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.OR)
self.assertEqual(token.value, "or")
def test_get_next_token_not(self):
"""Test tokenizing NOT operator"""
lexer = SCIMPathLexer("not")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.NOT)
self.assertEqual(token.value, "not")
def test_get_next_token_operators(self):
"""Test tokenizing all comparison operators"""
operators = ["eq", "ne", "co", "sw", "ew", "gt", "lt", "ge", "le", "pr"]
for op in operators:
with self.subTest(operator=op):
lexer = SCIMPathLexer(op)
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.OPERATOR)
self.assertEqual(token.value, op)
def test_get_next_token_operators_case_insensitive(self):
"""Test tokenizing operators with different cases"""
for op in ["EQ", "Eq", "NE", "Ne"]:
with self.subTest(operator=op):
lexer = SCIMPathLexer(op)
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.OPERATOR)
self.assertEqual(token.value, op.lower())
def test_get_next_token_attribute(self):
"""Test tokenizing attribute name"""
lexer = SCIMPathLexer("userName")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.ATTRIBUTE)
self.assertEqual(token.value, "userName")
def test_get_next_token_attribute_with_underscore(self):
"""Test tokenizing attribute name with underscore"""
lexer = SCIMPathLexer("_userName")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.ATTRIBUTE)
self.assertEqual(token.value, "_userName")
def test_get_next_token_eof(self):
"""Test tokenizing end of file"""
lexer = SCIMPathLexer("")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.EOF)
self.assertEqual(token.value, "")
def test_get_next_token_with_whitespace(self):
"""Test tokenizing with leading whitespace"""
lexer = SCIMPathLexer(" userName")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.ATTRIBUTE)
self.assertEqual(token.value, "userName")
def test_get_next_token_skip_unknown_characters(self):
"""Test that unknown characters are skipped"""
lexer = SCIMPathLexer("@#$userName")
token = lexer.get_next_token()
self.assertEqual(token.type, TokenType.ATTRIBUTE)
self.assertEqual(token.value, "userName")
def test_get_next_token_multiple_tokens(self):
"""Test tokenizing multiple tokens in sequence"""
lexer = SCIMPathLexer("userName.givenName")
token1 = lexer.get_next_token()
self.assertEqual(token1.type, TokenType.ATTRIBUTE)
self.assertEqual(token1.value, "userName")
token2 = lexer.get_next_token()
self.assertEqual(token2.type, TokenType.DOT)
self.assertEqual(token2.value, ".")
token3 = lexer.get_next_token()
self.assertEqual(token3.type, TokenType.ATTRIBUTE)
self.assertEqual(token3.value, "givenName")
token4 = lexer.get_next_token()
self.assertEqual(token4.type, TokenType.EOF)
def test_get_next_token_complex_filter(self):
"""Test tokenizing complex filter expression"""
lexer = SCIMPathLexer('emails[type eq "work" and primary eq true]')
tokens = []
while True:
token = lexer.get_next_token()
tokens.append(token)
if token.type == TokenType.EOF:
break
expected_types = [
TokenType.ATTRIBUTE, # emails
TokenType.LBRACKET, # [
TokenType.ATTRIBUTE, # type
TokenType.OPERATOR, # eq
TokenType.STRING, # "work"
TokenType.AND, # and
TokenType.ATTRIBUTE, # primary
TokenType.OPERATOR, # eq
TokenType.BOOLEAN, # true
TokenType.RBRACKET, # ]
TokenType.EOF,
]
self.assertEqual(len(tokens), len(expected_types))
for token, expected_type in zip(tokens, expected_types, strict=False):
self.assertEqual(token.type, expected_type)
def test_get_next_token_urn_attribute(self):
"""Test tokenizing URN-based attribute"""
lexer = SCIMPathLexer(f"{SCIM_URN_USER}.userName")
token1 = lexer.get_next_token()
self.assertEqual(token1.type, TokenType.ATTRIBUTE)
self.assertEqual(token1.value, SCIM_URN_USER)
token2 = lexer.get_next_token()
self.assertEqual(token2.type, TokenType.DOT)
token3 = lexer.get_next_token()
self.assertEqual(token3.type, TokenType.ATTRIBUTE)
self.assertEqual(token3.value, "userName")
def test_get_next_token_enterprise_urn(self):
"""Test tokenizing enterprise URN"""
lexer = SCIMPathLexer(f"{SCIM_URN_USER_ENTERPRISE}.manager")
token1 = lexer.get_next_token()
self.assertEqual(token1.type, TokenType.ATTRIBUTE)
self.assertEqual(token1.value, SCIM_URN_USER_ENTERPRISE)
token2 = lexer.get_next_token()
self.assertEqual(token2.type, TokenType.DOT)
def test_lexer_state_after_eof(self):
"""Test lexer state after reaching EOF"""
lexer = SCIMPathLexer("a")
# Get first token
token1 = lexer.get_next_token()
self.assertEqual(token1.type, TokenType.ATTRIBUTE)
# Get EOF token
token2 = lexer.get_next_token()
self.assertEqual(token2.type, TokenType.EOF)
# Should continue returning EOF
token3 = lexer.get_next_token()
self.assertEqual(token3.type, TokenType.EOF)
def test_read_identifier_edge_cases(self):
"""Test read_identifier with edge cases"""
# Test identifier ending with colon
lexer = SCIMPathLexer("test:")
result = lexer.read_identifier()
self.assertEqual(result, "test:")
# Test identifier with numbers
lexer = SCIMPathLexer("test123")
result = lexer.read_identifier()
self.assertEqual(result, "test123")
def test_complex_urn_parsing(self):
"""Test parsing complex URN with version numbers"""
urn = "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
lexer = SCIMPathLexer(urn)
result = lexer.read_identifier()
self.assertEqual(result, urn)

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@ from authentik.core.tests.utils import create_test_user
from authentik.events.models import Event, EventAction
from authentik.lib.generators import generate_id
from authentik.providers.scim.clients.schema import User as SCIMUserSchema
from authentik.sources.scim.constants import SCIM_URN_USER_ENTERPRISE
from authentik.sources.scim.models import SCIMSource, SCIMSourcePropertyMapping, SCIMSourceUser
from authentik.sources.scim.views.v2.base import SCIM_CONTENT_TYPE
@@ -81,7 +82,9 @@ class TestSCIMUsers(APITestCase):
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, 201)
self.assertTrue(SCIMSourceUser.objects.filter(source=self.source, id=ext_id).exists())
self.assertTrue(
SCIMSourceUser.objects.filter(source=self.source, external_id=ext_id).exists()
)
self.assertTrue(
Event.objects.filter(
action=EventAction.MODEL_CREATED, user__username=self.source.token.user.username
@@ -174,14 +177,16 @@ class TestSCIMUsers(APITestCase):
)
self.assertEqual(response.status_code, 201)
self.assertEqual(
SCIMSourceUser.objects.get(source=self.source, id=ext_id).user.attributes["phone"],
SCIMSourceUser.objects.get(source=self.source, external_id=ext_id).user.attributes[
"phone"
],
"0123456789",
)
def test_user_update(self):
"""Test user update"""
user = create_test_user()
existing = SCIMSourceUser.objects.create(source=self.source, user=user, id=uuid4())
existing = SCIMSourceUser.objects.create(source=self.source, user=user, external_id=uuid4())
ext_id = generate_id()
response = self.client.put(
reverse(
@@ -209,10 +214,51 @@ class TestSCIMUsers(APITestCase):
)
self.assertEqual(response.status_code, 200)
def test_user_update_patch(self):
"""Test user update (patch)"""
user = create_test_user()
existing = SCIMSourceUser.objects.create(
source=self.source,
user=user,
external_id=uuid4(),
attributes={
"userName": generate_id(),
},
)
response = self.client.patch(
reverse(
"authentik_sources_scim:v2-users",
kwargs={
"source_slug": self.source.slug,
"user_id": str(user.uuid),
},
),
data=dumps(
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "Add",
"path": f"{SCIM_URN_USER_ENTERPRISE}:manager",
"value": "86b2ed3e-30cd-4881-bb58-c4e910821339",
}
],
}
),
content_type=SCIM_CONTENT_TYPE,
HTTP_AUTHORIZATION=f"Bearer {self.source.token.key}",
)
self.assertEqual(response.status_code, 200)
existing.refresh_from_db()
self.assertEqual(
existing.attributes[SCIM_URN_USER_ENTERPRISE],
{"manager": {"value": "86b2ed3e-30cd-4881-bb58-c4e910821339"}},
)
def test_user_delete(self):
"""Test user delete"""
user = create_test_user()
SCIMSourceUser.objects.create(source=self.source, user=user, id=uuid4())
SCIMSourceUser.objects.create(source=self.source, user=user, external_id=uuid4())
response = self.client.delete(
reverse(
"authentik_sources_scim:v2-users",

View File

@@ -0,0 +1,488 @@
from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_user
from authentik.lib.generators import generate_id
from authentik.sources.scim.constants import SCIM_URN_USER_ENTERPRISE
from authentik.sources.scim.models import SCIMSource, SCIMSourceUser
from authentik.sources.scim.patch.processor import SCIMPatchProcessor
class TestSCIMUsersPatch(APITestCase):
"""Test SCIM User Patch"""
def test_add(self):
req = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{"op": "Add", "path": "name.givenName", "value": "aqwer"},
{"op": "Add", "path": "name.familyName", "value": "qwerqqqq"},
{"op": "Add", "path": "name.formatted", "value": "aqwer qwerqqqq"},
],
}
user = create_test_user()
source = SCIMSource.objects.create(slug=generate_id())
connection = SCIMSourceUser.objects.create(
user=user,
id=generate_id(),
source=source,
attributes={
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
updated = SCIMPatchProcessor().apply_patches(connection.attributes, req["Operations"])
self.assertEqual(
updated,
{
"meta": {"resourceType": "User"},
"active": True,
"name": {
"givenName": "aqwer",
"familyName": "qwerqqqq",
"formatted": "aqwer qwerqqqq",
},
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
def test_add_no_path(self):
"""Test add patch with no path set"""
req = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{"op": "Add", "value": {"externalId": "aqwer"}},
],
}
user = create_test_user()
source = SCIMSource.objects.create(slug=generate_id())
connection = SCIMSourceUser.objects.create(
user=user,
id=generate_id(),
source=source,
attributes={
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"displayName": "Test MS",
},
)
updated = SCIMPatchProcessor().apply_patches(connection.attributes, req["Operations"])
self.assertEqual(
updated,
{
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "aqwer",
"displayName": "Test MS",
},
)
def test_replace(self):
req = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{"op": "Replace", "path": "name", "value": {"givenName": "aqwer"}},
],
}
user = create_test_user()
source = SCIMSource.objects.create(slug=generate_id())
connection = SCIMSourceUser.objects.create(
user=user,
id=generate_id(),
source=source,
attributes={
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
updated = SCIMPatchProcessor().apply_patches(connection.attributes, req["Operations"])
self.assertEqual(
updated,
{
"meta": {"resourceType": "User"},
"active": True,
"name": {
"givenName": "aqwer",
},
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
def test_replace_no_path(self):
"""Test value replace with no path"""
req = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{"op": "Replace", "value": {"externalId": "aqwer"}},
],
}
user = create_test_user()
source = SCIMSource.objects.create(slug=generate_id())
connection = SCIMSourceUser.objects.create(
user=user,
id=generate_id(),
source=source,
attributes={
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
updated = SCIMPatchProcessor().apply_patches(connection.attributes, req["Operations"])
self.assertEqual(
updated,
{
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "aqwer",
"displayName": "Test MS",
},
)
def test_remove(self):
req = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{"op": "Remove", "path": "name", "value": {"givenName": "aqwer"}},
],
}
user = create_test_user()
source = SCIMSource.objects.create(slug=generate_id())
connection = SCIMSourceUser.objects.create(
user=user,
id=generate_id(),
source=source,
attributes={
"meta": {"resourceType": "User"},
"active": True,
"name": {
"givenName": "aqwer",
},
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
updated = SCIMPatchProcessor().apply_patches(connection.attributes, req["Operations"])
self.assertEqual(
updated,
{
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
def test_large(self):
"""Large amount of patch operations"""
req = {
"Operations": [
{
"op": "replace",
"path": "emails[primary eq true].value",
"value": "dandre_kling@wintheiser.info",
},
{
"op": "replace",
"path": "phoneNumbers[primary eq true].value",
"value": "72-634-1548",
},
{
"op": "replace",
"path": "phoneNumbers[primary eq true].display",
"value": "72-634-1548",
},
{"op": "replace", "path": "ims[primary eq true].value", "value": "GXSGJKWGHVVS"},
{"op": "replace", "path": "ims[primary eq true].display", "value": "IMCHDKUQIPYB"},
{
"op": "replace",
"path": "photos[primary eq true].display",
"value": "TWAWLHHSUNIV",
},
{
"op": "replace",
"path": "addresses[primary eq true].formatted",
"value": "TMINZQAJQDCL",
},
{
"op": "replace",
"path": "addresses[primary eq true].streetAddress",
"value": "081 Wisoky Key",
},
{
"op": "replace",
"path": "addresses[primary eq true].locality",
"value": "DPFASBZRPMDP",
},
{
"op": "replace",
"path": "addresses[primary eq true].region",
"value": "WHSTJSPIPTCF",
},
{
"op": "replace",
"path": "addresses[primary eq true].postalCode",
"value": "ko28 1qa",
},
{"op": "replace", "path": "addresses[primary eq true].country", "value": "Taiwan"},
{
"op": "replace",
"path": "entitlements[primary eq true].value",
"value": "NGBJMUYZVVBX",
},
{"op": "replace", "path": "roles[primary eq true].value", "value": "XEELVFMMWCVM"},
{
"op": "replace",
"path": "x509Certificates[primary eq true].value",
"value": "UYISMEDOXUZY",
},
{
"op": "replace",
"value": {
"externalId": "7faaefb0-0774-4d8e-8f6d-863c361bc72c",
"name.formatted": "Dell",
"name.familyName": "Gay",
"name.givenName": "Kyler",
"name.middleName": "Hannah",
"name.honorificPrefix": "Cassie",
"name.honorificSuffix": "Yolanda",
"displayName": "DPRLIJSFQMTL",
"nickName": "BKSPMIRMFBTI",
"title": "NBZCOAXVYJUY",
"userType": "ZGJMYZRUORZE",
"preferredLanguage": "as-IN",
"locale": "JLOJHLPWZODG",
"timezone": "America/Argentina/Rio_Gallegos",
"active": True,
f"{SCIM_URN_USER_ENTERPRISE}:employeeNumber": "PDFWRRZBQOHB",
f"{SCIM_URN_USER_ENTERPRISE}:costCenter": "HACMZWSEDOTQ",
f"{SCIM_URN_USER_ENTERPRISE}:organization": "LXVHJUOLNCLS",
f"{SCIM_URN_USER_ENTERPRISE}:division": "JASVTPKPBPMG",
f"{SCIM_URN_USER_ENTERPRISE}:department": "GMSBFLMNPABY",
},
},
],
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
}
user = create_test_user()
source = SCIMSource.objects.create(slug=generate_id())
connection = SCIMSourceUser.objects.create(
user=user,
id=generate_id(),
source=source,
attributes={
"active": True,
"addresses": [
{
"primary": "true",
"formatted": "BLJMCNXHYLZK",
"streetAddress": "7801 Jacobs Fork",
"locality": "HZJBJWFAKXDD",
"region": "GJXCXPMIIKWK",
"postalCode": "pv82 8ua",
"country": "India",
}
],
"displayName": "KEFXCHKHAFOT",
"emails": [{"primary": "true", "value": "scot@zemlak.uk"}],
"entitlements": [{"primary": "true", "value": "FTTUXWYDAAQC"}],
"externalId": "448d2786-7bf6-4e03-a4ef-64cbaf162fa7",
"ims": [{"primary": "true", "value": "IGWZUUMCMKXS", "display": "PJVGMMKYYHRU"}],
"locale": "PJNYJHWJILTI",
"name": {
"formatted": "Ladarius",
"familyName": "Manley",
"givenName": "Mazie",
"middleName": "Vernon",
"honorificPrefix": "Melyssa",
"honorificSuffix": "Demarcus",
},
"nickName": "HTPKOXMWZKHL",
"phoneNumbers": [
{"primary": "true", "value": "50-608-7660", "display": "50-608-7660"}
],
"photos": [{"primary": "true", "display": "KCONLNLSYTBP"}],
"preferredLanguage": "wae",
"profileUrl": "HPSEOIPXMGOH",
"roles": [{"primary": "true", "value": "TLGYITOIZGKP"}],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"timezone": "America/Indiana/Petersburg",
"title": "EJWFXLHNHMCD",
SCIM_URN_USER_ENTERPRISE: {
"employeeNumber": "XHDMEJUURJNR",
"costCenter": "RXUYBXOTRCZH",
"organization": "CEXWXMBRYAHN",
"division": "XMPFMDCLRKCW",
"department": "BKMNJVMCJUYS",
"manager": "PNGSGXLYVWMV",
},
"userName": "imelda.auer@kshlerin.co.uk",
"userType": "PZFXORVSUAPU",
"x509Certificates": [{"primary": "true", "value": "KOVKWGIVVEHH"}],
},
)
updated = SCIMPatchProcessor().apply_patches(connection.attributes, req["Operations"])
self.assertEqual(
updated,
{
"active": True,
"addresses": [
{
"primary": "true",
"formatted": "BLJMCNXHYLZK",
"streetAddress": "7801 Jacobs Fork",
"locality": "HZJBJWFAKXDD",
"region": "GJXCXPMIIKWK",
"postalCode": "pv82 8ua",
"country": "India",
}
],
"displayName": "DPRLIJSFQMTL",
"emails": [{"primary": "true", "value": "scot@zemlak.uk"}],
"entitlements": [{"primary": "true", "value": "FTTUXWYDAAQC"}],
"externalId": "7faaefb0-0774-4d8e-8f6d-863c361bc72c",
"ims": [{"primary": "true", "value": "IGWZUUMCMKXS", "display": "PJVGMMKYYHRU"}],
"locale": "JLOJHLPWZODG",
"name": {
"formatted": "Dell",
"familyName": "Gay",
"givenName": "Kyler",
"middleName": "Hannah",
"honorificPrefix": "Cassie",
"honorificSuffix": "Yolanda",
},
"nickName": "BKSPMIRMFBTI",
"phoneNumbers": [
{"primary": "true", "value": "50-608-7660", "display": "50-608-7660"}
],
"photos": [{"primary": "true", "display": "KCONLNLSYTBP"}],
"preferredLanguage": "as-IN",
"profileUrl": "HPSEOIPXMGOH",
"roles": [{"primary": "true", "value": "TLGYITOIZGKP"}],
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"timezone": "America/Argentina/Rio_Gallegos",
"title": "NBZCOAXVYJUY",
SCIM_URN_USER_ENTERPRISE: {
"employeeNumber": "PDFWRRZBQOHB",
"costCenter": "HACMZWSEDOTQ",
"organization": "LXVHJUOLNCLS",
"division": "JASVTPKPBPMG",
"department": "GMSBFLMNPABY",
"manager": "PNGSGXLYVWMV",
},
"userName": "imelda.auer@kshlerin.co.uk",
"userType": "ZGJMYZRUORZE",
"x509Certificates": [{"primary": "true", "value": "KOVKWGIVVEHH"}],
},
)
def test_schema_urn_manager(self):
req = {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "Add",
"value": {
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:manager": "foo"
},
},
],
}
user = create_test_user()
source = SCIMSource.objects.create(slug=generate_id())
connection = SCIMSourceUser.objects.create(
user=user,
id=generate_id(),
source=source,
attributes={
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
},
)
updated = SCIMPatchProcessor().apply_patches(connection.attributes, req["Operations"])
self.assertEqual(
updated,
{
"meta": {"resourceType": "User"},
"active": True,
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
SCIM_URN_USER_ENTERPRISE,
],
"userName": "test@t.goauthentik.io",
"externalId": "test",
"displayName": "Test MS",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"manager": {"value": "foo"}
},
},
)

View File

@@ -1,6 +1,7 @@
"""SCIM Utils"""
from typing import Any
from uuid import UUID
from django.conf import settings
from django.core.paginator import Page, Paginator
@@ -21,6 +22,7 @@ from authentik.core.sources.mapper import SourceMapper
from authentik.lib.sync.mapper import PropertyMappingManager
from authentik.sources.scim.models import SCIMSource
from authentik.sources.scim.views.v2.auth import SCIMTokenAuth
from authentik.sources.scim.views.v2.exceptions import SCIMNotFoundError
SCIM_CONTENT_TYPE = "application/scim+json"
@@ -54,6 +56,13 @@ class SCIMView(APIView):
def get_authenticators(self):
return [SCIMTokenAuth(self)]
def remove_excluded_attributes(self, data: dict):
"""Remove attributes specified in excludedAttributes"""
excluded: str = self.request.query_params.get("excludedAttributes", "")
for key in excluded.split(","):
data.pop(key.strip(), None)
return data
def filter_parse(self, request: Request):
"""Parse the path of a Patch Operation"""
path = request.query_params.get("filter")
@@ -103,6 +112,12 @@ class SCIMObjectView(SCIMView):
# a source attribute before
self.mapper = SourceMapper(self.source)
self.manager = self.mapper.get_manager(self.model, ["data"])
for key, value in kwargs.items():
if key.endswith("_id"):
try:
UUID(value)
except ValueError:
raise SCIMNotFoundError("Invalid ID") from None
def build_object_properties(self, data: dict[str, Any]) -> dict[str, Any | dict[str, Any]]:
return self.mapper.build_object_properties(

View File

@@ -17,6 +17,7 @@ from authentik.core.models import Group, User
from authentik.providers.scim.clients.schema import SCIM_GROUP_SCHEMA, PatchOp, PatchOperation
from authentik.providers.scim.clients.schema import Group as SCIMGroupModel
from authentik.sources.scim.models import SCIMSourceGroup
from authentik.sources.scim.patch.processor import SCIMPatchProcessor
from authentik.sources.scim.views.v2.base import SCIMObjectView
from authentik.sources.scim.views.v2.exceptions import (
SCIMConflictError,
@@ -35,11 +36,12 @@ class GroupsView(SCIMObjectView):
payload = SCIMGroupModel(
schemas=[SCIM_GROUP_SCHEMA],
id=str(scim_group.group.pk),
externalId=scim_group.id,
externalId=scim_group.external_id,
displayName=scim_group.group.name,
members=[],
meta={
"resourceType": "Group",
"lastModified": scim_group.last_update,
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-groups",
@@ -54,7 +56,11 @@ class GroupsView(SCIMObjectView):
for member in scim_group.group.users.order_by("pk"):
member: User
payload.members.append(GroupMember(value=str(member.uuid)))
return payload.model_dump(mode="json", exclude_unset=True)
final_payload = payload.model_dump(mode="json", exclude_unset=True)
final_payload.update(scim_group.attributes)
return self.remove_excluded_attributes(
SCIMGroupModel.model_validate(final_payload).model_dump(mode="json", exclude_unset=True)
)
def get(self, request: Request, group_id: str | None = None, **kwargs) -> Response:
"""List Group handler"""
@@ -81,7 +87,7 @@ class GroupsView(SCIMObjectView):
)
@atomic
def update_group(self, connection: SCIMSourceGroup | None, data: QueryDict):
def update_group(self, connection: SCIMSourceGroup | None, data: QueryDict, apply_members=True):
"""Partial update a group"""
properties = self.build_object_properties(data)
@@ -94,7 +100,7 @@ class GroupsView(SCIMObjectView):
group.update_attributes(properties)
if "members" in data:
if "members" in data and apply_members:
query = Q()
for _member in data.get("members", []):
try:
@@ -105,14 +111,18 @@ class GroupsView(SCIMObjectView):
query |= Q(uuid=member.value)
if query:
group.users.set(User.objects.filter(query))
data["members"] = self._convert_members(group)
if not connection:
connection, _ = SCIMSourceGroup.objects.get_or_create(
connection, _ = SCIMSourceGroup.objects.update_or_create(
external_id=data.get("externalId") or str(uuid4()),
source=self.source,
group=group,
attributes=data,
id=data.get("externalId") or str(uuid4()),
defaults={
"attributes": data,
},
)
else:
connection.external_id = data.get("externalId", connection.external_id)
connection.attributes = data
connection.save()
return connection
@@ -139,6 +149,12 @@ class GroupsView(SCIMObjectView):
connection = self.update_group(connection, request.data)
return Response(self.group_to_scim(connection), status=200)
def _convert_members(self, group: Group):
users = []
for user in group.users.all().order_by("uuid"):
users.append({"value": str(user.uuid)})
return sorted(users, key=lambda u: u["value"])
@atomic
def patch(self, request: Request, group_id: str, **kwargs) -> Response:
"""Patch group handler"""
@@ -171,6 +187,13 @@ class GroupsView(SCIMObjectView):
query |= Q(uuid=member["value"])
if query:
connection.group.users.remove(*User.objects.filter(query))
patcher = SCIMPatchProcessor()
patched_data = patcher.apply_patches(
connection.attributes, request.data.get("Operations", [])
)
patched_data["members"] = self._convert_members(connection.group)
if patched_data != connection.attributes:
self.update_group(connection, patched_data, apply_members=False)
return Response(self.group_to_scim(connection), status=200)
@atomic

View File

@@ -33,9 +33,7 @@ class ServiceProviderConfigView(SCIMView):
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
"authenticationSchemes": auth_schemas,
# We only support patch for groups currently, so don't broadly advertise it.
# Implementations that require Group patch will use it regardless of this flag.
"patch": {"supported": False},
"patch": {"supported": True},
"bulk": {"supported": False, "maxOperations": 0, "maxPayloadSize": 0},
"filter": {
"supported": True,

View File

@@ -15,6 +15,7 @@ from authentik.core.models import User
from authentik.providers.scim.clients.schema import SCIM_USER_SCHEMA
from authentik.providers.scim.clients.schema import User as SCIMUserModel
from authentik.sources.scim.models import SCIMSourceUser
from authentik.sources.scim.patch.processor import SCIMPatchProcessor
from authentik.sources.scim.views.v2.base import SCIMObjectView
from authentik.sources.scim.views.v2.exceptions import SCIMConflictError, SCIMNotFoundError
@@ -29,7 +30,7 @@ class UsersView(SCIMObjectView):
payload = SCIMUserModel(
schemas=[SCIM_USER_SCHEMA],
id=str(scim_user.user.uuid),
externalId=scim_user.id,
externalId=scim_user.external_id,
userName=scim_user.user.username,
name=Name(
formatted=scim_user.user.name,
@@ -44,8 +45,7 @@ class UsersView(SCIMObjectView):
meta={
"resourceType": "User",
"created": scim_user.user.date_joined,
# TODO: use events to find last edit?
"lastModified": scim_user.user.date_joined,
"lastModified": scim_user.last_update,
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-users",
@@ -59,7 +59,9 @@ class UsersView(SCIMObjectView):
)
final_payload = payload.model_dump(mode="json", exclude_unset=True)
final_payload.update(scim_user.attributes)
return final_payload
return self.remove_excluded_attributes(
SCIMUserModel.model_validate(final_payload).model_dump(mode="json", exclude_unset=True)
)
def get(self, request: Request, user_id: str | None = None, **kwargs) -> Response:
"""List User handler"""
@@ -101,13 +103,16 @@ class UsersView(SCIMObjectView):
user.update_attributes(properties)
if not connection:
connection, _ = SCIMSourceUser.objects.get_or_create(
connection, _ = SCIMSourceUser.objects.update_or_create(
external_id=data.get("externalId") or str(uuid4()),
source=self.source,
user=user,
attributes=data,
id=data.get("externalId") or str(uuid4()),
defaults={
"attributes": data,
},
)
else:
connection.external_id = data.get("externalId", connection.external_id)
connection.attributes = data
connection.save()
return connection
@@ -127,6 +132,18 @@ class UsersView(SCIMObjectView):
connection = self.update_user(None, request.data)
return Response(self.user_to_scim(connection), status=201)
def patch(self, request: Request, user_id: str, **kwargs):
connection = SCIMSourceUser.objects.filter(source=self.source, user__uuid=user_id).first()
if not connection:
raise SCIMNotFoundError("User not found.")
patcher = SCIMPatchProcessor()
patched_data = patcher.apply_patches(
connection.attributes, request.data.get("Operations", [])
)
if patched_data != connection.attributes:
self.update_user(connection, patched_data)
return Response(self.user_to_scim(connection), status=200)
def put(self, request: Request, user_id: str, **kwargs) -> Response:
"""Update user handler"""
connection = SCIMSourceUser.objects.filter(source=self.source, user__uuid=user_id).first()

View File

@@ -13,7 +13,6 @@ from authentik.flows.exceptions import StageInvalidException
from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage
from authentik.lib.config import CONFIG
from authentik.lib.models import SerializerModel
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.time import timedelta_string_validator
from authentik.stages.authenticator.models import SideChannelDevice
from authentik.stages.email.utils import TemplateEmailMessage
@@ -160,9 +159,8 @@ class EmailDevice(SerializerModel, SideChannelDevice):
Event.new(
EventAction.CONFIGURATION_ERROR,
message=_("Exception occurred while rendering E-mail template"),
error=exception_to_string(exc),
template=stage.template,
).from_http(self.request)
).with_exception(exc).from_http(self.request)
raise StageInvalidException from exc
def __str__(self):

View File

@@ -17,7 +17,6 @@ from authentik.flows.challenge import (
from authentik.flows.exceptions import StageInvalidException
from authentik.flows.stage import ChallengeStageView
from authentik.lib.utils.email import mask_email
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.time import timedelta_from_string
from authentik.stages.authenticator_email.models import (
AuthenticatorEmailStage,
@@ -100,9 +99,8 @@ class AuthenticatorEmailStageView(ChallengeStageView):
Event.new(
EventAction.CONFIGURATION_ERROR,
message=_("Exception occurred while rendering E-mail template"),
error=exception_to_string(exc),
template=stage.template,
).from_http(self.request)
).with_exception(exc).from_http(self.request)
raise StageInvalidException from exc
def _has_email(self) -> str | None:

View File

@@ -4,7 +4,7 @@ from hashlib import sha256
from django.contrib.auth import get_user_model
from django.db import models
from django.http import HttpResponseBadRequest
from django.http import HttpRequest, HttpResponseBadRequest
from django.utils.translation import gettext_lazy as _
from django.views import View
from requests.exceptions import RequestException
@@ -19,7 +19,6 @@ from authentik.events.models import Event, EventAction, NotificationWebhookMappi
from authentik.events.utils import sanitize_item
from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage
from authentik.lib.models import SerializerModel
from authentik.lib.utils.errors import exception_to_string
from authentik.lib.utils.http import get_http_session
from authentik.stages.authenticator.models import SideChannelDevice
@@ -69,32 +68,44 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage):
help_text=_("Optionally modify the payload being sent to custom providers."),
)
def send(self, token: str, device: "SMSDevice"):
def send(self, request: HttpRequest, token: str, device: "SMSDevice"):
"""Send message via selected provider"""
if self.provider == SMSProviders.TWILIO:
return self.send_twilio(token, device)
return self.send_twilio(request, token, device)
if self.provider == SMSProviders.GENERIC:
return self.send_generic(token, device)
return self.send_generic(request, token, device)
raise ValueError(f"invalid provider {self.provider}")
def get_message(self, token: str) -> str:
"""Get SMS message"""
return _("Use this code to authenticate in authentik: {token}".format_map({"token": token}))
def send_twilio(self, token: str, device: "SMSDevice"):
def send_twilio(self, request: HttpRequest, token: str, device: "SMSDevice"):
"""send sms via twilio provider"""
client = Client(self.account_sid, self.auth)
message_body = str(self.get_message(token))
if self.mapping:
payload = sanitize_item(
self.mapping.evaluate(
user=device.user,
request=request,
device=device,
token=token,
stage=self,
)
)
message_body = payload.get("message", message_body)
try:
message = client.messages.create(
to=device.phone_number, from_=self.from_number, body=str(self.get_message(token))
to=device.phone_number, from_=self.from_number, body=message_body
)
LOGGER.debug("Sent SMS", to=device, message=message.sid)
except TwilioRestException as exc:
LOGGER.warning("Error sending token by Twilio SMS", exc=exc, msg=exc.msg)
raise ValidationError(exc.msg) from None
def send_generic(self, token: str, device: "SMSDevice"):
def send_generic(self, request: HttpRequest, token: str, device: "SMSDevice"):
"""Send SMS via outside API"""
payload = {
"From": self.from_number,
@@ -107,7 +118,7 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage):
payload = sanitize_item(
self.mapping.evaluate(
user=device.user,
request=None,
request=request,
device=device,
token=token,
stage=self,
@@ -142,10 +153,9 @@ class AuthenticatorSMSStage(ConfigurableStage, FriendlyNamedStage, Stage):
Event.new(
EventAction.CONFIGURATION_ERROR,
message="Error sending SMS",
exc=exception_to_string(exc),
status_code=response.status_code,
body=response.text,
).set_user(device.user).save()
).with_exception(exc).set_user(device.user).save()
if response.status_code >= HttpResponseBadRequest.status_code:
raise ValidationError(response.text) from None
raise

View File

@@ -71,7 +71,7 @@ class AuthenticatorSMSStageView(ChallengeStageView):
raise ValidationError(_("Invalid phone number"))
# No code yet, but we have a phone number, so send a verification message
device: SMSDevice = self.request.session[SESSION_KEY_SMS_DEVICE]
stage.send(device.token, device)
stage.send(self.request, device.token, device)
def _has_phone_number(self) -> str | None:
context = self.executor.plan.context

View File

@@ -9,7 +9,7 @@ from django.http.response import Http404
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as __
from django.utils.translation import gettext_lazy as _
from rest_framework.fields import CharField, DateTimeField
from rest_framework.fields import CharField, ChoiceField, DateTimeField
from rest_framework.serializers import ValidationError
from structlog.stdlib import get_logger
from webauthn import options_to_json
@@ -18,7 +18,7 @@ from webauthn.authentication.verify_authentication_response import verify_authen
from webauthn.helpers import parse_authentication_credential_json
from webauthn.helpers.base64url_to_bytes import base64url_to_bytes
from webauthn.helpers.exceptions import InvalidAuthenticationResponse, InvalidJSONStructure
from webauthn.helpers.structs import UserVerificationRequirement
from webauthn.helpers.structs import PublicKeyCredentialType, UserVerificationRequirement
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.models import Application, User
@@ -48,7 +48,7 @@ if TYPE_CHECKING:
class DeviceChallenge(PassiveSerializer):
"""Single device challenge"""
device_class = CharField()
device_class = ChoiceField(choices=DeviceClasses.choices)
device_uid = CharField()
challenge = JSONDictField()
last_used = DateTimeField(allow_null=True)
@@ -124,7 +124,7 @@ def select_challenge(request: HttpRequest, device: Device):
def select_challenge_sms(request: HttpRequest, device: SMSDevice):
"""Send SMS"""
device.generate_token()
device.stage.send(device.token, device)
device.stage.send(request, device.token, device)
def select_challenge_email(request: HttpRequest, device: EmailDevice):
@@ -157,6 +157,12 @@ def validate_challenge_webauthn(data: dict, stage_view: StageView, user: User) -
request = stage_view.request
challenge = stage_view.executor.plan.context.get(PLAN_CONTEXT_WEBAUTHN_CHALLENGE)
stage: AuthenticatorValidateStage = stage_view.executor.current_stage
if "MinuteMaid" in request.META.get("HTTP_USER_AGENT", ""):
# Workaround for Android sign-in, when signing into Google Workspace on android while
# adding the account to the system (not in Chrome), for some reason `type` is not set
# so in that case we fall back to `public-key`
# since that's the only option we support anyways
data.setdefault("type", PublicKeyCredentialType.PUBLIC_KEY)
try:
credential = parse_authentication_credential_json(data)
except InvalidJSONStructure as exc:

View File

@@ -173,6 +173,7 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
{
"auth_method": "auth_mfa",
"auth_method_args": {
"known_device": False,
"mfa_devices": [
{
"app": "authentik_stages_authenticator_duo",
@@ -180,7 +181,7 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
"name": "",
"pk": duo_device.pk,
}
]
],
},
"http_request": {
"args": {},

View File

@@ -153,13 +153,13 @@ class AuthenticatorValidateStageTests(FlowTestCase):
plan.append_stage(stage)
plan.context[PLAN_CONTEXT_DEVICE_CHALLENGES] = [
{
"device_class": "static",
"device_class": DeviceClasses.STATIC,
"device_uid": "1",
"challenge": {},
"last_used": now(),
},
{
"device_class": "totp",
"device_class": DeviceClasses.TOTP,
"device_uid": "2",
"challenge": {},
"last_used": now(),
@@ -172,7 +172,7 @@ class AuthenticatorValidateStageTests(FlowTestCase):
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
data={
"selected_challenge": {
"device_class": "baz",
"device_class": DeviceClasses.WEBAUTHN,
"device_uid": "quox",
"challenge": {},
"last_used": None,

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