Compare commits

...

78 Commits

Author SHA1 Message Date
a9373d60d0 Update index.js
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
2025-04-07 19:59:19 +02:00
82fadf587b web: Use ESBuild for bundling. Split out webauthn utils. Prep for
TypeScript monorepo.
2025-04-07 19:59:19 +02:00
220378b3f2 web: Fix TypeScript compilation issues for mixins, events. (#13766) 2025-04-07 19:53:51 +02:00
363d655378 web: Normalize client-side error handling (#13595)
web: Clean up error handling. Prep for permission checks.

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

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

* Clarified Knocknoc config

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

* Fixed typos

* fixed note markdown

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

---------

Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-07 12:00:43 -05:00
3ad7f4dc24 sources: move identifier to parent model (#13797)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-07 18:01:41 +02:00
c5045e8792 stages/email: fix for newlines in emails (#13799)
stages/email: fix for newlines in emails (#13712)

* Test fix for newlines in emails

* fix linting

* remove base64 names from email address

* Make better checks on message.to

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

* Added instructions for skipobject to each source

* removed saml

* removed oauth

* Updates

* Added provider SkipObject instructions

* combined examples into one

* modified kerberos python snippet as per suggestion from Marc

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

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

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

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

* Clarified how to use the exception

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

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

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

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

* fixed missing ) after gws

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

* fixed missing . from /scim

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

* fixing broken links

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

* Fixed links

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

---------

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

* Added details on trace and debug modes

* changed file to .mdx format

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

* Modified trace section

* Applied suggestions from dominic

* Prettier update

* Fixed tabs and lowercased the headers

* More tab fixes - prettier causing issues

* Prettier fix

* removed headers from inside tab sections

* added tabs import

* Changed line positioning for tabs import

* Update website/docs/troubleshooting/logs.mdx

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

* Applied suggestions from Dominic and Tana

* .

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

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

---------

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

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

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

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

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

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

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

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

* fix

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

---------

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

* Typo

* Added testing step and formatted URLs

* Removed unnecessary URL

* Updated to newer templater

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Edited code marks

* Bolded some UI elements

---------

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

* Added mention of OS specific section

* Updated to include synology instructions

* Fixed typos

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

* Added headers

* Updated keytool documentation link to JDK21 (latest)

* Squashed commit of the following:

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

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

    * website/docs: ops: service accounts

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    * Dewi's suggestions

    ---------

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

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

    website/integrations: add mailcow (#13727)

    * Add mailcow to Applications

    * Update wording and layout

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

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

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

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

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

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

    * lint

    ---------

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

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

    website: edit menu items (#13747)

    for review

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

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

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

    * website/integrations-all: update authentik configuration template

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

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

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

    This reverts commit 8378502090.

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

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

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

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

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

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

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

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

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

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

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

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

    Translate locale/en/LC_MESSAGES/django.po in zh_CN

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

    Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>

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

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

    Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025023.1 to 3.2025023.2.
    - [Release notes](https://github.com/goauthentik/client-go/releases)
    - [Changelog](https://github.com/goauthentik/client-go/blob/main/model_version_history.go)
    - [Commits](https://github.com/goauthentik/client-go/compare/v3.2025023.1...v3.2025023.2)

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

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

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

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

    Squash sdko/closes-13562

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

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

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

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

    web: bump API Client version (#13741)

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

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

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

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

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

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

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

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

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

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

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

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

    ---------

    Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>

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

    website/docs: style guide (#13704)

    * new word choices, tweaks

    * shockingly, a typo

    * tweaks

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

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

    ---------

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

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

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

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

    core, web: update translations (#13728)

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

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

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

    Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025022.6 to 3.2025023.1.
    - [Release notes](https://github.com/goauthentik/client-go/releases)
    - [Changelog](https://github.com/goauthentik/client-go/blob/main/model_version_history.go)
    - [Commits](https://github.com/goauthentik/client-go/compare/v3.2025022.6...v3.2025023.1)

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

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

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

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

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

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

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

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

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

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

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

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

    Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.10 to 0.6.11.
    - [Release notes](https://github.com/astral-sh/uv/releases)
    - [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
    - [Commits](https://github.com/astral-sh/uv/compare/0.6.10...0.6.11)

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

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

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

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

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

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

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

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

    * better cleanup

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

    * more polish

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

    * more cleanup

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

    * add tests

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

    * fix multiple redirects, add e2e test

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

    * unrelated: add sp initiated post test

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

    * add SAML parallel test

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

    * format

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

    * optimise detection of when authentication is in progress

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

    * better backoff timing

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

    ---------

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

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

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

    * core: bump oss/go/microsoft/golang

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

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

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

    * upstream docker image, use native fips

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

    * bump go version

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

    ---------

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    * website/docs: add reference to setting in CVE

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

    * reword

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

    ---------

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

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

    web: bump API Client version (#13708)

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

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

    release: 2025.2.3 (#13705)

    * release: 2025.2.3

    * fix uv lock not being bumped

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

    ---------

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

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

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

    * website/docs: fix 2025 CVE category title

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

    * add sideeffect of changing session backend

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

    ---------

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

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

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

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

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

    * update

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

    * update v2

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

    * format

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

    ---------

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

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

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

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

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

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

    * refactor cleanup behavior after stage form submit

    * refresh captcha on failing Identification stage

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

    This reverts commit b7beac6795.

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

    ---------

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

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

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

    discovered by @dominic-r

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    * Update authentik/lib/default.yml

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

    * fix linting to please the ci check

    ---------

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

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

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

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

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

    * auto-expand if there's just one task

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

    ---------

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

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

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

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

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

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

    * init

    * 6 more

    * tana...

    * quick reformat

    * welp only time for one change

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * Revert "wip"

    This reverts commit e71f0d22e3f093350e8d12eaad5e5c0f9d38253c.

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * wip

    * a

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

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

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

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

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

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

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

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

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

    * fix lint

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

    * fix v2

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

    * fix v3

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

    ---------

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

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

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

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

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

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

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

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

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

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

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-version: 2.1007.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-03 14:15:50 +02:00
8f689890df core: bump astral-sh/uv from 0.6.11 to 0.6.12 (#13756)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.11 to 0.6.12.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.6.11...0.6.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-03 14:13:43 +02:00
ec49b2e0e0 website/integrations: calibre-web: document (#12477)
* website/integrations: calibre-web: add to sidebar

Adds the calibre-web integration to the sidebar.

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

* website/integrations: calibre-web: init

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

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

* website/integrations: calibre-web: service configuration

Adds configuration documentation for calibre-web

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

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

* Update index.md

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

* Changed proider pair instructions to new version

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

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

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

---------

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Dewi's suggestions

---------

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

* Update wording and layout

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

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

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

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

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

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

* lint

---------

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

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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 18:29:16 +02:00
f5941e403b translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#13736)
Translate locale/en/LC_MESSAGES/django.po in zh_CN

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-04-01 18:18:59 +02:00
ff3cf8c10e core: bump goauthentik.io/api/v3 from 3.2025023.1 to 3.2025023.2 (#13746)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2025023.1 to 3.2025023.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Changelog](https://github.com/goauthentik/client-go/blob/main/model_version_history.go)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2025023.1...v3.2025023.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 18:18:42 +02:00
bfa6328172 web/common: utils: fix infinite value handling in getRelativeTime function (#13564)
Squash sdko/closes-13562
2025-04-01 06:46:29 -07:00
4c9691c932 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#13744)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-04-01 12:58:43 +02:00
a0f1566b4c web: bump API Client version (#13741)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-04-01 02:15:47 +02:00
46261a4f42 */saml: allow for domainless SAML URLs (#13737) 2025-04-01 01:41:18 +02:00
8b42ff1e97 core: fix error when viewing used_by for built-in source (#13588)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-03-31 16:36:14 +00:00
ca4cb0d251 translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#13738)
* Translate locale/en/LC_MESSAGES/django.po in fr

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

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

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

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-03-31 15:54:37 +00:00
a5a0fa79dd website/docs: style guide (#13704)
* new word choices, tweaks

* shockingly, a typo

* tweaks

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

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

---------

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 12:27:56 +02:00
d989f23907 website: bump the build group in /website with 3 updates (#13730)
Bumps the build group in /website with 3 updates: [@rspack/binding-darwin-arm64](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack), [@rspack/binding-linux-arm64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack) and [@rspack/binding-linux-x64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack).


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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 12:27:44 +02:00
059180edef core: bump astral-sh/uv from 0.6.10 to 0.6.11 (#13733)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.10 to 0.6.11.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.6.10...0.6.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-31 12:27:18 +02:00
22f30634a8 website/docs: Fix Caddy forward auth example (#13726) 2025-03-30 20:28:11 +02:00
35ff418c42 policies: buffered policy access view for concurrent authorization attempts when unauthenticated (#13629)
* policies: buffered policy access view for concurrent authorization attempts when unauthenticated

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

* better cleanup

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

* more polish

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

* more cleanup

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

* add tests

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

* fix multiple redirects, add e2e test

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

* unrelated: add sp initiated post test

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

* add SAML parallel test

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

* format

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

* optimise detection of when authentication is in progress

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

* better backoff timing

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

---------

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

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

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

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

* upstream docker image, use native fips

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

* bump go version

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

---------

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

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

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

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

* reword

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-28 17:42:45 +01:00
22fa3a7fba web: bump API Client version (#13708)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-03-28 17:42:24 +01:00
bcfd6fefa7 release: 2025.2.3 (#13705)
* release: 2025.2.3

* fix uv lock not being bumped

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

---------

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

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

* add sideeffect of changing session backend

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

---------

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

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

* update

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

* update v2

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

* format

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

---------

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

* refresh captcha on failing Identification stage

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

This reverts commit b7beac6795.

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

---------

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-28 13:21:30 +01:00
8ee90826fc enterprise/stages/source: set is_redirected in flow source stage redirects to (#13604)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-27 19:07:36 +01:00
8c7d4d2f5e website/docs: Clarify frontend development. Document local overrides. (#13586)
* website/docs: Clarify setup flow. Document local overrides.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Update authentik/lib/default.yml

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

* fix linting to please the ci check

---------

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

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

* auto-expand if there's just one task

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

---------

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

* 6 more

* tana...

* quick reformat

* welp only time for one change

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Revert "wip"

This reverts commit e71f0d22e3f093350e8d12eaad5e5c0f9d38253c.

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

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

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

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

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

* fix lint

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

* fix v2

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

* fix v3

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

---------

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


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

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

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 14:22:25 +01:00
88662b54c1 core: bump astral-sh/uv from 0.6.9 to 0.6.10 (#13669)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.6.9 to 0.6.10.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.6.9...0.6.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 12:01:43 +01:00
b38bc8c1c4 lifecycle/aws: bump aws-cdk from 2.1005.0 to 2.1006.0 in /lifecycle/aws (#13670)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1005.0 to 2.1006.0.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1006.0/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 12:00:06 +01:00
a9b648842a website/docs: Flesh out integrations copy changes. (#13619)
* website/docs: Flesh out integrations copy changes.

* Apply suggestions from code review

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

* Lint.

* Revert removed section. Fix links.

* reorder integrations page sections

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

* add back page title

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

* move cards to very end of topic

* fix broken anchor link

---------

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

* Included kubernetes instructions

* Fixed typos

* Fixed commands

* typo

* Updated kubernetes section

* updated as per suggestions from Dominic

* further changes to simplify the document

* Added section about Ctrl + C to stop logs

---------

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

* Apply suggestions from code review

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

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

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

* Apply suggestions from code review

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

* Update index.md

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

* website/docs: Reorder.

---------

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

* Use blankspace replace in names

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

* added note about a PR

* Update .github/ISSUE_TEMPLATE/docs_issue.md

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

* Update .github/ISSUE_TEMPLATE/docs_issue.md

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

---------

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

Signed-off-by: joeftiger <j.oeftiger@protonmail.com>
2025-03-24 18:44:08 -05:00
9f9524fbcb ci: stop publishing latest tag (#13245)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-24 20:23:55 +00:00
1df87cdf77 root: fix dependency install due to description-file (#13655)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-03-24 20:18:18 +00:00
325 changed files with 7966 additions and 5886 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2025.2.2
current_version = 2025.2.3
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
@ -17,6 +17,8 @@ optional_value = final
[bumpversion:file:pyproject.toml]
[bumpversion:file:uv.lock]
[bumpversion:file:package.json]
[bumpversion:file:docker-compose.yml]

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

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

View File

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

View File

@ -36,11 +36,6 @@ jobs:
run: |
export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION
- name: Upgrade /web/packages/sfe
working-directory: web/packages/sfe
run: |
export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION
- uses: peter-evans/create-pull-request@v7
id: cpr
with:

View File

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

View File

@ -30,7 +30,6 @@ WORKDIR /work/web
RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \
--mount=type=bind,target=/work/web/packages/sfe/package.json,src=./web/packages/sfe/package.json \
--mount=type=bind,target=/work/web/scripts,src=./web/scripts \
--mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
npm ci --include=dev
@ -43,7 +42,7 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build
# Stage 3: Build go proxy
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-bookworm AS go-builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
ARG TARGETOS
ARG TARGETARCH
@ -76,7 +75,7 @@ COPY ./go.sum /go/src/goauthentik.io/go.sum
RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
--mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/authentik ./cmd/server
# Stage 4: MaxMind GeoIP
@ -94,9 +93,9 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
/bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 5: Download uv
FROM ghcr.io/astral-sh/uv:0.6.9 AS uv
FROM ghcr.io/astral-sh/uv:0.6.12 AS uv
# Stage 6: Base python image
FROM ghcr.io/goauthentik/fips-python:3.12.8-slim-bookworm-fips AS python-base
FROM ghcr.io/goauthentik/fips-python:3.12.9-slim-bookworm-fips AS python-base
ENV VENV_PATH="/ak-root/.venv" \
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \

View File

@ -2,7 +2,7 @@
from os import environ
__version__ = "2025.2.2"
__version__ = "2025.2.3"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

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

View File

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

View File

@ -1,13 +1,14 @@
"""User API Views"""
from datetime import timedelta
from importlib import import_module
from json import loads
from typing import Any
from django.conf import settings
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.models import Permission
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core.cache import cache
from django.contrib.sessions.backends.base import SessionBase
from django.db.models.functions import ExtractHour
from django.db.transaction import atomic
from django.db.utils import IntegrityError
@ -91,6 +92,7 @@ from authentik.stages.email.tasks import send_mails
from authentik.stages.email.utils import TemplateEmailMessage
LOGGER = get_logger()
SessionStore: SessionBase = import_module(settings.SESSION_ENGINE).SessionStore
class UserGroupSerializer(ModelSerializer):
@ -373,7 +375,7 @@ class UsersFilter(FilterSet):
method="filter_attributes",
)
is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser")
is_superuser = BooleanFilter(field_name="ak_groups", method="filter_is_superuser")
uuid = UUIDFilter(field_name="uuid")
path = CharFilter(field_name="path")
@ -391,6 +393,11 @@ class UsersFilter(FilterSet):
queryset=Group.objects.all().order_by("name"),
)
def filter_is_superuser(self, queryset, name, value):
if value:
return queryset.filter(ak_groups__is_superuser=True).distinct()
return queryset.exclude(ak_groups__is_superuser=True).distinct()
def filter_attributes(self, queryset, name, value):
"""Filter attributes by query args"""
try:
@ -769,7 +776,8 @@ class UserViewSet(UsedByMixin, ModelViewSet):
if not instance.is_active:
sessions = AuthenticatedSession.objects.filter(user=instance)
session_ids = sessions.values_list("session_key", flat=True)
cache.delete_many(f"{KEY_PREFIX}{session}" for session in session_ids)
for session in session_ids:
SessionStore(session).delete()
sessions.delete()
LOGGER.debug("Deleted user's sessions", user=instance.username)
return response

View File

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

View File

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

View File

@ -761,11 +761,17 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
@property
def component(self) -> str:
"""Return component used to edit this object"""
if self.managed == self.MANAGED_INBUILT:
return ""
raise NotImplementedError
@property
def property_mapping_type(self) -> "type[PropertyMapping]":
"""Return property mapping type used by this object"""
if self.managed == self.MANAGED_INBUILT:
from authentik.core.models import PropertyMapping
return PropertyMapping
raise NotImplementedError
def ui_login_button(self, request: HttpRequest) -> UILoginButton | None:
@ -780,10 +786,14 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
def get_base_user_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
"""Get base properties for a user to build final properties upon."""
if self.managed == self.MANAGED_INBUILT:
return {}
raise NotImplementedError
def get_base_group_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
"""Get base properties for a group to build final properties upon."""
if self.managed == self.MANAGED_INBUILT:
return {}
raise NotImplementedError
def __str__(self):
@ -814,6 +824,7 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
user = models.ForeignKey(User, on_delete=models.CASCADE)
source = models.ForeignKey(Source, on_delete=models.CASCADE)
identifier = models.TextField()
objects = InheritanceManager()
@ -827,6 +838,10 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
class Meta:
unique_together = (("user", "source"),)
indexes = (
models.Index(fields=("identifier",)),
models.Index(fields=("source", "identifier")),
)
class GroupSourceConnection(SerializerModel, CreatedUpdatedModel):

View File

@ -1,7 +1,10 @@
"""authentik core signals"""
from importlib import import_module
from django.conf import settings
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.contrib.sessions.backends.base import SessionBase
from django.core.cache import cache
from django.core.signals import Signal
from django.db.models import Model
@ -25,6 +28,7 @@ password_changed = Signal()
login_failed = Signal()
LOGGER = get_logger()
SessionStore: SessionBase = import_module(settings.SESSION_ENGINE).SessionStore
@receiver(post_save, sender=Application)
@ -60,8 +64,7 @@ def user_logged_out_session(sender, request: HttpRequest, user: User, **_):
@receiver(pre_delete, sender=AuthenticatedSession)
def authenticated_session_delete(sender: type[Model], instance: "AuthenticatedSession", **_):
"""Delete session when authenticated session is deleted"""
cache_key = f"{KEY_PREFIX}{instance.session_key}"
cache.delete(cache_key)
SessionStore(instance.session_key).delete()
@receiver(pre_save)

View File

@ -36,6 +36,7 @@ from authentik.flows.planner import (
)
from authentik.flows.stage import StageView
from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_GET
from authentik.lib.utils.urls import is_url_absolute
from authentik.lib.views import bad_request_message
from authentik.policies.denied import AccessDeniedResponse
from authentik.policies.utils import delete_none_values
@ -48,6 +49,7 @@ LOGGER = get_logger()
PLAN_CONTEXT_SOURCE_GROUPS = "source_groups"
SESSION_KEY_SOURCE_FLOW_STAGES = "authentik/flows/source_flow_stages"
SESSION_KEY_SOURCE_FLOW_CONTEXT = "authentik/flows/source_flow_context"
SESSION_KEY_OVERRIDE_FLOW_TOKEN = "authentik/flows/source_override_flow_token" # nosec
@ -208,6 +210,8 @@ class SourceFlowManager:
final_redirect = self.request.session.get(SESSION_KEY_GET, {}).get(
NEXT_ARG_NAME, "authentik_core:if-user"
)
if not is_url_absolute(final_redirect):
final_redirect = "authentik_core:if-user"
flow_context.update(
{
# Since we authenticate the user by their token, they have no backend set
@ -261,6 +265,7 @@ class SourceFlowManager:
plan.append_stage(stage)
for stage in self.request.session.get(SESSION_KEY_SOURCE_FLOW_STAGES, []):
plan.append_stage(stage)
plan.context.update(self.request.session.get(SESSION_KEY_SOURCE_FLOW_CONTEXT, {}))
return plan.to_redirect(self.request, flow)
def handle_auth(

View File

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

View File

@ -1,6 +1,7 @@
"""Test Users API"""
from datetime import datetime
from json import loads
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core.cache import cache
@ -15,7 +16,12 @@ from authentik.core.models import (
User,
UserTypes,
)
from authentik.core.tests.utils import create_test_admin_user, create_test_brand, create_test_flow
from authentik.core.tests.utils import (
create_test_admin_user,
create_test_brand,
create_test_flow,
create_test_user,
)
from authentik.flows.models import FlowDesignation
from authentik.lib.generators import generate_id, generate_key
from authentik.stages.email.models import EmailStage
@ -26,7 +32,7 @@ class TestUsersAPI(APITestCase):
def setUp(self) -> None:
self.admin = create_test_admin_user()
self.user = User.objects.create(username="test-user")
self.user = create_test_user()
def test_filter_type(self):
"""Test API filtering by type"""
@ -41,6 +47,35 @@ class TestUsersAPI(APITestCase):
)
self.assertEqual(response.status_code, 200)
def test_filter_is_superuser(self):
"""Test API filtering by superuser status"""
User.objects.all().delete()
admin = create_test_admin_user()
self.client.force_login(admin)
# Test superuser
response = self.client.get(
reverse("authentik_api:user-list"),
data={
"is_superuser": True,
},
)
self.assertEqual(response.status_code, 200)
body = loads(response.content)
self.assertEqual(len(body["results"]), 1)
self.assertEqual(body["results"][0]["username"], admin.username)
# Test non-superuser
user = create_test_user()
response = self.client.get(
reverse("authentik_api:user-list"),
data={
"is_superuser": False,
},
)
self.assertEqual(response.status_code, 200)
body = loads(response.content)
self.assertEqual(len(body["results"]), 1, body)
self.assertEqual(body["results"][0]["username"], user.username)
def test_list_with_groups(self):
"""Test listing with groups"""
self.client.force_login(self.admin)
@ -99,6 +134,8 @@ class TestUsersAPI(APITestCase):
def test_recovery_email_no_flow(self):
"""Test user recovery link (no recovery flow set)"""
self.client.force_login(self.admin)
self.user.email = ""
self.user.save()
response = self.client.post(
reverse("authentik_api:user-recovery-email", kwargs={"pk": self.user.pk})
)

View File

@ -13,7 +13,11 @@ from authentik.core.api.devices import AdminDeviceViewSet, DeviceViewSet
from authentik.core.api.groups import GroupViewSet
from authentik.core.api.property_mappings import PropertyMappingViewSet
from authentik.core.api.providers import ProviderViewSet
from authentik.core.api.sources import SourceViewSet, UserSourceConnectionViewSet
from authentik.core.api.sources import (
GroupSourceConnectionViewSet,
SourceViewSet,
UserSourceConnectionViewSet,
)
from authentik.core.api.tokens import TokenViewSet
from authentik.core.api.transactional_applications import TransactionalApplicationView
from authentik.core.api.users import UserViewSet
@ -81,6 +85,7 @@ api_urlpatterns = [
("core/tokens", TokenViewSet),
("sources/all", SourceViewSet),
("sources/user_connections/all", UserSourceConnectionViewSet),
("sources/group_connections/all", GroupSourceConnectionViewSet),
("providers/all", ProviderViewSet),
("propertymappings/all", PropertyMappingViewSet),
("authenticators/all", DeviceViewSet, "device"),

View File

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

View File

@ -49,6 +49,6 @@
</main>
<span class="mt-3 mb-0 text-muted text-center">{% trans 'Powered by authentik' %}</span>
</div>
<script src="{% static 'dist/sfe/index.js' %}"></script>
<script src="{% static 'dist/sfe/main.js' %}"></script>
</body>
</html>

View File

@ -69,6 +69,7 @@ SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre"
SESSION_KEY_GET = "authentik/flows/get"
SESSION_KEY_POST = "authentik/flows/post"
SESSION_KEY_HISTORY = "authentik/flows/history"
SESSION_KEY_AUTH_STARTED = "authentik/flows/auth_started"
QS_KEY_TOKEN = "flow_token" # nosec
QS_QUERY = "query"
@ -453,6 +454,7 @@ class FlowExecutorView(APIView):
SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_PLAN,
SESSION_KEY_GET,
SESSION_KEY_AUTH_STARTED,
# We might need the initial POST payloads for later requests
# SESSION_KEY_POST,
# We don't delete the history on purpose, as a user might

View File

@ -6,14 +6,22 @@ from django.shortcuts import get_object_or_404
from ua_parser.user_agent_parser import Parse
from authentik.core.views.interface import InterfaceView
from authentik.flows.models import Flow
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.views.executor import SESSION_KEY_AUTH_STARTED
class FlowInterfaceView(InterfaceView):
"""Flow interface"""
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
kwargs["flow"] = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
kwargs["flow"] = flow
if (
not self.request.user.is_authenticated
and flow.designation == FlowDesignation.AUTHENTICATION
):
self.request.session[SESSION_KEY_AUTH_STARTED] = True
self.request.session.save()
kwargs["inspector"] = "inspector" in self.request.GET
return super().get_context_data(**kwargs)

View File

@ -1,5 +1,20 @@
# update website/docs/install-config/configuration/configuration.mdx
# This is the default configuration file
# authentik configuration
#
# https://docs.goauthentik.io/docs/install-config/configuration/
#
# To override the settings in this file, run the following command from the repository root:
#
# ```shell
# make gen-dev-config
# ```
#
# You may edit the generated file to override the configuration below.
#
# When making modifying the default configuration file,
# ensure that the corresponding documentation is updated to match.
#
# @see {@link ../../website/docs/install-config/configuration/configuration.mdx Configuration documentation} for more information.
postgresql:
host: localhost
name: authentik

View File

@ -18,6 +18,15 @@ class SerializerModel(models.Model):
@property
def serializer(self) -> type[BaseSerializer]:
"""Get serializer for this model"""
# Special handling for built-in source
if (
hasattr(self, "managed")
and hasattr(self, "MANAGED_INBUILT")
and self.managed == self.MANAGED_INBUILT
):
from authentik.core.api.sources import SourceSerializer
return SourceSerializer
raise NotImplementedError

View File

@ -13,6 +13,7 @@ from paramiko.ssh_exception import SSHException
from structlog.stdlib import get_logger
from yaml import safe_dump
from authentik import __version__
from authentik.outposts.apps import MANAGED_OUTPOST
from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException
from authentik.outposts.docker_ssh import DockerInlineSSH, SSHManagedExternallyException
@ -184,7 +185,7 @@ class DockerController(BaseController):
try:
self.client.images.pull(image)
except DockerException: # pragma: no cover
image = f"ghcr.io/goauthentik/{self.outpost.type}:latest"
image = f"ghcr.io/goauthentik/{self.outpost.type}:{__version__}"
self.client.images.pull(image)
return image

View File

@ -35,3 +35,4 @@ class AuthentikPoliciesConfig(ManagedAppConfig):
label = "authentik_policies"
verbose_name = "authentik Policies"
default = True
mountpoint = "policy/"

View File

@ -0,0 +1,89 @@
{% extends 'login/base_full.html' %}
{% load static %}
{% load i18n %}
{% block head %}
{{ block.super }}
<script>
let redirecting = false;
const checkAuth = async () => {
if (redirecting) return true;
const url = "{{ check_auth_url }}";
console.debug("authentik/policies/buffer: Checking authentication...");
try {
const result = await fetch(url, {
method: "HEAD",
});
if (result.status >= 400) {
return false
}
console.debug("authentik/policies/buffer: Continuing");
redirecting = true;
if ("{{ auth_req_method }}" === "post") {
document.querySelector("form").submit();
} else {
window.location.assign("{{ continue_url|escapejs }}");
}
} catch {
return false;
}
};
let timeout = 100;
let offset = 20;
let attempt = 0;
const main = async () => {
attempt += 1;
await checkAuth();
console.debug(`authentik/policies/buffer: Waiting ${timeout}ms...`);
setTimeout(main, timeout);
timeout += (offset * attempt);
if (timeout >= 2000) {
timeout = 2000;
}
}
document.addEventListener("visibilitychange", async () => {
if (document.hidden) return;
console.debug("authentik/policies/buffer: Checking authentication on tab activate...");
await checkAuth();
});
main();
</script>
{% endblock %}
{% block title %}
{% trans 'Waiting for authentication...' %} - {{ brand.branding_title }}
{% endblock %}
{% block card_title %}
{% trans 'Waiting for authentication...' %}
{% endblock %}
{% block card %}
<form class="pf-c-form" method="{{ auth_req_method }}" action="{{ continue_url }}">
{% if auth_req_method == "post" %}
{% for key, value in auth_req_body.items %}
<input type="hidden" name="{{ key }}" value="{{ value }}" />
{% endfor %}
{% endif %}
<div class="pf-c-empty-state">
<div class="pf-c-empty-state__content">
<div class="pf-c-empty-state__icon">
<span class="pf-c-spinner pf-m-xl" role="progressbar">
<span class="pf-c-spinner__clipper"></span>
<span class="pf-c-spinner__lead-ball"></span>
<span class="pf-c-spinner__tail-ball"></span>
</span>
</div>
<h1 class="pf-c-title pf-m-lg">
{% trans "You're already authenticating in another tab. This page will refresh once authentication is completed." %}
</h1>
</div>
</div>
<div class="pf-c-form__group pf-m-action">
<a href="{{ auth_req_url }}" class="pf-c-button pf-m-primary pf-m-block">
{% trans "Authenticate in this tab" %}
</a>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,121 @@
from django.contrib.auth.models import AnonymousUser
from django.contrib.sessions.middleware import SessionMiddleware
from django.http import HttpResponse
from django.test import RequestFactory, TestCase
from django.urls import reverse
from authentik.core.models import Application, Provider
from authentik.core.tests.utils import create_test_flow, create_test_user
from authentik.flows.models import FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import dummy_get_response
from authentik.policies.views import (
QS_BUFFER_ID,
SESSION_KEY_BUFFER,
BufferedPolicyAccessView,
BufferView,
PolicyAccessView,
)
class TestPolicyViews(TestCase):
"""Test PolicyAccessView"""
def setUp(self):
super().setUp()
self.factory = RequestFactory()
self.user = create_test_user()
def test_pav(self):
"""Test simple policy access view"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
class TestView(PolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/")
req.user = self.user
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 200)
self.assertEqual(res.content, b"foo")
def test_pav_buffer(self):
"""Test simple policy access view"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
class TestView(BufferedPolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
req.session.save()
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 302)
self.assertTrue(res.url.startswith(reverse("authentik_policies:buffer")))
def test_pav_buffer_skip(self):
"""Test simple policy access view (skip buffer)"""
provider = Provider.objects.create(
name=generate_id(),
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
class TestView(BufferedPolicyAccessView):
def resolve_provider_application(self):
self.provider = provider
self.application = app
def get(self, *args, **kwargs):
return HttpResponse("foo")
req = self.factory.get("/?skip_buffer=true")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk)
req.session.save()
res = TestView.as_view()(req)
self.assertEqual(res.status_code, 302)
self.assertTrue(res.url.startswith(reverse("authentik_flows:default-authentication")))
def test_buffer(self):
"""Test buffer view"""
uid = generate_id()
req = self.factory.get(f"/?{QS_BUFFER_ID}={uid}")
req.user = AnonymousUser()
middleware = SessionMiddleware(dummy_get_response)
middleware.process_request(req)
ts = generate_id()
req.session[SESSION_KEY_BUFFER % uid] = {
"method": "get",
"body": {},
"url": f"/{ts}",
}
req.session.save()
res = BufferView.as_view()(req)
self.assertEqual(res.status_code, 200)
self.assertIn(ts, res.render().content.decode())

View File

@ -1,7 +1,14 @@
"""API URLs"""
from django.urls import path
from authentik.policies.api.bindings import PolicyBindingViewSet
from authentik.policies.api.policies import PolicyViewSet
from authentik.policies.views import BufferView
urlpatterns = [
path("buffer", BufferView.as_view(), name="buffer"),
]
api_urlpatterns = [
("policies/all", PolicyViewSet),

View File

@ -1,23 +1,37 @@
"""authentik access helper classes"""
from typing import Any
from uuid import uuid4
from django.contrib import messages
from django.contrib.auth.mixins import AccessMixin
from django.contrib.auth.views import redirect_to_login
from django.http import HttpRequest, HttpResponse
from django.http import HttpRequest, HttpResponse, QueryDict
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.http import urlencode
from django.utils.translation import gettext as _
from django.views.generic.base import View
from django.views.generic.base import TemplateView, View
from structlog.stdlib import get_logger
from authentik.core.models import Application, Provider, User
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_POST
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import (
SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_AUTH_STARTED,
SESSION_KEY_PLAN,
SESSION_KEY_POST,
)
from authentik.lib.sentry import SentryIgnoredException
from authentik.policies.denied import AccessDeniedResponse
from authentik.policies.engine import PolicyEngine
from authentik.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger()
QS_BUFFER_ID = "af_bf_id"
QS_SKIP_BUFFER = "skip_buffer"
SESSION_KEY_BUFFER = "authentik/policies/pav_buffer/%s"
class RequestValidationError(SentryIgnoredException):
@ -125,3 +139,65 @@ class PolicyAccessView(AccessMixin, View):
for message in result.messages:
messages.error(self.request, _(message))
return result
def url_with_qs(url: str, **kwargs):
"""Update/set querystring of `url` with the parameters in `kwargs`. Original query string
parameters are retained"""
if "?" not in url:
return url + f"?{urlencode(kwargs)}"
url, _, qs = url.partition("?")
qs = QueryDict(qs, mutable=True)
qs.update(kwargs)
return url + f"?{urlencode(qs.items())}"
class BufferView(TemplateView):
"""Buffer view"""
template_name = "policies/buffer.html"
def get_context_data(self, **kwargs):
buf_id = self.request.GET.get(QS_BUFFER_ID)
buffer: dict = self.request.session.get(SESSION_KEY_BUFFER % buf_id)
kwargs["auth_req_method"] = buffer["method"]
kwargs["auth_req_body"] = buffer["body"]
kwargs["auth_req_url"] = url_with_qs(buffer["url"], **{QS_SKIP_BUFFER: True})
kwargs["check_auth_url"] = reverse("authentik_api:user-me")
kwargs["continue_url"] = url_with_qs(buffer["url"], **{QS_BUFFER_ID: buf_id})
return super().get_context_data(**kwargs)
class BufferedPolicyAccessView(PolicyAccessView):
"""PolicyAccessView which buffers access requests in case the user is not logged in"""
def handle_no_permission(self):
plan: FlowPlan | None = self.request.session.get(SESSION_KEY_PLAN)
authenticating = self.request.session.get(SESSION_KEY_AUTH_STARTED)
if plan:
flow = Flow.objects.filter(pk=plan.flow_pk).first()
if not flow or flow.designation != FlowDesignation.AUTHENTICATION:
LOGGER.debug("Not buffering request, no flow or flow not for authentication")
return super().handle_no_permission()
if not plan and authenticating is None:
LOGGER.debug("Not buffering request, no flow plan active")
return super().handle_no_permission()
if self.request.GET.get(QS_SKIP_BUFFER):
LOGGER.debug("Not buffering request, explicit skip")
return super().handle_no_permission()
buffer_id = str(uuid4())
LOGGER.debug("Buffering access request", bf_id=buffer_id)
self.request.session[SESSION_KEY_BUFFER % buffer_id] = {
"body": self.request.POST,
"url": self.request.build_absolute_uri(self.request.get_full_path()),
"method": self.request.method.lower(),
}
return redirect(
url_with_qs(reverse("authentik_policies:buffer"), **{QS_BUFFER_ID: buffer_id})
)
def dispatch(self, request, *args, **kwargs):
response = super().dispatch(request, *args, **kwargs)
if QS_BUFFER_ID in self.request.GET:
self.request.session.pop(SESSION_KEY_BUFFER % self.request.GET[QS_BUFFER_ID], None)
return response

View File

@ -30,7 +30,7 @@ from authentik.flows.stage import StageView
from authentik.lib.utils.time import timedelta_from_string
from authentik.lib.views import bad_request_message
from authentik.policies.types import PolicyRequest
from authentik.policies.views import PolicyAccessView, RequestValidationError
from authentik.policies.views import BufferedPolicyAccessView, RequestValidationError
from authentik.providers.oauth2.constants import (
PKCE_METHOD_PLAIN,
PKCE_METHOD_S256,
@ -328,7 +328,7 @@ class OAuthAuthorizationParams:
return code
class AuthorizationFlowInitView(PolicyAccessView):
class AuthorizationFlowInitView(BufferedPolicyAccessView):
"""OAuth2 Flow initializer, checks access to application and starts flow"""
params: OAuthAuthorizationParams

View File

@ -18,11 +18,11 @@ from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner
from authentik.flows.stage import RedirectStage
from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.engine import PolicyEngine
from authentik.policies.views import PolicyAccessView
from authentik.policies.views import BufferedPolicyAccessView
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
class RACStartView(PolicyAccessView):
class RACStartView(BufferedPolicyAccessView):
"""Start a RAC connection by checking access and creating a connection token"""
endpoint: Endpoint

View File

@ -0,0 +1,22 @@
# Generated by Django 5.0.13 on 2025-03-31 13:50
import authentik.lib.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_saml", "0017_samlprovider_authn_context_class_ref_mapping"),
]
operations = [
migrations.AlterField(
model_name="samlprovider",
name="acs_url",
field=models.TextField(
validators=[authentik.lib.models.DomainlessURLValidator(schemes=("http", "https"))],
verbose_name="ACS URL",
),
),
]

View File

@ -10,6 +10,7 @@ from structlog.stdlib import get_logger
from authentik.core.api.object_types import CreatableType
from authentik.core.models import PropertyMapping, Provider
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import (
DSA_SHA1,
@ -40,7 +41,9 @@ class SAMLBindings(models.TextChoices):
class SAMLProvider(Provider):
"""SAML 2.0 Endpoint for applications which support SAML."""
acs_url = models.URLField(verbose_name=_("ACS URL"))
acs_url = models.TextField(
validators=[DomainlessURLValidator(schemes=("http", "https"))], verbose_name=_("ACS URL")
)
audience = models.TextField(
default="",
blank=True,

View File

@ -15,7 +15,7 @@ from authentik.flows.models import in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner
from authentik.flows.views.executor import SESSION_KEY_POST
from authentik.lib.views import bad_request_message
from authentik.policies.views import PolicyAccessView
from authentik.policies.views import BufferedPolicyAccessView
from authentik.providers.saml.exceptions import CannotHandleAssertion
from authentik.providers.saml.models import SAMLBindings, SAMLProvider
from authentik.providers.saml.processors.authn_request_parser import AuthNRequestParser
@ -35,7 +35,7 @@ from authentik.stages.consent.stage import (
LOGGER = get_logger()
class SAMLSSOView(PolicyAccessView):
class SAMLSSOView(BufferedPolicyAccessView):
"""SAML SSO Base View, which plans a flow and injects our final stage.
Calls get/post handler."""
@ -83,7 +83,7 @@ class SAMLSSOView(PolicyAccessView):
def post(self, request: HttpRequest, application_slug: str) -> HttpResponse:
"""GET and POST use the same handler, but we can't
override .dispatch easily because PolicyAccessView's dispatch"""
override .dispatch easily because BufferedPolicyAccessView's dispatch"""
return self.get(request, application_slug)

View File

@ -1,13 +1,11 @@
"""Kerberos Source Serializer"""
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.sources import (
GroupSourceConnectionSerializer,
GroupSourceConnectionViewSet,
UserSourceConnectionSerializer,
UserSourceConnectionViewSet,
)
from authentik.core.api.used_by import UsedByMixin
from authentik.sources.kerberos.models import (
GroupKerberosSourceConnection,
UserKerberosSourceConnection,
@ -15,33 +13,20 @@ from authentik.sources.kerberos.models import (
class UserKerberosSourceConnectionSerializer(UserSourceConnectionSerializer):
"""Kerberos Source Serializer"""
class Meta:
class Meta(UserSourceConnectionSerializer.Meta):
model = UserKerberosSourceConnection
fields = UserSourceConnectionSerializer.Meta.fields + ["identifier"]
class UserKerberosSourceConnectionViewSet(UsedByMixin, ModelViewSet):
"""Source Viewset"""
class UserKerberosSourceConnectionViewSet(UserSourceConnectionViewSet, ModelViewSet):
queryset = UserKerberosSourceConnection.objects.all()
serializer_class = UserKerberosSourceConnectionSerializer
filterset_fields = ["source__slug"]
search_fields = ["source__slug"]
ordering = ["source__slug"]
owner_field = "user"
class GroupKerberosSourceConnectionSerializer(GroupSourceConnectionSerializer):
"""OAuth Group-Source connection Serializer"""
class Meta(GroupSourceConnectionSerializer.Meta):
model = GroupKerberosSourceConnection
class GroupKerberosSourceConnectionViewSet(GroupSourceConnectionViewSet):
"""Group-source connection Viewset"""
class GroupKerberosSourceConnectionViewSet(GroupSourceConnectionViewSet, ModelViewSet):
queryset = GroupKerberosSourceConnection.objects.all()
serializer_class = GroupKerberosSourceConnectionSerializer

View File

@ -0,0 +1,28 @@
from django.db import migrations
def migrate_identifier(apps, schema_editor):
db_alias = schema_editor.connection.alias
UserKerberosSourceConnection = apps.get_model(
"authentik_sources_kerberos", "UserKerberosSourceConnection"
)
for connection in UserKerberosSourceConnection.objects.using(db_alias).all():
connection.new_identifier = connection.identifier
connection.save(using=db_alias)
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_kerberos", "0002_kerberossource_kadmin_type"),
("authentik_core", "0044_usersourceconnection_new_identifier"),
]
operations = [
migrations.RunPython(code=migrate_identifier, reverse_code=migrations.RunPython.noop),
migrations.RemoveField(
model_name="userkerberossourceconnection",
name="identifier",
),
]

View File

@ -372,8 +372,6 @@ class KerberosSourcePropertyMapping(PropertyMapping):
class UserKerberosSourceConnection(UserSourceConnection):
"""Connection to configured Kerberos Sources."""
identifier = models.TextField()
@property
def serializer(self) -> type[Serializer]:
from authentik.sources.kerberos.api.source_connection import (

View File

@ -1,5 +1,3 @@
"""OAuth Source Serializer"""
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.sources import (
@ -12,11 +10,9 @@ from authentik.sources.oauth.models import GroupOAuthSourceConnection, UserOAuth
class UserOAuthSourceConnectionSerializer(UserSourceConnectionSerializer):
"""OAuth Source Serializer"""
class Meta(UserSourceConnectionSerializer.Meta):
model = UserOAuthSourceConnection
fields = UserSourceConnectionSerializer.Meta.fields + ["identifier", "access_token"]
fields = UserSourceConnectionSerializer.Meta.fields + ["access_token"]
extra_kwargs = {
**UserSourceConnectionSerializer.Meta.extra_kwargs,
"access_token": {"write_only": True},
@ -24,21 +20,15 @@ class UserOAuthSourceConnectionSerializer(UserSourceConnectionSerializer):
class UserOAuthSourceConnectionViewSet(UserSourceConnectionViewSet, ModelViewSet):
"""Source Viewset"""
queryset = UserOAuthSourceConnection.objects.all()
serializer_class = UserOAuthSourceConnectionSerializer
class GroupOAuthSourceConnectionSerializer(GroupSourceConnectionSerializer):
"""OAuth Group-Source connection Serializer"""
class Meta(GroupSourceConnectionSerializer.Meta):
model = GroupOAuthSourceConnection
class GroupOAuthSourceConnectionViewSet(GroupSourceConnectionViewSet, ModelViewSet):
"""Group-source connection Viewset"""
queryset = GroupOAuthSourceConnection.objects.all()
serializer_class = GroupOAuthSourceConnectionSerializer

View File

@ -0,0 +1,28 @@
from django.db import migrations
def migrate_identifier(apps, schema_editor):
db_alias = schema_editor.connection.alias
UserOAuthSourceConnection = apps.get_model(
"authentik_sources_oauth", "UserOAuthSourceConnection"
)
for connection in UserOAuthSourceConnection.objects.using(db_alias).all():
connection.new_identifier = connection.identifier
connection.save(using=db_alias)
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_oauth", "0008_groupoauthsourceconnection_and_more"),
("authentik_core", "0044_usersourceconnection_new_identifier"),
]
operations = [
migrations.RunPython(code=migrate_identifier, reverse_code=migrations.RunPython.noop),
migrations.RemoveField(
model_name="useroauthsourceconnection",
name="identifier",
),
]

View File

@ -286,7 +286,6 @@ class OAuthSourcePropertyMapping(PropertyMapping):
class UserOAuthSourceConnection(UserSourceConnection):
"""Authorized remote OAuth provider."""
identifier = models.CharField(max_length=255)
access_token = models.TextField(blank=True, null=True, default=None)
@property

View File

@ -1,5 +1,3 @@
"""Plex Source connection Serializer"""
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.sources import (
@ -12,14 +10,9 @@ from authentik.sources.plex.models import GroupPlexSourceConnection, UserPlexSou
class UserPlexSourceConnectionSerializer(UserSourceConnectionSerializer):
"""Plex Source connection Serializer"""
class Meta(UserSourceConnectionSerializer.Meta):
model = UserPlexSourceConnection
fields = UserSourceConnectionSerializer.Meta.fields + [
"identifier",
"plex_token",
]
fields = UserSourceConnectionSerializer.Meta.fields + ["plex_token"]
extra_kwargs = {
**UserSourceConnectionSerializer.Meta.extra_kwargs,
"plex_token": {"write_only": True},
@ -27,21 +20,15 @@ class UserPlexSourceConnectionSerializer(UserSourceConnectionSerializer):
class UserPlexSourceConnectionViewSet(UserSourceConnectionViewSet, ModelViewSet):
"""Plex Source connection Serializer"""
queryset = UserPlexSourceConnection.objects.all()
serializer_class = UserPlexSourceConnectionSerializer
class GroupPlexSourceConnectionSerializer(GroupSourceConnectionSerializer):
"""Plex Group-Source connection Serializer"""
class Meta(GroupSourceConnectionSerializer.Meta):
model = GroupPlexSourceConnection
class GroupPlexSourceConnectionViewSet(GroupSourceConnectionViewSet, ModelViewSet):
"""Group-source connection Viewset"""
queryset = GroupPlexSourceConnection.objects.all()
serializer_class = GroupPlexSourceConnectionSerializer

View File

@ -0,0 +1,29 @@
from django.db import migrations
def migrate_identifier(apps, schema_editor):
db_alias = schema_editor.connection.alias
UserPlexSourceConnection = apps.get_model("authentik_sources_plex", "UserPlexSourceConnection")
for connection in UserPlexSourceConnection.objects.using(db_alias).all():
connection.new_identifier = connection.identifier
connection.save(using=db_alias)
class Migration(migrations.Migration):
dependencies = [
(
"authentik_sources_plex",
"0004_groupplexsourceconnection_plexsourcepropertymapping_and_more",
),
("authentik_core", "0044_usersourceconnection_new_identifier"),
]
operations = [
migrations.RunPython(code=migrate_identifier, reverse_code=migrations.RunPython.noop),
migrations.RemoveField(
model_name="userplexsourceconnection",
name="identifier",
),
]

View File

@ -141,7 +141,6 @@ class UserPlexSourceConnection(UserSourceConnection):
"""Connect user and plex source"""
plex_token = models.TextField()
identifier = models.TextField()
@property
def serializer(self) -> type[Serializer]:

View File

@ -1,5 +1,3 @@
"""SAML Source Serializer"""
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.sources import (
@ -12,29 +10,20 @@ from authentik.sources.saml.models import GroupSAMLSourceConnection, UserSAMLSou
class UserSAMLSourceConnectionSerializer(UserSourceConnectionSerializer):
"""SAML Source Serializer"""
class Meta(UserSourceConnectionSerializer.Meta):
model = UserSAMLSourceConnection
fields = UserSourceConnectionSerializer.Meta.fields + ["identifier"]
class UserSAMLSourceConnectionViewSet(UserSourceConnectionViewSet, ModelViewSet):
"""Source Viewset"""
queryset = UserSAMLSourceConnection.objects.all()
serializer_class = UserSAMLSourceConnectionSerializer
class GroupSAMLSourceConnectionSerializer(GroupSourceConnectionSerializer):
"""OAuth Group-Source connection Serializer"""
class Meta(GroupSourceConnectionSerializer.Meta):
model = GroupSAMLSourceConnection
class GroupSAMLSourceConnectionViewSet(GroupSourceConnectionViewSet):
"""Group-source connection Viewset"""
class GroupSAMLSourceConnectionViewSet(GroupSourceConnectionViewSet, ModelViewSet):
queryset = GroupSAMLSourceConnection.objects.all()
serializer_class = GroupSAMLSourceConnectionSerializer

View File

@ -0,0 +1,35 @@
# Generated by Django 5.0.13 on 2025-03-31 13:53
import authentik.lib.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_saml", "0017_fix_x509subjectname"),
]
operations = [
migrations.AlterField(
model_name="samlsource",
name="slo_url",
field=models.TextField(
blank=True,
default=None,
help_text="Optional URL if your IDP supports Single-Logout.",
null=True,
validators=[authentik.lib.models.DomainlessURLValidator(schemes=("http", "https"))],
verbose_name="SLO URL",
),
),
migrations.AlterField(
model_name="samlsource",
name="sso_url",
field=models.TextField(
help_text="URL that the initial Login request is sent to.",
validators=[authentik.lib.models.DomainlessURLValidator(schemes=("http", "https"))],
verbose_name="SSO URL",
),
),
]

View File

@ -0,0 +1,26 @@
from django.db import migrations
def migrate_identifier(apps, schema_editor):
db_alias = schema_editor.connection.alias
UserSAMLSourceConnection = apps.get_model("authentik_sources_saml", "UserSAMLSourceConnection")
for connection in UserSAMLSourceConnection.objects.using(db_alias).all():
connection.new_identifier = connection.identifier
connection.save(using=db_alias)
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_saml", "0018_alter_samlsource_slo_url_alter_samlsource_sso_url"),
("authentik_core", "0044_usersourceconnection_new_identifier"),
]
operations = [
migrations.RunPython(code=migrate_identifier, reverse_code=migrations.RunPython.noop),
migrations.RemoveField(
model_name="usersamlsourceconnection",
name="identifier",
),
]

View File

@ -20,6 +20,7 @@ from authentik.crypto.models import CertificateKeyPair
from authentik.flows.challenge import RedirectChallenge
from authentik.flows.models import Flow
from authentik.lib.expression.evaluator import BaseEvaluator
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import (
DSA_SHA1,
@ -91,11 +92,13 @@ class SAMLSource(Source):
help_text=_("Also known as Entity ID. Defaults the Metadata URL."),
)
sso_url = models.URLField(
sso_url = models.TextField(
validators=[DomainlessURLValidator(schemes=("http", "https"))],
verbose_name=_("SSO URL"),
help_text=_("URL that the initial Login request is sent to."),
)
slo_url = models.URLField(
slo_url = models.TextField(
validators=[DomainlessURLValidator(schemes=("http", "https"))],
default=None,
blank=True,
null=True,
@ -315,8 +318,6 @@ class SAMLSourcePropertyMapping(PropertyMapping):
class UserSAMLSourceConnection(UserSourceConnection):
"""Connection to configured SAML Sources."""
identifier = models.TextField()
@property
def serializer(self) -> Serializer:
from authentik.sources.saml.api.source_connection import UserSAMLSourceConnectionSerializer

View File

@ -33,6 +33,7 @@ from authentik.flows.planner import (
)
from authentik.flows.stage import ChallengeStageView
from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_GET, SESSION_KEY_PLAN
from authentik.lib.utils.urls import is_url_absolute
from authentik.lib.views import bad_request_message
from authentik.providers.saml.utils.encoding import nice64
from authentik.sources.saml.exceptions import MissingSAMLResponse, UnsupportedNameIDFormat
@ -73,6 +74,8 @@ class InitiateView(View):
final_redirect = self.request.session.get(SESSION_KEY_GET, {}).get(
NEXT_ARG_NAME, "authentik_core:if-user"
)
if not is_url_absolute(final_redirect):
final_redirect = "authentik_core:if-user"
kwargs.update(
{
PLAN_CONTEXT_SSO: True,

File diff suppressed because one or more lines are too long

View File

@ -104,6 +104,13 @@ def send_mail(
# can't be converted to json)
message_object.attach(logo_data())
if (
message_object.to
and isinstance(message_object.to[0], str)
and "=?utf-8?" in message_object.to[0]
):
message_object.to = [message_object.to[0].split("<")[-1].replace(">", "")]
LOGGER.debug("Sending mail", to=message_object.to)
backend.send_messages([message_object])
Event.new(

View File

@ -8,7 +8,7 @@ from django.core.mail.backends.locmem import EmailBackend
from django.urls import reverse
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.core.tests.utils import create_test_admin_user, create_test_flow, create_test_user
from authentik.events.models import Event, EventAction
from authentik.flows.markers import StageMarker
from authentik.flows.models import FlowDesignation, FlowStageBinding
@ -67,6 +67,67 @@ class TestEmailStageSending(FlowTestCase):
self.assertEqual(event.context["to_email"], [f"{self.user.name} <{self.user.email}>"])
self.assertEqual(event.context["from_email"], "system@authentik.local")
def test_newlines_long_name(self):
"""Test with pending user"""
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
long_user = create_test_user()
long_user.name = "Test User\r\n Many Words\r\n"
long_user.save()
plan.context[PLAN_CONTEXT_PENDING_USER] = long_user
session = self.client.session
session[SESSION_KEY_PLAN] = plan
session.save()
Event.objects.filter(action=EventAction.EMAIL_SENT).delete()
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
with patch(
"authentik.stages.email.models.EmailStage.backend_class",
PropertyMock(return_value=EmailBackend),
):
response = self.client.post(url)
self.assertEqual(response.status_code, 200)
self.assertStageResponse(
response,
self.flow,
response_errors={
"non_field_errors": [{"string": "email-sent", "code": "email-sent"}]
},
)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, "authentik")
self.assertEqual(mail.outbox[0].to, [f"Test User Many Words <{long_user.email}>"])
def test_utf8_name(self):
"""Test with pending user"""
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
utf8_user = create_test_user()
utf8_user.name = "Cirilo ЉМНЊ el cirilico И̂ӢЙӤ "
utf8_user.email = "cyrillic@authentik.local"
utf8_user.save()
plan.context[PLAN_CONTEXT_PENDING_USER] = utf8_user
session = self.client.session
session[SESSION_KEY_PLAN] = plan
session.save()
Event.objects.filter(action=EventAction.EMAIL_SENT).delete()
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
with patch(
"authentik.stages.email.models.EmailStage.backend_class",
PropertyMock(return_value=EmailBackend),
):
response = self.client.post(url)
self.assertEqual(response.status_code, 200)
self.assertStageResponse(
response,
self.flow,
response_errors={
"non_field_errors": [{"string": "email-sent", "code": "email-sent"}]
},
)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, "authentik")
self.assertEqual(mail.outbox[0].to, [f"{utf8_user.email}"])
def test_pending_fake_user(self):
"""Test with pending (fake) user"""
self.flow.designation = FlowDesignation.RECOVERY

View File

@ -32,7 +32,14 @@ class TemplateEmailMessage(EmailMultiAlternatives):
sanitized_to = []
# Ensure that all recipients are valid
for recipient_name, recipient_email in to:
sanitized_to.append(sanitize_address((recipient_name, recipient_email), "utf-8"))
# Remove any newline characters from name and email before sanitizing
clean_name = (
recipient_name.replace("\n", " ").replace("\r", " ") if recipient_name else ""
)
clean_email = (
recipient_email.replace("\n", "").replace("\r", "") if recipient_email else ""
)
sanitized_to.append(sanitize_address((clean_name, clean_email), "utf-8"))
super().__init__(to=sanitized_to, **kwargs)
if not template_name:
return

View File

@ -142,35 +142,38 @@ class IdentificationChallengeResponse(ChallengeResponse):
raise ValidationError("Failed to authenticate.")
self.pre_user = pre_user
# Password check
if current_stage.password_stage:
password = attrs.get("password", None)
if not password:
self.stage.logger.warning("Password not set for ident+auth attempt")
try:
with start_span(
op="authentik.stages.identification.authenticate",
name="User authenticate call (combo stage)",
):
user = authenticate(
self.stage.request,
current_stage.password_stage.backends,
current_stage,
username=self.pre_user.username,
password=password,
)
if not user:
raise ValidationError("Failed to authenticate.")
self.pre_user = user
except PermissionDenied as exc:
raise ValidationError(str(exc)) from exc
# Captcha check
if captcha_stage := current_stage.captcha_stage:
captcha_token = attrs.get("captcha_token", None)
if not captcha_token:
self.stage.logger.warning("Token not set for captcha attempt")
verify_captcha_token(captcha_stage, captcha_token, client_ip)
# Password check
if not current_stage.password_stage:
# No password stage select, don't validate the password
return attrs
password = attrs.get("password", None)
if not password:
self.stage.logger.warning("Password not set for ident+auth attempt")
try:
with start_span(
op="authentik.stages.identification.authenticate",
name="User authenticate call (combo stage)",
):
user = authenticate(
self.stage.request,
current_stage.password_stage.backends,
current_stage,
username=self.pre_user.username,
password=password,
)
if not user:
raise ValidationError("Failed to authenticate.")
self.pre_user = user
except PermissionDenied as exc:
raise ValidationError(str(exc)) from exc
return attrs

View File

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://goauthentik.io/blueprints/schema.json",
"type": "object",
"title": "authentik 2025.2.2 Blueprint schema",
"title": "authentik 2025.2.3 Blueprint schema",
"required": [
"version",
"entries"
@ -6423,8 +6423,6 @@
},
"acs_url": {
"type": "string",
"format": "uri",
"maxLength": 200,
"minLength": 1,
"title": "ACS URL"
},
@ -8233,7 +8231,6 @@
},
"identifier": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"title": "Identifier"
},
@ -8733,8 +8730,6 @@
},
"sso_url": {
"type": "string",
"format": "uri",
"maxLength": 200,
"minLength": 1,
"title": "SSO URL",
"description": "URL that the initial Login request is sent to."
@ -8744,8 +8739,6 @@
"string",
"null"
],
"format": "uri",
"maxLength": 200,
"title": "SLO URL",
"description": "Optional URL if your IDP supports Single-Logout."
},

View File

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

7
go.mod
View File

@ -1,9 +1,6 @@
module goauthentik.io
go 1.23.0
toolchain go1.24.0
go 1.24.0
require (
beryju.io/ldap v0.1.0
github.com/coreos/go-oidc/v3 v3.13.0
@ -29,7 +26,7 @@ require (
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2025022.6
goauthentik.io/api/v3 v3.2025023.2
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.28.0
golang.org/x/sync v0.12.0

4
go.sum
View File

@ -299,8 +299,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
goauthentik.io/api/v3 v3.2025022.6 h1:M5M8Cd/1N7E8KLkvYYh7VdcdKz5nfzjKPFLK+YOtOVg=
goauthentik.io/api/v3 v3.2025022.6/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2025023.2 h1:4XHlnykN5jQH78liQ4cp2Jf8eigvQImIJp+A+bsq1nA=
goauthentik.io/api/v3 v3.2025023.2/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -162,13 +162,14 @@ func (c *Config) parseScheme(rawVal string) string {
if err != nil {
return rawVal
}
if u.Scheme == "env" {
switch u.Scheme {
case "env":
e, ok := os.LookupEnv(u.Host)
if ok {
return e
}
return u.RawQuery
} else if u.Scheme == "file" {
case "file":
d, err := os.ReadFile(u.Path)
if err != nil {
return u.RawQuery

View File

@ -10,7 +10,7 @@ import (
)
func TestConfigEnv(t *testing.T) {
os.Setenv("AUTHENTIK_SECRET_KEY", "bar")
assert.NoError(t, os.Setenv("AUTHENTIK_SECRET_KEY", "bar"))
cfg = nil
if err := Get().fromEnv(); err != nil {
panic(err)
@ -19,8 +19,8 @@ func TestConfigEnv(t *testing.T) {
}
func TestConfigEnv_Scheme(t *testing.T) {
os.Setenv("foo", "bar")
os.Setenv("AUTHENTIK_SECRET_KEY", "env://foo")
assert.NoError(t, os.Setenv("foo", "bar"))
assert.NoError(t, os.Setenv("AUTHENTIK_SECRET_KEY", "env://foo"))
cfg = nil
if err := Get().fromEnv(); err != nil {
panic(err)
@ -33,13 +33,15 @@ func TestConfigEnv_File(t *testing.T) {
if err != nil {
log.Fatal(err)
}
defer os.Remove(file.Name())
defer func() {
assert.NoError(t, os.Remove(file.Name()))
}()
_, err = file.Write([]byte("bar"))
if err != nil {
panic(err)
}
os.Setenv("AUTHENTIK_SECRET_KEY", fmt.Sprintf("file://%s", file.Name()))
assert.NoError(t, os.Setenv("AUTHENTIK_SECRET_KEY", fmt.Sprintf("file://%s", file.Name())))
cfg = nil
if err := Get().fromEnv(); err != nil {
panic(err)

View File

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

View File

@ -1,5 +0,0 @@
//go:build requirefips
package backend
var FipsEnabled = true

View File

@ -1,5 +0,0 @@
//go:build !requirefips
package backend
var FipsEnabled = false

View File

@ -35,7 +35,7 @@ func EnableDebugServer() {
if err != nil {
return nil
}
_, err = w.Write([]byte(fmt.Sprintf("<a href='%[1]s'>%[1]s</a><br>", tpl)))
_, err = fmt.Fprintf(w, "<a href='%[1]s'>%[1]s</a><br>", tpl)
if err != nil {
l.WithError(err).Warning("failed to write index")
return nil

View File

@ -44,10 +44,11 @@ func New(healthcheck func() bool) *GoUnicorn {
signal.Notify(c, syscall.SIGHUP, syscall.SIGUSR2)
go func() {
for sig := range c {
if sig == syscall.SIGHUP {
switch sig {
case syscall.SIGHUP:
g.log.Info("SIGHUP received, forwarding to gunicorn")
g.Reload()
} else if sig == syscall.SIGUSR2 {
case syscall.SIGUSR2:
g.log.Info("SIGUSR2 received, restarting gunicorn")
g.Restart()
}

View File

@ -2,6 +2,7 @@ package ak
import (
"context"
"crypto/fips140"
"fmt"
"math/rand"
"net/http"
@ -203,7 +204,7 @@ func (a *APIController) getWebsocketPingArgs() map[string]interface{} {
"golangVersion": runtime.Version(),
"opensslEnabled": cryptobackend.OpensslEnabled,
"opensslVersion": cryptobackend.OpensslVersion(),
"fipsEnabled": cryptobackend.FipsEnabled,
"fipsEnabled": fips140.Enabled(),
}
hostname, err := os.Hostname()
if err == nil {

View File

@ -35,13 +35,19 @@ func Paginator[Tobj any, Treq any, Tres PaginatorResponse[Tobj]](
req PaginatorRequest[Treq, Tres],
opts PaginatorOptions,
) ([]Tobj, error) {
if opts.Logger == nil {
opts.Logger = log.NewEntry(log.StandardLogger())
}
var bfreq, cfreq interface{}
fetchOffset := func(page int32) (Tres, error) {
bfreq = req.Page(page)
cfreq = bfreq.(PaginatorRequest[Treq, Tres]).PageSize(int32(opts.PageSize))
res, _, err := cfreq.(PaginatorRequest[Treq, Tres]).Execute()
res, hres, err := cfreq.(PaginatorRequest[Treq, Tres]).Execute()
if err != nil {
opts.Logger.WithError(err).WithField("page", page).Warning("failed to fetch page")
if hres != nil && hres.StatusCode >= 400 && hres.StatusCode < 500 {
return res, err
}
}
return res, err
}
@ -51,6 +57,9 @@ func Paginator[Tobj any, Treq any, Tres PaginatorResponse[Tobj]](
for {
apiObjects, err := fetchOffset(page)
if err != nil {
if page == 1 {
return objects, err
}
errs = append(errs, err)
continue
}

View File

@ -1,5 +1,64 @@
package ak
import (
"errors"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"goauthentik.io/api/v3"
)
type fakeAPIType struct{}
type fakeAPIResponse struct {
results []fakeAPIType
pagination api.Pagination
}
func (fapi *fakeAPIResponse) GetResults() []fakeAPIType { return fapi.results }
func (fapi *fakeAPIResponse) GetPagination() api.Pagination { return fapi.pagination }
type fakeAPIRequest struct {
res *fakeAPIResponse
http *http.Response
err error
}
func (fapi *fakeAPIRequest) Page(page int32) *fakeAPIRequest { return fapi }
func (fapi *fakeAPIRequest) PageSize(size int32) *fakeAPIRequest { return fapi }
func (fapi *fakeAPIRequest) Execute() (*fakeAPIResponse, *http.Response, error) {
return fapi.res, fapi.http, fapi.err
}
func Test_Simple(t *testing.T) {
req := &fakeAPIRequest{
res: &fakeAPIResponse{
results: []fakeAPIType{
{},
},
pagination: api.Pagination{
TotalPages: 1,
},
},
}
res, err := Paginator(req, PaginatorOptions{})
assert.NoError(t, err)
assert.Len(t, res, 1)
}
func Test_BadRequest(t *testing.T) {
req := &fakeAPIRequest{
http: &http.Response{
StatusCode: 400,
},
err: errors.New("foo"),
}
res, err := Paginator(req, PaginatorOptions{})
assert.Error(t, err)
assert.Equal(t, []fakeAPIType{}, res)
}
// func Test_PaginatorCompile(t *testing.T) {
// req := api.ApiCoreUsersListRequest{}
// Paginator(req, PaginatorOptions{

View File

@ -148,7 +148,8 @@ func (ac *APIController) startWSHandler() {
"outpost_type": ac.Server.Type(),
"uuid": ac.instanceUUID.String(),
}).Set(1)
if wsMsg.Instruction == WebsocketInstructionTriggerUpdate {
switch wsMsg.Instruction {
case WebsocketInstructionTriggerUpdate:
time.Sleep(ac.reloadOffset)
logger.Debug("Got update trigger...")
err := ac.OnRefresh()
@ -163,7 +164,7 @@ func (ac *APIController) startWSHandler() {
"build": constants.BUILD(""),
}).SetToCurrentTime()
}
} else if wsMsg.Instruction == WebsocketInstructionProviderSpecific {
case WebsocketInstructionProviderSpecific:
for _, h := range ac.wsHandlers {
h(context.Background(), wsMsg.Args)
}

View File

@ -66,7 +66,12 @@ func (ls *LDAPServer) StartLDAPServer() error {
return err
}
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
defer func() {
err := proxyListener.Close()
if err != nil {
ls.log.WithError(err).Warning("failed to close proxy listener")
}
}()
ls.log.WithField("listen", listen).Info("Starting LDAP server")
err = ls.s.Serve(proxyListener)

View File

@ -49,7 +49,12 @@ func (ls *LDAPServer) StartLDAPTLSServer() error {
}
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
defer func() {
err := proxyListener.Close()
if err != nil {
ls.log.WithError(err).Warning("failed to close proxy listener")
}
}()
tln := tls.NewListener(proxyListener, tlsConfig)

View File

@ -98,7 +98,7 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
entries := make([]*ldap.Entry, 0)
scope := req.SearchRequest.Scope
scope := req.Scope
needUsers, needGroups := ms.si.GetNeededObjects(scope, req.BaseDN, req.FilterObjectClass)
if scope >= 0 && strings.EqualFold(req.BaseDN, baseDN) {

View File

@ -56,7 +56,7 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string, embedded bo
if !embedded && hostBrowser == "" {
return ep
}
var newHost *url.URL = aku
var newHost = aku
var newBrowserHost *url.URL
if embedded {
if authentikHost == "" {

View File

@ -130,7 +130,12 @@ func (ps *ProxyServer) ServeHTTP() {
return
}
proxyListener := &proxyproto.Listener{Listener: listener, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
defer func() {
err := proxyListener.Close()
if err != nil {
ps.log.WithError(err).Warning("failed to close proxy listener")
}
}()
ps.log.WithField("listen", listenAddress).Info("Starting HTTP server")
ps.serve(proxyListener)
@ -149,7 +154,12 @@ func (ps *ProxyServer) ServeHTTPS() {
return
}
proxyListener := &proxyproto.Listener{Listener: web.TCPKeepAliveListener{TCPListener: ln.(*net.TCPListener)}, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
defer func() {
err := proxyListener.Close()
if err != nil {
ps.log.WithError(err).Warning("failed to close proxy listener")
}
}()
tlsListener := tls.NewListener(proxyListener, tlsConfig)
ps.log.WithField("listen", listenAddress).Info("Starting HTTPS server")

View File

@ -72,11 +72,13 @@ func (s *RedisStore) New(r *http.Request, name string) (*sessions.Session, error
session.ID = c.Value
err = s.load(r.Context(), session)
if err == nil {
session.IsNew = false
} else if err == redis.Nil {
err = nil // no data stored
if err != nil {
if errors.Is(err, redis.Nil) {
return session, nil
}
return session, err
}
session.IsNew = false
return session, err
}

View File

@ -156,7 +156,12 @@ func (ws *WebServer) listenPlain() {
return
}
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
defer func() {
err := proxyListener.Close()
if err != nil {
ws.log.WithError(err).Warning("failed to close proxy listener")
}
}()
ws.log.WithField("listen", config.Get().Listen.HTTP).Info("Starting HTTP server")
ws.serve(proxyListener)

View File

@ -46,7 +46,12 @@ func (ws *WebServer) listenTLS() {
return
}
proxyListener := &proxyproto.Listener{Listener: web.TCPKeepAliveListener{TCPListener: ln.(*net.TCPListener)}, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
defer func() {
err := proxyListener.Close()
if err != nil {
ws.log.WithError(err).Warning("failed to close proxy listener")
}
}()
tlsListener := tls.NewListener(proxyListener, tlsConfig)
ws.log.WithField("listen", config.Get().Listen.HTTPS).Info("Starting HTTPS server")

View File

@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-bookworm AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
@ -27,7 +27,7 @@ COPY . .
RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
--mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/ldap ./cmd/ldap
# Stage 2: Run

View File

@ -9,7 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
"aws-cdk": "^2.1005.0",
"aws-cdk": "^2.1007.0",
"cross-env": "^7.0.3"
},
"engines": {
@ -17,9 +17,9 @@
}
},
"node_modules/aws-cdk": {
"version": "2.1005.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1005.0.tgz",
"integrity": "sha512-4ejfGGrGCEl0pg1xcqkxK0lpBEZqNI48wtrXhk6dYOFYPYMZtqn1kdla29ONN+eO2unewkNF4nLP1lPYhlf9Pg==",
"version": "2.1007.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1007.0.tgz",
"integrity": "sha512-/UOYOTGWUm+pP9qxg03tID5tL6euC+pb+xo0RBue+xhnUWwj/Bbsw6DbqbpOPMrNzTUxmM723/uMEQmM6S26dw==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@ -10,7 +10,7 @@
"node": ">=20"
},
"devDependencies": {
"aws-cdk": "^2.1005.0",
"aws-cdk": "^2.1007.0",
"cross-env": "^7.0.3"
}
}

View File

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

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-22 00:10+0000\n"
"POT-Creation-Date: 2025-03-31 00:10+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -1220,6 +1220,20 @@ msgstr ""
msgid "Reputation Scores"
msgstr ""
#: authentik/policies/templates/policies/buffer.html
msgid "Waiting for authentication..."
msgstr ""
#: authentik/policies/templates/policies/buffer.html
msgid ""
"You're already authenticating in another tab. This page will refresh once "
"authentication is completed."
msgstr ""
#: authentik/policies/templates/policies/buffer.html
msgid "Authenticate in this tab"
msgstr ""
#: authentik/policies/templates/policies/denied.html
msgid "Permission denied"
msgstr ""

View File

@ -10,8 +10,8 @@
# Manuel Viens, 2023
# Mordecai, 2023
# nerdinator <florian.dupret@gmail.com>, 2024
# Tina, 2024
# Charles Leclerc, 2025
# Tina, 2025
# Marc Schmitt, 2025
#
#, fuzzy
@ -19,7 +19,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-22 00:10+0000\n"
"POT-Creation-Date: 2025-03-31 00:10+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Marc Schmitt, 2025\n"
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
@ -1347,6 +1347,22 @@ msgstr "Score de Réputation"
msgid "Reputation Scores"
msgstr "Scores de Réputation"
#: authentik/policies/templates/policies/buffer.html
msgid "Waiting for authentication..."
msgstr "En attente de l'authentification..."
#: authentik/policies/templates/policies/buffer.html
msgid ""
"You're already authenticating in another tab. This page will refresh once "
"authentication is completed."
msgstr ""
"Vous êtes déjà en cours d'authentification dans un autre onglet. Cette page "
"se rafraîchira lorsque l'authentification sera terminée."
#: authentik/policies/templates/policies/buffer.html
msgid "Authenticate in this tab"
msgstr "S'authentifier dans cet onglet"
#: authentik/policies/templates/policies/denied.html
msgid "Permission denied"
msgstr "Permission refusée"

Binary file not shown.

View File

@ -14,7 +14,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-22 00:10+0000\n"
"POT-Creation-Date: 2025-03-31 00:10+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: deluxghost, 2025\n"
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
@ -1234,6 +1234,20 @@ msgstr "信誉分数"
msgid "Reputation Scores"
msgstr "信誉分数"
#: authentik/policies/templates/policies/buffer.html
msgid "Waiting for authentication..."
msgstr "正在等待身份验证…"
#: authentik/policies/templates/policies/buffer.html
msgid ""
"You're already authenticating in another tab. This page will refresh once "
"authentication is completed."
msgstr "您正在另一个标签页中验证身份。身份验证完成后,此页面会刷新。"
#: authentik/policies/templates/policies/buffer.html
msgid "Authenticate in this tab"
msgstr "在此标签页中验证身份"
#: authentik/policies/templates/policies/denied.html
msgid "Permission denied"
msgstr "权限被拒绝"

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "@goauthentik/authentik",
"version": "2025.2.1",
"version": "2025.2.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@goauthentik/authentik",
"version": "2025.2.1"
"version": "2025.2.3"
}
}
}

View File

@ -1,5 +1,5 @@
{
"name": "@goauthentik/authentik",
"version": "2025.2.2",
"version": "2025.2.3",
"private": true
}

View File

@ -17,7 +17,7 @@ COPY web .
RUN npm run build-proxy
# Stage 2: Build
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-bookworm AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
@ -43,7 +43,7 @@ COPY . .
RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
--mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/proxy ./cmd/proxy
# Stage 3: Run

View File

@ -1,6 +1,6 @@
[project]
name = "authentik"
version = "2025.2.2"
version = "2025.2.3"
description = ""
authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }]
requires-python = "==3.12.*"
@ -52,7 +52,7 @@ dependencies = [
"pydantic-scim",
"pyjwt",
"pyrad",
"python-kadmin-rs ==0.5.3",
"python-kadmin-rs ==0.6.0",
"pyyaml",
"requests-oauthlib",
"scim2-filter-parser",
@ -103,7 +103,7 @@ dev = [
[tool.uv.sources]
django-tenants = { git = "https://github.com/rissson/django-tenants.git", branch = "authentik-fixes" }
opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf" }
opencontainers = { git = "https://github.com/BeryJu/oci-python", rev = "c791b19056769cd67957322806809ab70f5bead8" }
[project.scripts]
ak = "lifecycle.ak:main"

View File

@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-bookworm AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
@ -27,7 +27,7 @@ COPY . .
RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
--mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/rac ./cmd/rac
# Stage 2: Run

View File

@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build
FROM --platform=${BUILDPLATFORM} mcr.microsoft.com/oss/go/microsoft/golang:1.23-fips-bookworm AS builder
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
@ -27,7 +27,7 @@ COPY . .
RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
--mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
CGO_ENABLED=1 GOEXPERIMENT="systemcrypto" GOFLAGS="-tags=requirefips" GOARM="${TARGETVARIANT#v}" \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/radius ./cmd/radius
# Stage 2: Run

File diff suppressed because it is too large Load Diff

View File

@ -5,45 +5,85 @@ from yaml import safe_dump
from authentik.lib.generators import generate_id
with open("local.env.yml", "w", encoding="utf-8") as _config:
safe_dump(
{
"debug": True,
"log_level": "debug",
"secret_key": generate_id(),
"postgresql": {
"user": "postgres",
},
"outposts": {
"container_image_base": "ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s",
"disable_embedded_outpost": False,
},
"blueprints_dir": "./blueprints",
"cert_discovery_dir": "./certs",
"events": {
"processors": {
"geoip": "tests/GeoLite2-City-Test.mmdb",
"asn": "tests/GeoLite2-ASN-Test.mmdb",
}
},
"storage": {
"media": {
"backend": "file",
"s3": {
"endpoint": "http://localhost:8020",
"access_key": "accessKey1",
"secret_key": "secretKey1",
"bucket_name": "authentik-media",
"custom_domain": "localhost:8020/authentik-media",
"secure_urls": False,
},
def generate_local_config():
"""Generate a local development configuration"""
# TODO: This should be generated and validated against a schema, such as Pydantic.
return {
"debug": True,
"log_level": "debug",
"secret_key": generate_id(),
"postgresql": {
"user": "postgres",
},
"outposts": {
"container_image_base": "ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s",
"disable_embedded_outpost": False,
},
"blueprints_dir": "./blueprints",
"cert_discovery_dir": "./certs",
"events": {
"processors": {
"geoip": "tests/GeoLite2-City-Test.mmdb",
"asn": "tests/GeoLite2-ASN-Test.mmdb",
}
},
"storage": {
"media": {
"backend": "file",
"s3": {
"endpoint": "http://localhost:8020",
"access_key": "accessKey1",
"secret_key": "secretKey1",
"bucket_name": "authentik-media",
"custom_domain": "localhost:8020/authentik-media",
"secure_urls": False,
},
},
"tenants": {
"enabled": False,
"api_key": generate_id(),
},
},
_config,
default_flow_style=False,
"tenants": {
"enabled": False,
"api_key": generate_id(),
},
}
if __name__ == "__main__":
config_file_name = "local.env.yml"
with open(config_file_name, "w", encoding="utf-8") as _config:
_config.write(
"""
# Local authentik configuration overrides
#
# https://docs.goauthentik.io/docs/install-config/configuration/
#
# To regenerate this file, run the following command from the repository root:
#
# ```shell
# make gen-dev-config
# ```
"""
)
safe_dump(
generate_local_config(),
_config,
default_flow_style=False,
)
print(
f"""
---
Generated configuration file: {config_file_name}
For more information on how to use this configuration, see:
https://docs.goauthentik.io/docs/install-config/configuration/
---
"""
)

View File

@ -410,3 +410,77 @@ class TestProviderOAuth2OAuth(SeleniumTestCase):
self.driver.find_element(By.CSS_SELECTOR, "header > h1").text,
"Permission denied",
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint("default/flow-default-provider-authorization-implicit-consent.yaml")
@apply_blueprint("system/providers-oauth2.yaml")
@reconcile_app("authentik_crypto")
def test_authorization_consent_implied_parallel(self):
"""test OpenID Provider flow (default authorization flow with implied consent)"""
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider = OAuth2Provider.objects.create(
name=generate_id(),
client_type=ClientTypes.CONFIDENTIAL,
client_id=self.client_id,
client_secret=self.client_secret,
signing_key=create_test_cert(),
redirect_uris=[
RedirectURI(
RedirectURIMatchingMode.STRICT, "http://localhost:3000/login/generic_oauth"
)
],
authorization_flow=authorization_flow,
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
scope_name__in=[
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
SCOPE_OFFLINE_ACCESS,
]
)
)
Application.objects.create(
name=generate_id(),
slug=self.app_slug,
provider=provider,
)
self.driver.get(self.live_server_url)
login_window = self.driver.current_window_handle
self.driver.switch_to.new_window("tab")
grafana_window = self.driver.current_window_handle
self.driver.get("http://localhost:3000")
self.driver.find_element(By.CLASS_NAME, "btn-service--oauth").click()
self.driver.switch_to.window(login_window)
self.login()
self.driver.switch_to.window(grafana_window)
self.wait_for_url("http://localhost:3000/?orgId=1")
self.driver.get("http://localhost:3000/profile")
self.assertEqual(
self.driver.find_element(By.CLASS_NAME, "page-header__title").text,
self.user.name,
)
self.assertEqual(
self.driver.find_element(By.CSS_SELECTOR, "input[name=name]").get_attribute("value"),
self.user.name,
)
self.assertEqual(
self.driver.find_element(By.CSS_SELECTOR, "input[name=email]").get_attribute("value"),
self.user.email,
)
self.assertEqual(
self.driver.find_element(By.CSS_SELECTOR, "input[name=login]").get_attribute("value"),
self.user.email,
)

View File

@ -20,7 +20,7 @@ from tests.e2e.utils import SeleniumTestCase, retry
class TestProviderSAML(SeleniumTestCase):
"""test SAML Provider flow"""
def setup_client(self, provider: SAMLProvider, force_post: bool = False):
def setup_client(self, provider: SAMLProvider, force_post: bool = False, **kwargs):
"""Setup client saml-sp container which we test SAML against"""
metadata_url = (
self.url(
@ -40,6 +40,7 @@ class TestProviderSAML(SeleniumTestCase):
"SP_ENTITY_ID": provider.issuer,
"SP_SSO_BINDING": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
"SP_METADATA_URL": metadata_url,
**kwargs,
},
)
@ -111,6 +112,74 @@ class TestProviderSAML(SeleniumTestCase):
[self.user.email],
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-implicit-consent.yaml",
)
@apply_blueprint(
"system/providers-saml.yaml",
)
@reconcile_app("authentik_crypto")
def test_sp_initiated_implicit_post(self):
"""test SAML Provider flow SP-initiated flow (implicit consent)"""
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider: SAMLProvider = SAMLProvider.objects.create(
name="saml-test",
acs_url="http://localhost:9009/saml/acs",
audience="authentik-e2e",
issuer="authentik-e2e",
sp_binding=SAMLBindings.POST,
authorization_flow=authorization_flow,
signing_kp=create_test_cert(),
)
provider.property_mappings.set(SAMLPropertyMapping.objects.all())
provider.save()
Application.objects.create(
name="SAML",
slug="authentik-saml",
provider=provider,
)
self.setup_client(provider, True)
self.driver.get("http://localhost:9009")
self.login()
self.wait_for_url("http://localhost:9009/")
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],
[self.user.name],
)
self.assertEqual(
body["attr"][
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/username"],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/uid"],
[str(self.user.pk)],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
[self.user.email],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"],
[self.user.email],
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
@ -450,3 +519,81 @@ class TestProviderSAML(SeleniumTestCase):
lambda driver: driver.current_url.startswith(should_url),
f"URL {self.driver.current_url} doesn't match expected URL {should_url}",
)
@retry()
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-implicit-consent.yaml",
)
@apply_blueprint(
"system/providers-saml.yaml",
)
@reconcile_app("authentik_crypto")
def test_sp_initiated_implicit_post_buffer(self):
"""test SAML Provider flow SP-initiated flow (implicit consent)"""
# Bootstrap all needed objects
authorization_flow = Flow.objects.get(
slug="default-provider-authorization-implicit-consent"
)
provider: SAMLProvider = SAMLProvider.objects.create(
name="saml-test",
acs_url=f"http://{self.host}:9009/saml/acs",
audience="authentik-e2e",
issuer="authentik-e2e",
sp_binding=SAMLBindings.POST,
authorization_flow=authorization_flow,
signing_kp=create_test_cert(),
)
provider.property_mappings.set(SAMLPropertyMapping.objects.all())
provider.save()
Application.objects.create(
name="SAML",
slug="authentik-saml",
provider=provider,
)
self.setup_client(provider, True, SP_ROOT_URL=f"http://{self.host}:9009")
self.driver.get(self.live_server_url)
login_window = self.driver.current_window_handle
self.driver.switch_to.new_window("tab")
client_window = self.driver.current_window_handle
# We need to access the SP on the same host as the IdP for SameSite cookies
self.driver.get(f"http://{self.host}:9009")
self.driver.switch_to.window(login_window)
self.login()
self.driver.switch_to.window(client_window)
self.wait_for_url(f"http://{self.host}:9009/")
body = loads(self.driver.find_element(By.CSS_SELECTOR, "pre").text)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"],
[self.user.name],
)
self.assertEqual(
body["attr"][
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"
],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/username"],
[self.user.username],
)
self.assertEqual(
body["attr"]["http://schemas.goauthentik.io/2021/02/saml/uid"],
[str(self.user.pk)],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
[self.user.email],
)
self.assertEqual(
body["attr"]["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"],
[self.user.email],
)

31
uv.lock generated
View File

@ -162,7 +162,7 @@ wheels = [
[[package]]
name = "authentik"
version = "2025.2.2"
version = "2025.2.3"
source = { editable = "." }
dependencies = [
{ name = "argon2-cffi" },
@ -302,7 +302,7 @@ requires-dist = [
{ name = "ldap3" },
{ name = "lxml" },
{ name = "msgraph-sdk" },
{ name = "opencontainers", git = "https://github.com/vsoch/oci-python?rev=20d69d9cc50a0fef31605b46f06da0c94f1ec3cf" },
{ name = "opencontainers", git = "https://github.com/BeryJu/oci-python?rev=c791b19056769cd67957322806809ab70f5bead8" },
{ name = "packaging" },
{ name = "paramiko" },
{ name = "psycopg", extras = ["c"] },
@ -310,7 +310,7 @@ requires-dist = [
{ name = "pydantic-scim" },
{ name = "pyjwt" },
{ name = "pyrad" },
{ name = "python-kadmin-rs", specifier = "==0.5.3" },
{ name = "python-kadmin-rs", specifier = "==0.6.0" },
{ name = "pyyaml" },
{ name = "requests-oauthlib" },
{ name = "scim2-filter-parser" },
@ -1216,9 +1216,12 @@ wheels = [
[[package]]
name = "durationpy"
version = "0.7"
version = "0.9"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8b/b8/074abdcc251bec87da6c5b19b88d7898ec7996c6780d40c6ac5000d3dd47/durationpy-0.7.tar.gz", hash = "sha256:8447c43df4f1a0b434e70c15a38d77f5c9bd17284bfc1ff1d430f233d5083732", size = 3168 }
sdist = { url = "https://files.pythonhosted.org/packages/31/e9/f49c4e7fccb77fa5c43c2480e09a857a78b41e7331a75e128ed5df45c56b/durationpy-0.9.tar.gz", hash = "sha256:fd3feb0a69a0057d582ef643c355c40d2fa1c942191f914d12203b1a01ac722a", size = 3186 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/4c/a3/ac312faeceffd2d8f86bc6dcb5c401188ba5a01bc88e69bed97578a0dfcd/durationpy-0.9-py3-none-any.whl", hash = "sha256:e65359a7af5cedad07fb77a2dd3f390f8eb0b74cb845589fa6c057086834dd38", size = 3461 },
]
[[package]]
name = "email-validator"
@ -2075,7 +2078,7 @@ wheels = [
[[package]]
name = "opencontainers"
version = "0.0.14"
source = { git = "https://github.com/vsoch/oci-python?rev=20d69d9cc50a0fef31605b46f06da0c94f1ec3cf#20d69d9cc50a0fef31605b46f06da0c94f1ec3cf" }
source = { git = "https://github.com/BeryJu/oci-python?rev=c791b19056769cd67957322806809ab70f5bead8#c791b19056769cd67957322806809ab70f5bead8" }
[[package]]
name = "opentelemetry-api"
@ -2596,16 +2599,16 @@ wheels = [
[[package]]
name = "python-kadmin-rs"
version = "0.5.3"
version = "0.6.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e7/95/07b708623f13874ad86dc603f2fe36e980a5f5890edea87286d13f2b0b81/python_kadmin_rs-0.5.3.tar.gz", hash = "sha256:4f46fd854af622896136c3ac4fc5e6a37d37bfffb5b2023e438001ffa62ab7e3", size = 89865 }
sdist = { url = "https://files.pythonhosted.org/packages/b9/ac/df3a093b1e186cd68a6f38778fac025450e5c5e9859c4790e00c2ed0ff62/python_kadmin_rs-0.6.0.tar.gz", hash = "sha256:dadd3d4ef542b829c1dcde97360a6b6a10700a4b5686f12f24b10f6cf5ca6e6c", size = 89318 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/96/46/1bbfd7d6819851c300b991d7340452fba8edc3d2fe68b33271279eb74887/python_kadmin_rs-0.5.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:54b5e1c2e22da0d16c1418eb2b46da8baa11699a5db8db2afc52dbfd02d14958", size = 1416637 },
{ url = "https://files.pythonhosted.org/packages/be/34/fd7f5c324aaf1b9ad3dd5050ac2059230618c29adc452d676d2af4d5ae79/python_kadmin_rs-0.5.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:d1dc7ad1f07bbfd09baeb1fb0dfc45c87776ed717052081e63d3bdba340a250e", size = 1503018 },
{ url = "https://files.pythonhosted.org/packages/e5/29/3931502534e07806cf7c70631374452cfcbafa44e75c5403416372b701c7/python_kadmin_rs-0.5.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:86404a1060ece916088ae4a0d188e9309fd46e0b3003779ee7a8dc7493176779", size = 3268475 },
{ url = "https://files.pythonhosted.org/packages/ba/5d/f18ca5df97a4241711555987eb308c6e6c5505883514ac7f18d7aebd52f2/python_kadmin_rs-0.5.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:7aa62a618af2b2112f708fd44f9cc3cf25e28f1562ea66a2036fb3cd1a47e649", size = 3371699 },
{ url = "https://files.pythonhosted.org/packages/91/d3/42c4d57414cfdf4e4ff528dd8e72428908ee67aeeae6a63fe2f5dbcd04bc/python_kadmin_rs-0.5.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80813af82dfbcc6a90505183c822eab11de77b6703e5691e37ed77d292224dd9", size = 1584049 },
{ url = "https://files.pythonhosted.org/packages/9a/65/705f179cf4bf4d16fc1daeac0810def57da2f4514a5b79ca60f24d7efb90/python_kadmin_rs-0.5.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6799a0faddb4ccf200acfa87da38e5fa2af54970d066b2c876e752bbf794b204", size = 1590360 },
{ url = "https://files.pythonhosted.org/packages/12/6d/59fefe1c4c11177c4feb8ad65dd6a265e9cc5fc83682a928acdccb170000/python_kadmin_rs-0.6.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:0069fbd656096b98853f8cdc6d5e24f754829fa9cb4a716dac33777f0305d37a", size = 1418187 },
{ url = "https://files.pythonhosted.org/packages/a6/12/c00a71c0fc17f5d208b4bb5e570002d74f0bc414e35194537d46ea32080f/python_kadmin_rs-0.6.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:cfcfe9982e969705dee62f2b97c8d7c249b55b2a97e2bc981408061ea7182b96", size = 1501759 },
{ url = "https://files.pythonhosted.org/packages/a0/b5/06cf809cfaaeded84e6634bf07116264ab4f8fd5eccca7523114e197f424/python_kadmin_rs-0.6.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:920df382e7a554d2f6fd160436a64adf1251f3262ec16bccd6d3b9f7e039d5fa", size = 3262691 },
{ url = "https://files.pythonhosted.org/packages/e6/72/99884dbc1856440a548ea8bf2ff1232c7f2823b6cb1a62bbb4d902a34609/python_kadmin_rs-0.6.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:94509b7470b18105c27fcaf5e6af894644614a687af74a43499735c405217e01", size = 3382996 },
{ url = "https://files.pythonhosted.org/packages/bd/4f/5d7e5be27cd466affc00fcab71fb94ea0420aee95306188988faf270b129/python_kadmin_rs-0.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f89e7fbcb7220a42c143a1b008685f98ca0a72ecc55c30f85b72c9d1ba9c3b9", size = 1572007 },
{ url = "https://files.pythonhosted.org/packages/a6/1e/fdd7d6cd2ebc4cc654112329311380d1c03c681511973e32ae6ab90f261c/python_kadmin_rs-0.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:775ce07ffd47a50ba27c8d74c20baacb56acfc7a8c56a8b02f2207ed9829156e", size = 1618897 },
]
[[package]]

206
web/authentication/index.js Normal file
View File

@ -0,0 +1,206 @@
/**
* @file WebAuthn utilities.
*/
import { fromByteArray } from "base64-js";
//@ts-check
//#region Type Definitions
/**
* @typedef {object} Assertion
* @property {string} id
* @property {string} rawId
* @property {string} type
* @property {string} registrationClientExtensions
* @property {object} response
* @property {string} response.clientDataJSON
* @property {string} response.attestationObject
*/
/**
* @typedef {object} AuthAssertion
* @property {string} id
* @property {string} rawId
* @property {string} type
* @property {string} assertionClientExtensions
* @property {object} response
* @property {string} response.clientDataJSON
* @property {string} response.authenticatorData
* @property {string} response.signature
* @property {string | null} response.userHandle
*/
//#endregion
//#region Encoding/Decoding
/**
* Encodes a byte array into a URL-safe base64 string.
*
* @param {Uint8Array} buffer
* @returns {string}
*/
export function encodeBase64(buffer) {
return fromByteArray(buffer).replace(/\+/g, "-").replace(/\//g, "_").replace(/[=]/g, "");
}
/**
* Encodes a byte array into a base64 string without URL-safe encoding, i.e., with padding.
* @param {Uint8Array} buffer
* @returns {string}
*/
export function encodeBase64Raw(buffer) {
return fromByteArray(buffer).replace(/\+/g, "-").replace(/\//g, "_");
}
/**
* Decodes a base64 string into a byte array.
*
* @param {string} input
* @returns {Uint8Array}
*/
export function decodeBase64(input) {
return Uint8Array.from(atob(input.replace(/_/g, "/").replace(/-/g, "+")), (c) =>
c.charCodeAt(0),
);
}
//#endregion
//#region Utility Functions
/**
* Checks if the browser supports WebAuthn.
*
* @returns {boolean}
*/
export function isWebAuthnSupported() {
if ("credentials" in navigator) return true;
if (window.location.protocol === "http:" && window.location.hostname !== "localhost") {
console.warn("WebAuthn requires this page to be accessed via HTTPS.");
return false;
}
console.warn("WebAuthn not supported by browser.");
return false;
}
/**
* Asserts that the browser supports WebAuthn and that we're in a secure context.
*
* @throws {Error} If WebAuthn is not supported.
*/
export function assertWebAuthnSupport() {
// Is the navigator exposing the credentials API?
if ("credentials" in navigator) return;
if (window.location.protocol === "http:" && window.location.hostname !== "localhost") {
throw new Error("WebAuthn requires this page to be accessed via HTTPS.");
}
throw new Error("WebAuthn not supported by browser.");
}
/**
* Transforms items in the credentialCreateOptions generated on the server
* into byte arrays expected by the navigator.credentials.create() call
* @param {PublicKeyCredentialCreationOptions} credentialCreateOptions
* @param {string} userID
* @returns {PublicKeyCredentialCreationOptions}
*/
export function transformCredentialCreateOptions(credentialCreateOptions, userID) {
const user = credentialCreateOptions.user;
// Because json can't contain raw bytes, the server base64-encodes the User ID
// So to get the base64 encoded byte array, we first need to convert it to a regular
// string, then a byte array, re-encode it and wrap that in an array.
const stringId = decodeURIComponent(window.atob(userID));
user.id = decodeBase64(encodeBase64(decodeBase64(stringId)));
const challenge = decodeBase64(credentialCreateOptions.challenge.toString());
return {
...credentialCreateOptions,
challenge,
user,
};
}
/**
* Transforms the binary data in the credential into base64 strings
* for posting to the server.
*
* @param {PublicKeyCredential} newAssertion
* @returns {Assertion}
*/
export function transformNewAssertionForServer(newAssertion) {
const response = /** @type {AuthenticatorAttestationResponse} */ (newAssertion.response);
const attObj = new Uint8Array(response.attestationObject);
const clientDataJSON = new Uint8Array(newAssertion.response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const registrationClientExtensions = newAssertion.getClientExtensionResults();
return {
id: newAssertion.id,
rawId: encodeBase64(rawId),
type: newAssertion.type,
registrationClientExtensions: JSON.stringify(registrationClientExtensions),
response: {
clientDataJSON: encodeBase64(clientDataJSON),
attestationObject: encodeBase64(attObj),
},
};
}
/**
* Transforms the items in the credentialRequestOptions generated on the server
*
* @param {PublicKeyCredentialRequestOptions} credentialRequestOptions
* @returns {PublicKeyCredentialRequestOptions}
*/
export function transformCredentialRequestOptions(credentialRequestOptions) {
const challenge = decodeBase64(credentialRequestOptions.challenge.toString());
const allowCredentials = (credentialRequestOptions.allowCredentials || []).map(
(credentialDescriptor) => {
const id = decodeBase64(credentialDescriptor.id.toString());
return Object.assign({}, credentialDescriptor, { id });
},
);
return Object.assign({}, credentialRequestOptions, {
challenge,
allowCredentials,
});
}
/**
* Encodes the binary data in the assertion into strings for posting to the server.
* @param {PublicKeyCredential} newAssertion
* @returns {AuthAssertion}
*/
export function transformAssertionForServer(newAssertion) {
const response = /** @type {AuthenticatorAssertionResponse} */ (newAssertion.response);
const authData = new Uint8Array(response.authenticatorData);
const clientDataJSON = new Uint8Array(response.clientDataJSON);
const rawId = new Uint8Array(newAssertion.rawId);
const sig = new Uint8Array(response.signature);
const assertionClientExtensions = newAssertion.getClientExtensionResults();
return {
id: newAssertion.id,
rawId: encodeBase64(rawId),
type: newAssertion.type,
assertionClientExtensions: JSON.stringify(assertionClientExtensions),
response: {
clientDataJSON: encodeBase64Raw(clientDataJSON),
signature: encodeBase64Raw(sig),
authenticatorData: encodeBase64Raw(authData),
userHandle: null,
},
};
}

View File

@ -48,6 +48,9 @@ export default [
"lit/no-template-bind": "error",
"no-unused-vars": "off",
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
// TODO: TypeScript already handles this.
// Remove after project-wide ESLint config is properly set up.
"no-undef": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
@ -71,8 +74,18 @@ export default [
...globals.node,
},
},
files: ["scripts/**/*.mjs", "*.ts", "*.mjs"],
files: [
// TODO:Remove after project-wide ESLint config is properly set up.
"scripts/**/*.mjs",
"authentication/**/*.js",
"sfe/**/*.js",
"*.ts",
"*.mjs",
],
rules: {
"no-undef": "off",
// TODO: TypeScript already handles this.
// Remove after project-wide ESLint config is properly set up.
"no-unused-vars": "off",
// We WANT our scripts to output to the console!
"no-console": "off",

2028
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
"@floating-ui/dom": "^1.6.11",
"@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.6.0",
"@goauthentik/api": "^2025.2.2-1742585853",
"@goauthentik/api": "^2025.2.3-1743464496",
"@lit-labs/ssr": "^3.2.2",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2",
@ -57,9 +57,14 @@
"ts-pattern": "^5.4.0",
"unist-util-visit": "^5.0.0",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.5.1"
"yaml": "^2.5.1",
"bootstrap": "^4.6.1",
"formdata-polyfill": "^4.0.10",
"jquery": "^3.7.1",
"weakmap-polyfill": "^2.0.4"
},
"devDependencies": {
"@types/jquery": "^3.5.31",
"@eslint/js": "^9.11.1",
"@hcaptcha/types": "^1.0.4",
"@lit/localize-tools": "^0.8.0",
@ -90,6 +95,8 @@
"@wdio/spec-reporter": "^9.1.2",
"chromedriver": "^131.0.1",
"esbuild": "^0.25.0",
"esbuild-plugin-copy": "^2.1.1",
"esbuild-plugin-es5": "^2.1.1",
"esbuild-plugin-polyfill-node": "^0.3.0",
"esbuild-plugins-node-modules-polyfill": "^1.7.0",
"eslint": "^9.11.1",
@ -161,6 +168,12 @@
"watch": "run-s build-locales esbuild:watch"
},
"type": "module",
"exports": {
"./package.json": "./package.json",
"./paths": "./paths.js",
"./authentication": "./authentication/index.js",
"./scripts/*": "./scripts/*.mjs"
},
"wireit": {
"build": {
"#comment": [
@ -193,8 +206,7 @@
"./dist/patternfly.min.css"
],
"dependencies": [
"build-locales",
"./packages/sfe:build"
"build-locales"
],
"env": {
"NODE_RUNNER": {
@ -204,12 +216,7 @@
}
},
"build:sfe": {
"dependencies": [
"./packages/sfe:build"
],
"files": [
"./packages/sfe/**/*.ts"
]
"command": "node scripts/build-sfe.mjs"
},
"build-proxy": {
"command": "node scripts/build-web.mjs --proxy",
@ -242,11 +249,6 @@
"lint:package"
]
},
"format:packages": {
"dependencies": [
"./packages/sfe:prettier"
]
},
"lint": {
"command": "eslint --max-warnings 0 --fix",
"env": {
@ -274,11 +276,6 @@
"shell": true,
"command": "sh ./scripts/lint-lockfile.sh package-lock.json"
},
"lint:lockfiles": {
"dependencies": [
"./packages/sfe:lint:lockfile"
]
},
"lint:package": {
"command": "syncpack format -i ' '"
},
@ -314,9 +311,7 @@
"lint:spelling",
"lint:package",
"lint:lockfile",
"lint:lockfiles",
"lint:precommit",
"format:packages"
"lint:precommit"
]
},
"prettier": {

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