Compare commits

...

194 Commits

Author SHA1 Message Date
76b9add6b4 Merge branch 'main' into web/update-provider-forms-for-invalidation
* main: (142 commits)
  core: bump goauthentik.io/api/v3 from 3.2024102.2 to 3.2024104.1 (#12149)
  core: bump debugpy from 1.8.8 to 1.8.9 (#12150)
  core: bump webauthn from 2.2.0 to 2.3.0 (#12151)
  core: bump pydantic from 2.10.0 to 2.10.1 (#12152)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#12156)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#12157)
  core: bump sentry-sdk from 2.18.0 to 2.19.0 (#12153)
  web: bump API Client version (#12147)
  root: Backport version change (#12146)
  website/docs: update info about footer links to match new UI (#12120)
  website/docs: prepare release notes (#12142)
  providers/oauth2: fix migration (#12138)
  providers/oauth2: fix migration dependencies (#12123)
  web: bump API Client version (#12129)
  providers/oauth2: fix redirect uri input (#12122)
  providers/proxy: fix redirect_uri (#12121)
  website/docs: prepare release notes (#12119)
  web: bump API Client version (#12118)
  security: fix CVE 2024 52289 (#12113)
  security: fix CVE 2024 52307 (#12115)
  ...
2024-11-22 10:01:43 -08:00
785403de18 core: bump goauthentik.io/api/v3 from 3.2024102.2 to 3.2024104.1 (#12149)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2024102.2 to 3.2024104.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.2024102.2...v3.2024104.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>
2024-11-22 15:22:41 +01:00
1c4165a373 core: bump debugpy from 1.8.8 to 1.8.9 (#12150)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.8.8 to 1.8.9.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.8.8...v1.8.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-22 14:17:36 +01:00
bbd03b2b05 core: bump webauthn from 2.2.0 to 2.3.0 (#12151)
Bumps [webauthn](https://github.com/duo-labs/py_webauthn) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/duo-labs/py_webauthn/releases)
- [Changelog](https://github.com/duo-labs/py_webauthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/duo-labs/py_webauthn/compare/v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: webauthn
  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>
2024-11-22 14:17:28 +01:00
dd79aec5a6 core: bump pydantic from 2.10.0 to 2.10.1 (#12152)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.10.0 to 2.10.1.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.10.0...v2.10.1)

---
updated-dependencies:
- dependency-name: pydantic
  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>
2024-11-22 14:17:20 +01:00
3634ae3db9 translate: Updates for file web/xliff/en.xlf in zh_CN (#12156)
Translate web/xliff/en.xlf in zh_CN

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-22 14:17:13 +01:00
12e1ee93ed translate: Updates for file web/xliff/en.xlf in zh-Hans (#12157)
Translate web/xliff/en.xlf in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-22 14:16:52 +01:00
62aa3659b8 core: bump sentry-sdk from 2.18.0 to 2.19.0 (#12153)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.18.0 to 2.19.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.18.0...2.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-22 13:52:28 +01:00
23ec05a86c web: bump API Client version (#12147)
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>
2024-11-22 13:51:40 +01:00
520148bba4 root: Backport version change (#12146)
* release: 2024.10.3

* release: 2024.10.4
2024-11-22 01:51:30 +01:00
1c5d61209e website/docs: update info about footer links to match new UI (#12120)
* edit to match new UI

* polished text

* more tweaks

* additional sentence about Flow Executor and link to docs

---------

Co-authored-by: Tana M Berry <tana@goauthentik.com>
2024-11-21 14:14:15 -06:00
5fd1cdbb49 website/docs: prepare release notes (#12142)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 19:11:22 +01:00
0831bef098 providers/oauth2: fix migration (#12138)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 18:54:26 +01:00
26e852e8d5 providers/oauth2: fix migration dependencies (#12123)
we had to change these dependencies for 2024.8.x since that doesn't have invalidation flows

they also need to be changed for 2024.10 when upgrading, and these migrations don't need the invalidation flow migration at all

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 17:24:47 +01:00
95f54abb58 web: bump API Client version (#12129)
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>
2024-11-21 17:24:36 +01:00
a4b6fa1786 providers/oauth2: fix redirect uri input (#12122)
* fix elements disappearing

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

* fix incorrect field input

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

* fix wizard form and display

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 17:21:16 +01:00
2c0923e827 providers/proxy: fix redirect_uri (#12121)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 17:21:06 +01:00
7f224cbfea website/docs: prepare release notes (#12119)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 15:06:17 +01:00
db32439aa9 web: bump API Client version (#12118)
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>
2024-11-21 14:50:27 +01:00
85bb638243 security: fix CVE 2024 52289 (#12113)
* initial migration

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

* migrate tests

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

* fix loading

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

* fix

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

* start dynamic ui

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

* initial ui

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

* add serialize

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

* add error message handling

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

* fix/add tests

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

* prepare docs

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

* migrate to new input

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

* fix tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 14:46:43 +01:00
5ea4580884 security: fix CVE 2024 52307 (#12115)
* security: fix CVE-2024-52307

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

* add docs

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

* fix tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 14:24:28 +01:00
e9c29e1644 security: fix CVE 2024 52287 (#12114)
* security: CVE-2024-52287

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

* add tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-21 14:22:46 +01:00
a9b3a4cf25 website/docs: add CSP to hardening (#11970)
* add CSP to hardening

* re-word docs

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

* fix typo

* use the correct term "location" instead of "origin" in CSP docs

* reword docs

* add comments to permissive CSP directives

* add warning about overwriting existing CSP headers

---------

Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2024-11-21 14:20:04 +01:00
96964d2950 core: bump uvicorn from 0.32.0 to 0.32.1 (#12103)
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.32.0 to 0.32.1.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.32.0...0.32.1)

---
updated-dependencies:
- dependency-name: uvicorn
  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>
2024-11-21 13:08:15 +01:00
c89f663ca8 core: bump google-api-python-client from 2.153.0 to 2.154.0 (#12104)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.153.0 to 2.154.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.153.0...v2.154.0)

---
updated-dependencies:
- dependency-name: google-api-python-client
  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>
2024-11-21 13:07:55 +01:00
2ccb21ac87 core: bump pydantic from 2.9.2 to 2.10.0 (#12105)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.9.2 to 2.10.0.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.9.2...v2.10.0)

---
updated-dependencies:
- dependency-name: pydantic
  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>
2024-11-21 13:07:25 +01:00
d383cca297 translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#12110)
Translate locale/en/LC_MESSAGES/django.po in it

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-21 13:06:46 +01:00
4189981995 internal: add CSP header to files in /media (#12092)
add CSP header to files in `/media`

This fixes a security issue of stored cross-site scripting via embedding
JavaScript in SVG files by a malicious user with `can_save_media`
capability.

This can be exploited if:
- the uploaded file is served from the same origin as authentik, and
- the user opens the uploaded file directly in their browser

Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-21 09:16:07 +01:00
3e6ed8d213 core, web: update translations (#12101)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-21 01:11:15 +01:00
505b61225a web: fix bug that prevented error reporting in current wizard. (#12033)
* web: Add InvalidationFlow to Radius Provider dialogues

## What

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

## Note

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

* web/bugfix/fix-reporting-in-wizard-submit

# What

- Preserves the errors locally for the Wizard, providing explanation and links to fix the issues

# Why

Just a silly mistake on my part. There shouldn't be two copies of errors (and there isn't in the BIG
PRs), but this is how it's designed right now and making the errors show up is an easy fix. In doing
so, the "hack" to move the "bad provider name" to the provider page is included.

* Updated package.json to use Chromedriver 130
2024-11-20 15:23:55 -08:00
e5caa76276 website/docs: group CVEs by year (#12099)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-20 23:03:47 +01:00
d4bf3b7068 root: check remote IP for proxy protocol same as HTTP/etc (#12094)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-20 21:33:35 +01:00
14867e3fdd root: fix activation of locale not being scoped (#12091)
closes #12088

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-20 21:31:00 +01:00
a681af0c6e providers/scim: accept string and int for SCIM IDs (#12093)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-20 18:36:29 +01:00
dc9de43399 website: bump the docusaurus group in /website with 9 updates (#12086)
Bumps the docusaurus group in /website with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@docusaurus/core](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus) | `3.6.1` | `3.6.2` |
| [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) | `3.6.1` | `3.6.2` |
| [@docusaurus/plugin-content-docs](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-content-docs) | `3.6.1` | `3.6.2` |
| [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) | `3.6.1` | `3.6.2` |
| [@docusaurus/theme-common](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-common) | `3.6.1` | `3.6.2` |
| [@docusaurus/theme-mermaid](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-mermaid) | `3.6.1` | `3.6.2` |
| [@docusaurus/module-type-aliases](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-module-type-aliases) | `3.6.1` | `3.6.2` |
| [@docusaurus/tsconfig](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-tsconfig) | `3.6.1` | `3.6.2` |
| [@docusaurus/types](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-types) | `3.6.1` | `3.6.2` |


Updates `@docusaurus/core` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus)

Updates `@docusaurus/plugin-client-redirects` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-plugin-client-redirects)

Updates `@docusaurus/plugin-content-docs` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-plugin-content-docs)

Updates `@docusaurus/preset-classic` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-preset-classic)

Updates `@docusaurus/theme-common` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-theme-common)

Updates `@docusaurus/theme-mermaid` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-theme-mermaid)

Updates `@docusaurus/module-type-aliases` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-module-type-aliases)

Updates `@docusaurus/tsconfig` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-tsconfig)

Updates `@docusaurus/types` from 3.6.1 to 3.6.2
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.2/packages/docusaurus-types)

---
updated-dependencies:
- dependency-name: "@docusaurus/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/plugin-client-redirects"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/plugin-content-docs"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/preset-classic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-common"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-mermaid"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/module-type-aliases"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/tsconfig"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/types"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: docusaurus
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 13:53:15 +01:00
01fc5eb4ce core: fix source_flow_manager throwing error when authenticated user attempts to re-authenticate with existing link (#12080)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-19 18:27:04 +01:00
50015c5463 translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#12079)
Translate locale/en/LC_MESSAGES/django.po in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-19 17:33:23 +01:00
83d281eae5 scripts: remove read_replicas from generated dev config (#12078)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-19 17:33:02 +01:00
9e96f19cb9 core: bump geoip2 from 4.8.0 to 4.8.1 (#12071)
Bumps [geoip2](https://github.com/maxmind/GeoIP2-python) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/maxmind/GeoIP2-python/releases)
- [Changelog](https://github.com/maxmind/GeoIP2-python/blob/main/HISTORY.rst)
- [Commits](https://github.com/maxmind/GeoIP2-python/compare/v4.8.0...v4.8.1)

---
updated-dependencies:
- dependency-name: geoip2
  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>
2024-11-19 14:23:30 +01:00
3cec4d23e8 core: bump goauthentik.io/api/v3 from 3.2024100.2 to 3.2024102.2 (#12072)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2024100.2 to 3.2024102.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.2024100.2...v3.2024102.2)

---
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>
2024-11-19 14:22:57 +01:00
a70be016d9 core: bump maxmind/geoipupdate from v7.0.1 to v7.1.0 (#12073)
Bumps maxmind/geoipupdate from v7.0.1 to v7.1.0.

---
updated-dependencies:
- dependency-name: maxmind/geoipupdate
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-19 14:22:49 +01:00
c957a5016d translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12074)
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>
2024-11-19 14:22:31 +01:00
f4d9b2e6bd translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12075)
Translate django.po in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-19 14:22:10 +01:00
0e033d1f61 translate: Updates for file web/xliff/en.xlf in zh-Hans (#12076)
Translate web/xliff/en.xlf in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-19 14:21:53 +01:00
c8e6e60f70 translate: Updates for file web/xliff/en.xlf in zh_CN (#12077)
Translate web/xliff/en.xlf in zh_CN

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-19 14:21:34 +01:00
ce997f4473 web/admin: auto-prefill user path for new users based on selected path (#12070)
web/admin: auto-select user path based on selected path

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-19 14:20:02 +01:00
be30cb4553 core: bump aiohttp from 3.10.2 to 3.10.11 (#12069)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.10.2 to 3.10.11.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.10.2...v3.10.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-19 01:48:55 +01:00
88b6076161 web/admin: fix brand title not respected in application list (#12068)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-18 22:39:05 +01:00
fbba672161 core: bump pyjwt from 2.9.0 to 2.10.0 (#12063)
Bumps [pyjwt](https://github.com/jpadilla/pyjwt) from 2.9.0 to 2.10.0.
- [Release notes](https://github.com/jpadilla/pyjwt/releases)
- [Changelog](https://github.com/jpadilla/pyjwt/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jpadilla/pyjwt/compare/2.9.0...2.10.0)

---
updated-dependencies:
- dependency-name: pyjwt
  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>
2024-11-18 14:57:56 +01:00
b4e41de8ba web: add italian locale (#11958)
* Update lit-localize.json add italian

Signed-off-by: tmassimi <tmassimi@users.noreply.github.com>

* fix

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

---------

Signed-off-by: tmassimi <tmassimi@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2024-11-18 14:57:25 +01:00
ac00386a29 web/admin: better footer links (#12004)
* web: Add InvalidationFlow to Radius Provider dialogues

## What

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

## Note

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

* First things first: save the blueprint that initializes the test runner.

* Committing to having the PKs be a string, and streamlining an event handler.  Type solidity needed for the footer control.

* web/admin/better-footer-links

# What

- A data control that takes two string fields and returns the JSON object for a FooterLink
- A data control that takes a control like the one above and assists the user in entering a
  collection of such objects.

# Why

We're trying to move away from CodeMirror for the simple things, like tables of what is essentially
data entry. Jens proposed this ArrayInput thing, and I've simplified it so you define what "a row"
is as a small, lightweight custom Component that returns and validates the datatype for that row,
and ArrayInput creates a table of rows, and that's that.

We're still working out the details, but the demo is to replace the "Name & URL" table in
AdminSettingsForm with this, since it was silly to ask the customer to hand-write JSON or YAML,
getting the keys right every time, for an `Array<Record<{ name: string, href: string }>>`. And some
client-side validation can't hurt.

Storybook included.  Tests to come.

* Not ready for prime time.

* One lint.  Other lints are still in progress.

* web: lots of 'as unknown as Foo'

I know this is considered bad practice, but we use Lit and Lit.spread
to send initialization arguments to functions that create DOM
objects, and Lit's prefix convention of '.' for object, '?' for
boolean, and '@' for event handler doesn't map at all to the Interface
declarations of Typescript.  So we have to cast these types when
sending them via functions to constructors.

* web/admin/better-footer-links

# What

- Remove the "JSON or YAML" language from the AdminSettings page for describing FooterLinks inputs.
- Add unit tests for ArrayInput and AdminSettingsFooterLinks.
- Provide a property for accessing a component's value

# Why

Providing a property by which the JSONified version of the value can be accessed enhances the
ability of tests to independently check that the value is in a state we desire, since properties can
easily be accessed across the wire protocol used by browser-based testing environments.

* Ensure the UI is built from _current_ before running tests.
2024-11-18 13:17:21 +01:00
10a473eb90 core, web: update translations (#12052)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-18 13:16:59 +01:00
4744550a3c core: bump twilio from 9.3.6 to 9.3.7 (#12061)
Bumps [twilio](https://github.com/twilio/twilio-python) from 9.3.6 to 9.3.7.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/9.3.6...9.3.7)

---
updated-dependencies:
- dependency-name: twilio
  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>
2024-11-18 13:13:44 +01:00
2b8121f765 core: bump ruff from 0.7.3 to 0.7.4 (#12062)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.7.3 to 0.7.4.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.7.3...0.7.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 13:13:38 +01:00
e900df358d core: bump setproctitle from 1.3.3 to 1.3.4 (#12064)
Bumps [setproctitle](https://github.com/dvarrazzo/py-setproctitle) from 1.3.3 to 1.3.4.
- [Changelog](https://github.com/dvarrazzo/py-setproctitle/blob/master/HISTORY.rst)
- [Commits](https://github.com/dvarrazzo/py-setproctitle/compare/version-1.3.3...version-1.3.4)

---
updated-dependencies:
- dependency-name: setproctitle
  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>
2024-11-18 13:13:29 +01:00
75df0ab154 core: bump channels from 4.1.0 to 4.2.0 (#12065)
Bumps [channels](https://github.com/django/channels) from 4.1.0 to 4.2.0.
- [Changelog](https://github.com/django/channels/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels/compare/4.1.0...4.2.0)

---
updated-dependencies:
- dependency-name: channels
  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>
2024-11-18 13:13:18 +01:00
826d2eec7a core: bump coverage from 7.6.5 to 7.6.7 (#12066)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.5 to 7.6.7.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.6.5...7.6.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 13:13:08 +01:00
bb5e7628b9 core: bump channels-redis from 4.2.0 to 4.2.1 (#12067)
Bumps [channels-redis](https://github.com/django/channels_redis) from 4.2.0 to 4.2.1.
- [Changelog](https://github.com/django/channels_redis/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels_redis/compare/4.2.0...4.2.1)

---
updated-dependencies:
- dependency-name: channels-redis
  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>
2024-11-18 13:12:58 +01:00
57e9474658 website: bump cross-spawn from 7.0.3 to 7.0.5 in /website (#12060)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.5.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.5)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 03:07:09 +01:00
89b6b7a29a web: bump API Client version (#12059)
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>
2024-11-18 02:37:44 +01:00
4859dc7e68 core: add support to set policy bindings in transactional endpoint (#10399)
* core: add support to set policy bindings in transactional endpoint

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

* improve permission checks

especially since we'll be using the wizard as default in the future, it shouldn't be superuser only

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

* rebase, fix error response when using duplicate name in provider

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

* add permission test

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-18 00:55:25 +01:00
550e24edde translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12045)
Translate django.po in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-15 18:52:24 +01:00
39371bb3a6 translate: Updates for file web/xliff/en.xlf in zh_CN (#12047)
Translate web/xliff/en.xlf in zh_CN

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-15 18:52:02 +01:00
cea49c475e translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12044)
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>
2024-11-15 18:51:48 +01:00
282946c156 translate: Updates for file web/xliff/en.xlf in zh-Hans (#12046)
* Translate web/xliff/en.xlf in zh-Hans

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

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

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

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-15 18:51:27 +01:00
9c27b81e4b web/flows: fix invisible captcha call (#12048)
* fix invisible captcha call

* fix invisible captcha DOM removal
2024-11-15 18:49:57 +01:00
0bdef2a0f4 rbac: fix incorrect object_description for object-level permissions (#12029)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-15 14:21:22 +01:00
fcbee2edaa stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#12036)
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>
2024-11-15 13:53:25 +01:00
6b4c0bcb4b core: bump coverage from 7.6.4 to 7.6.5 (#12037)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 7.6.4 to 7.6.5.
- [Release notes](https://github.com/nedbat/coveragepy/releases)
- [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst)
- [Commits](https://github.com/nedbat/coveragepy/compare/7.6.4...7.6.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-15 13:53:14 +01:00
1e19ba6cb0 ci: bump codecov/codecov-action from 4 to 5 (#12038)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-15 13:53:06 +01:00
6702f34b40 release: 2024.10.2 (#12031) 2024-11-15 00:53:40 +01:00
c9036f870d providers/ldap: fix global search_full_directory permission not being sufficient (#12028)
* providers/ldap: fix global search_full_directory permission not being sufficient

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

* use full name of permission

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-14 19:45:35 +01:00
bcb91d2812 website/docs: 2024.10.2 release notes (#12025)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-14 16:59:24 +01:00
a2547e928d lifecycle: fix ak exit status not being passed (#12024)
* lifecycle: fix ak exit status not being passed

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

* use waitstatus_to_exitcode

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-14 15:33:03 +01:00
14d013645f core: use versioned_script for path only (#12003)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-14 14:02:18 +01:00
e53479f69c core, web: update translations (#12020)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-14 13:57:49 +01:00
dd14bfbe87 core: bump google-api-python-client from 2.152.0 to 2.153.0 (#12021)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.152.0 to 2.153.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.152.0...v2.153.0)

---
updated-dependencies:
- dependency-name: google-api-python-client
  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>
2024-11-14 13:57:38 +01:00
cf6c3c6d3f providers/oauth2: fix manual device code entry (#12017)
* providers/oauth2: fix manual device code entry

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

* make code input a char field to prevent leading 0s from being cut off

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-13 21:45:16 +01:00
74171e0b5a crypto: validate that generated certificate's name is unique (#12015)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-13 16:31:11 +01:00
7f9de1ab7e core, web: update translations (#12006)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-13 16:15:59 +01:00
7358f3bc37 core: bump google-api-python-client from 2.151.0 to 2.152.0 (#12007)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.151.0 to 2.152.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.151.0...v2.152.0)

---
updated-dependencies:
- dependency-name: google-api-python-client
  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>
2024-11-13 16:15:44 +01:00
94400191a2 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#12011)
Translate django.po in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-13 16:14:14 +01:00
efdb1339d6 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#12010)
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>
2024-11-13 16:14:00 +01:00
725fd899ca translate: Updates for file web/xliff/en.xlf in zh-Hans (#12012)
Translate web/xliff/en.xlf in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-13 16:13:44 +01:00
dffe3b563d translate: Updates for file web/xliff/en.xlf in zh_CN (#12013)
Translate web/xliff/en.xlf in zh_CN

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-13 16:13:27 +01:00
a892d4afd8 providers/proxy: fix Issuer when AUTHENTIK_HOST_BROWSER is set (#11968)
correctly use host_browser's hostname as host header for token requests to ensure Issuer is identical
2024-11-13 00:54:40 +01:00
1f6ae73e6e website/docs: move S3 ad GeoIP to System Management/Operations (#11998)
* first pass

* fix links

* oops redirects wrong

* fixed syntax

* Apply suggestions from code review

Signed-off-by: Jens L. <jens@beryju.org>

---------

Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-12 18:40:34 +00:00
Dis
568d5c3446 website/integrations: nextcloud: add SSE warning (#11976)
* fix: add sse warning to nextcloud

Signed-off-by: Dis <397465+disconn3ct@users.noreply.github.com>

* chore: pr feedback

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dis <397465+disconn3ct@users.noreply.github.com>

* Apply suggestions from code review

Signed-off-by: Jens L. <jens@beryju.org>

---------

Signed-off-by: Dis <397465+disconn3ct@users.noreply.github.com>
Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Jens L. <jens@beryju.org>
2024-11-12 18:34:53 +00:00
54bbdd5ea8 web: bump API Client version (#11997)
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>
2024-11-12 17:11:06 +01:00
eb9d8c214b sources/kerberos: use new python-kadmin implementation (#11932)
* sources/kerberos: use new python-kadmin implementation

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

* skip spnego on macos

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

---------

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2024-11-12 15:59:22 +01:00
0cffe0c953 core: add ability to provide reason for impersonation (#11951)
* core: add ability to provide reason for impersonation

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

* tenants api things

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

* add missing implem

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

* A tooltip needs a DOM object to determine the coordinates where it should render.  A solitary string is not enough; a  is needed here.

* web: user impersonation reason

To determine where to render the Tooltip content, the object associated with the Tooltip must be a DOM object with an HTML tag.  A naked string is not enough; a `<span>` will do nicely here.

Also, fixed a build failure: PFSize was not defined in RelatedUserList.

* add and fix tests

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

* avoid migration change

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

* small fixes

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

---------

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Ken Sternberg <ken@goauthentik.io>
2024-11-12 14:42:53 +01:00
6d5a61187e website/integrations: update vcenter integration docs (#11768)
* core: add prompt_data to auth flow (#11702)

I added the prompt_data and user_path to the auth flow. This allows us to more easily sync users details whenever they're logged in through a Source by using the Write stage, identical to an  Enrolment flow.

This makes sure that mappings etc are automatically taken into consideration, and are passed to the Authentication flow.

While I was at it, I made the code consistent with the `handle_enroll` method.

Signed-off-by: Wouter van Os <wouter0100@gmail.com>

* updates

* and remove errant .py file that somwhow snuck into the PR! also removed errant api ref files remove old images

* tweak to bumb build

* tweaks

* more tweaks

* removed extraneous old settings

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* Update website/integrations/services/vmware-vcenter/index.md

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

* formatting

* tweak

* why not saved before argh

---------

Signed-off-by: Wouter van Os <wouter0100@gmail.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Wouter van Os <wouter0100@gmail.com>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-11-12 14:10:35 +01:00
df4cdf1932 core, web: update translations (#11995)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-12 12:57:33 +01:00
887fbb7e86 website: bump postcss from 8.4.48 to 8.4.49 in /website (#11996)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.48 to 8.4.49.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.48...8.4.49)

---
updated-dependencies:
- dependency-name: postcss
  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>
2024-11-12 12:55:56 +01:00
b2c9dff6d5 web: bump API Client version (#11992)
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>
2024-11-11 12:41:56 +00:00
6b155621fe blueprints: add default Password policy (#11793)
* add password policy to default password change flow

This change complies with the minimal compositional requirements by
NIST SP 800-63 Digital Identity Guidelines. See
https://pages.nist.gov/800-63-4/sp800-63b.html#password

More work is needed to comply with other parts of the Guidelines,
specifically

> If the chosen password is found on the blocklist, the CSP or verifier
> [...] SHALL provide the reason for rejection.

and

> Verifiers SHALL offer guidance to the subscriber to assist the user in
> choosing a strong password. This is particularly important following
> the rejection of a password on the blocklist as it discourages trivial
> modification of listed weak passwords.

* add docs for default Password policy

* remove HIBP from default Password policy

* add zxcvbn to default Password policy

* add fallback password error message to password policy, fix validation policy

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

* reword docs

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

* add HIBP caveat

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

* separate policy into separate blueprint

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

* use password policy for oobe flow

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

* kiss

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2024-11-11 13:31:30 +01:00
4f1ddc5779 stages/captcha: Run interactive captcha in Frame (#11857)
* initial turnstile frame

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

* add interactive flag

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

* add interactive support for all

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

* fix missing migration

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

* don't hide in identification stage if interactive

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

* fixup

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

* require less hacky css

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

* update docs

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-11 13:20:49 +01:00
10d50481c9 core, web: update translations (#11979)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-11 13:01:48 +01:00
d1303236c6 core: bump packaging from 24.1 to 24.2 (#11985)
Bumps [packaging](https://github.com/pypa/packaging) from 24.1 to 24.2.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pypa/packaging/compare/24.1...24.2)

---
updated-dependencies:
- dependency-name: packaging
  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>
2024-11-11 13:01:37 +01:00
5d231ce59b core: bump ruff from 0.7.2 to 0.7.3 (#11986)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.7.2 to 0.7.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.7.2...0.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 13:01:23 +01:00
f6afdc05ff core: bump msgraph-sdk from 1.11.0 to 1.12.0 (#11987)
Bumps [msgraph-sdk](https://github.com/microsoftgraph/msgraph-sdk-python) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/microsoftgraph/msgraph-sdk-python/releases)
- [Changelog](https://github.com/microsoftgraph/msgraph-sdk-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoftgraph/msgraph-sdk-python/compare/v1.11.0...v1.12.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 13:01:15 +01:00
d68a8ce0b3 website: bump the docusaurus group in /website with 9 updates (#11988)
Bumps the docusaurus group in /website with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@docusaurus/core](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus) | `3.6.0` | `3.6.1` |
| [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) | `3.6.0` | `3.6.1` |
| [@docusaurus/plugin-content-docs](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-content-docs) | `3.6.0` | `3.6.1` |
| [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) | `3.6.0` | `3.6.1` |
| [@docusaurus/theme-common](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-common) | `3.6.0` | `3.6.1` |
| [@docusaurus/theme-mermaid](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-mermaid) | `3.6.0` | `3.6.1` |
| [@docusaurus/module-type-aliases](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-module-type-aliases) | `3.6.0` | `3.6.1` |
| [@docusaurus/tsconfig](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-tsconfig) | `3.6.0` | `3.6.1` |
| [@docusaurus/types](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-types) | `3.6.0` | `3.6.1` |


Updates `@docusaurus/core` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus)

Updates `@docusaurus/plugin-client-redirects` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-plugin-client-redirects)

Updates `@docusaurus/plugin-content-docs` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-plugin-content-docs)

Updates `@docusaurus/preset-classic` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-preset-classic)

Updates `@docusaurus/theme-common` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-theme-common)

Updates `@docusaurus/theme-mermaid` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-theme-mermaid)

Updates `@docusaurus/module-type-aliases` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-module-type-aliases)

Updates `@docusaurus/tsconfig` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-tsconfig)

Updates `@docusaurus/types` from 3.6.0 to 3.6.1
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.1/packages/docusaurus-types)

---
updated-dependencies:
- dependency-name: "@docusaurus/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/plugin-client-redirects"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/plugin-content-docs"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/preset-classic"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-common"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-mermaid"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/module-type-aliases"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/tsconfig"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: docusaurus
- dependency-name: "@docusaurus/types"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: docusaurus
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 13:01:05 +01:00
a14d120749 website: bump postcss from 8.4.47 to 8.4.48 in /website (#11989)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.47 to 8.4.48.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.47...8.4.48)

---
updated-dependencies:
- dependency-name: postcss
  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>
2024-11-11 13:00:52 +01:00
9036724b66 stages/password: use recovery flow from brand (#11953)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-08 16:51:58 +01:00
022b52075f core: bump golang.org/x/sync from 0.8.0 to 0.9.0 (#11962)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/sync/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  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>
2024-11-08 16:38:40 +01:00
cdea9a9553 web: bump cookie, swagger-client and express in /web (#11966)
Bumps [cookie](https://github.com/jshttp/cookie), [swagger-client](https://github.com/swagger-api/swagger-js) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `cookie` from 0.6.0 to 0.7.1
- [Release notes](https://github.com/jshttp/cookie/releases)
- [Commits](https://github.com/jshttp/cookie/compare/v0.6.0...v0.7.1)

Updates `swagger-client` from 3.29.3 to 3.31.0
- [Release notes](https://github.com/swagger-api/swagger-js/releases)
- [Changelog](https://github.com/swagger-api/swagger-js/blob/master/.releaserc)
- [Commits](https://github.com/swagger-api/swagger-js/compare/v3.29.3...v3.31.0)

Updates `express` from 4.21.0 to 4.21.1
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.1/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.21.0...4.21.1)

---
updated-dependencies:
- dependency-name: cookie
  dependency-type: indirect
- dependency-name: swagger-client
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 13:29:36 +01:00
2ea7196fd3 core, web: update translations (#11959)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-08 13:24:43 +01:00
729102a5c9 core: bump debugpy from 1.8.7 to 1.8.8 (#11961)
Bumps [debugpy](https://github.com/microsoft/debugpy) from 1.8.7 to 1.8.8.
- [Release notes](https://github.com/microsoft/debugpy/releases)
- [Commits](https://github.com/microsoft/debugpy/compare/v1.8.7...v1.8.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 13:24:34 +01:00
22e269234d core: bump golang.org/x/oauth2 from 0.23.0 to 0.24.0 (#11963)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.23.0 to 0.24.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.23.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  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>
2024-11-08 13:24:23 +01:00
750aaf22ac ci: fix dockerfile warning (#11956)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2024-11-07 19:16:11 +00:00
556eca2665 website/docs: fix slug matching redirect URI causing broken refresh (#11950)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-07 13:31:43 +01:00
4aeb243692 website/integrations: jellyfin: update plugin catalog location (#11948)
* website/integrations: jellyfin: update plugin catalog location

The add repositories button is now under the Admin interface > Catalog > Gear icon. This PR reflects that change.

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

* website/integrations: jellyfin: condense steps

Reduce the number of steps from 5 to it's original number, 3.

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

* website/integrations: jellyfin: add admin dashboard location

Tell the user where the admin dashboard is and how to reach it.

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

---------

Signed-off-by: 4d62 <github-user@sdko.org>
2024-11-07 12:47:30 +01:00
71361e5de7 translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#11942)
Translate locale/en/LC_MESSAGES/django.po in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-07 12:43:28 +01:00
f92061afd7 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11946)
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>
2024-11-07 12:43:08 +01:00
dbc477c7b1 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11947)
Translate django.po in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-07 12:42:49 +01:00
dfb4f86c25 website/docs: clarify traefik ingress setup (#11938) 2024-11-06 18:01:20 +00:00
49577fe333 core: bump importlib-metadata from 8.4.0 to 8.5.0 (#11934)
Bumps [importlib-metadata](https://github.com/python/importlib_metadata) from 8.4.0 to 8.5.0.
- [Release notes](https://github.com/python/importlib_metadata/releases)
- [Changelog](https://github.com/python/importlib_metadata/blob/main/NEWS.rst)
- [Commits](https://github.com/python/importlib_metadata/compare/v8.4.0...v8.5.0)

---
updated-dependencies:
- dependency-name: importlib-metadata
  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>
2024-11-06 13:54:29 +01:00
05b5987ccb web: bump API Client version (#11930)
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>
2024-11-05 12:43:21 -08:00
0a862e4fff root: backport version bump 2024.10.1 (#11929)
release: 2024.10.1
2024-11-05 20:29:31 +01:00
821e296c7e website/docs: 2024.10.1 Release Notes (#11926)
* fix API Changes in `2024.10` changelog

* add `2024.10.1` API Changes to changelog

* add changes in `2024.10.1` to changelog

* change `details` to `h3` in changelog
2024-11-05 18:04:14 +01:00
b44b5c1d3a website: bump path-to-regexp from 1.8.0 to 1.9.0 in /website (#11924)
Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v1.8.0...v1.9.0)

---
updated-dependencies:
- dependency-name: path-to-regexp
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-05 12:06:40 +01:00
4774f86d64 core: bump sentry-sdk from 2.17.0 to 2.18.0 (#11918)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.17.0 to 2.18.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.17.0...2.18.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-05 11:34:16 +01:00
4b9abaefad website: bump the docusaurus group in /website with 9 updates (#11917)
Bumps the docusaurus group in /website with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [@docusaurus/core](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus) | `3.5.2` | `3.6.0` |
| [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) | `3.5.2` | `3.6.0` |
| [@docusaurus/plugin-content-docs](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-content-docs) | `3.5.2` | `3.6.0` |
| [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) | `3.5.2` | `3.6.0` |
| [@docusaurus/theme-common](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-common) | `3.5.2` | `3.6.0` |
| [@docusaurus/theme-mermaid](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-mermaid) | `3.5.2` | `3.6.0` |
| [@docusaurus/module-type-aliases](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-module-type-aliases) | `3.5.2` | `3.6.0` |
| [@docusaurus/tsconfig](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-tsconfig) | `3.5.2` | `3.6.0` |
| [@docusaurus/types](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-types) | `3.5.2` | `3.6.0` |


Updates `@docusaurus/core` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus)

Updates `@docusaurus/plugin-client-redirects` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-plugin-client-redirects)

Updates `@docusaurus/plugin-content-docs` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-plugin-content-docs)

Updates `@docusaurus/preset-classic` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-preset-classic)

Updates `@docusaurus/theme-common` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-theme-common)

Updates `@docusaurus/theme-mermaid` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-theme-mermaid)

Updates `@docusaurus/module-type-aliases` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-module-type-aliases)

Updates `@docusaurus/tsconfig` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-tsconfig)

Updates `@docusaurus/types` from 3.5.2 to 3.6.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.6.0/packages/docusaurus-types)

---
updated-dependencies:
- dependency-name: "@docusaurus/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/plugin-client-redirects"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/plugin-content-docs"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/preset-classic"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-common"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-mermaid"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/module-type-aliases"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/tsconfig"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: docusaurus
- dependency-name: "@docusaurus/types"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: docusaurus
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-05 11:33:50 +01:00
21d3e33985 core: bump goauthentik.io/api/v3 from 3.2024100.1 to 3.2024100.2 (#11915)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2024100.1 to 3.2024100.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.2024100.1...v3.2024100.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-05 11:33:15 +01:00
2ee47d1b4d core, web: update translations (#11914)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-05 11:32:50 +01:00
0f8d497413 web: bump API Client version (#11909) 2024-11-04 18:53:26 +00:00
7352f37b05 enterprise/rac: fix API Schema for invalidation_flow (#11907)
* enterprise/rac: fix API Schema for invalidation_flow

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

* fix tests

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

* add tests

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-04 19:33:31 +01:00
f128ac026d core: add None check to a device's extra_description (#11904) 2024-11-04 18:10:02 +01:00
5198174e08 providers/oauth2: fix size limited index for tokens (#11879)
* providers/oauth2: fix size limited index for tokens

I preserved the migrations as comments so the index IDs and migration
IDs remain searchable without accessing git history.

* rename migration file to more descriptive
2024-11-04 18:04:35 +01:00
92fcb42f8a web: fix missing status code on failed build (#11903)
* fix missing status code on failed build

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

* fix locale

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

* fix format

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-11-04 17:31:59 +01:00
1a02a9c978 website: bump docusaurus-theme-openapi-docs from 4.1.0 to 4.2.0 in /website (#11897)
website: bump docusaurus-theme-openapi-docs in /website

Bumps [docusaurus-theme-openapi-docs](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/tree/HEAD/packages/docusaurus-theme-openapi-docs) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/releases)
- [Changelog](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/commits/v4.2.0/packages/docusaurus-theme-openapi-docs)

---
updated-dependencies:
- dependency-name: docusaurus-theme-openapi-docs
  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>
2024-11-04 13:00:31 +01:00
96f49ed489 translate: Updates for file locale/en/LC_MESSAGES/django.po in de (#11891)
Translate locale/en/LC_MESSAGES/django.po in de

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-04 12:59:43 +01:00
f4a27958b6 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#11884)
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>
2024-11-04 12:59:13 +01:00
ee687002dd translate: Updates for file web/xliff/en.xlf in tr (#11878)
Translate web/xliff/en.xlf in tr

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-04 12:58:57 +01:00
962bc54464 translate: Updates for file locale/en/LC_MESSAGES/django.po in tr (#11866)
Translate locale/en/LC_MESSAGES/django.po in tr

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-11-04 12:57:10 +01:00
c79851f582 core: bump google-api-python-client from 2.149.0 to 2.151.0 (#11885)
Bumps [google-api-python-client](https://github.com/googleapis/google-api-python-client) from 2.149.0 to 2.151.0.
- [Release notes](https://github.com/googleapis/google-api-python-client/releases)
- [Commits](https://github.com/googleapis/google-api-python-client/compare/v2.149.0...v2.151.0)

---
updated-dependencies:
- dependency-name: google-api-python-client
  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>
2024-11-04 12:54:36 +01:00
493d2843d8 core: bump selenium from 4.26.0 to 4.26.1 (#11886)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.26.0 to 4.26.1.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 12:54:20 +01:00
d2324fd073 core, web: update translations (#11896)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-11-04 12:54:05 +01:00
7d82b856ba website: bump docusaurus-plugin-openapi-docs from 4.1.0 to 4.2.0 in /website (#11898)
website: bump docusaurus-plugin-openapi-docs in /website

Bumps [docusaurus-plugin-openapi-docs](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/tree/HEAD/packages/docusaurus-plugin-openapi-docs) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/releases)
- [Changelog](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs/commits/v4.2.0/packages/docusaurus-plugin-openapi-docs)

---
updated-dependencies:
- dependency-name: docusaurus-plugin-openapi-docs
  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>
2024-11-04 12:53:13 +01:00
08e60b5237 core: bump watchdog from 5.0.3 to 6.0.0 (#11899)
Bumps [watchdog](https://github.com/gorakhargosh/watchdog) from 5.0.3 to 6.0.0.
- [Release notes](https://github.com/gorakhargosh/watchdog/releases)
- [Changelog](https://github.com/gorakhargosh/watchdog/blob/master/changelog.rst)
- [Commits](https://github.com/gorakhargosh/watchdog/compare/v5.0.3...v6.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 11:59:41 +01:00
98a8dca292 core: bump ruff from 0.7.1 to 0.7.2 (#11900)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.7.1 to 0.7.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.7.1...0.7.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 11:59:33 +01:00
2a05dc50d6 core: bump django-pglock from 1.6.2 to 1.7.0 (#11901)
Bumps [django-pglock](https://github.com/Opus10/django-pglock) from 1.6.2 to 1.7.0.
- [Release notes](https://github.com/Opus10/django-pglock/releases)
- [Changelog](https://github.com/Opus10/django-pglock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Opus10/django-pglock/compare/1.6.2...1.7.0)

---
updated-dependencies:
- dependency-name: django-pglock
  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>
2024-11-04 11:59:18 +01:00
d76e3c8023 Unneeded console.log 2024-11-01 12:46:24 -07:00
c24b619fb6 website/docs: fix release notes to say Federation (#11889)
* fix Federation

* typo

* added back should

* slooooow down

---------

Co-authored-by: Tana M Berry <tana@goauthentik.com>
2024-11-01 13:55:54 -05:00
fb40ee72a5 Fix merge bug; modify package to always build before testing to catch bugs of this kind. 2024-11-01 10:46:43 -07:00
24f52252ba Merge bug! Lesson of the day: always run npm run build && npm run test:e2e in that order! 2024-11-01 10:27:40 -07:00
26ceb3d6c9 How did that get through? 2024-11-01 10:20:44 -07:00
f756be2ece Merge branch 'main' into web/update-provider-forms-for-invalidation
* main:
  website: bump elliptic from 6.5.7 to 6.6.0 in /website (#11869)
  core: bump selenium from 4.25.0 to 4.26.0 (#11875)
  core: bump goauthentik.io/api/v3 from 3.2024083.14 to 3.2024100.1 (#11876)
  website/docs: add info about invalidation flow, default flows in general (#11800)
  website: fix docs redirect (#11873)
  website: remove RC disclaimer for version 2024.10 (#11871)
  website: update supported versions (#11841)
  web: bump API Client version (#11870)
  root: backport version bump 2024.10.0 (#11868)
  website/docs: 2024.8.4 release notes (#11862)
  web/admin: provide default invalidation flows for LDAP and Radius (#11861)
  core, web: update translations (#11858)
2024-10-31 09:33:14 -07:00
f192690f25 website: bump elliptic from 6.5.7 to 6.6.0 in /website (#11869)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.7 to 6.6.0.
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.7...v6.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-31 14:33:00 +01:00
ecd013401c core: bump selenium from 4.25.0 to 4.26.0 (#11875)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.25.0 to 4.26.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.25.0...selenium-4.26.0)

---
updated-dependencies:
- dependency-name: selenium
  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>
2024-10-31 14:31:45 +01:00
38adb41244 core: bump goauthentik.io/api/v3 from 3.2024083.14 to 3.2024100.1 (#11876)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2024083.14 to 3.2024100.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.2024083.14...v3.2024100.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>
2024-10-31 14:31:37 +01:00
712e5084c1 website/docs: add info about invalidation flow, default flows in general (#11800)
* restructure

* tweak

* fix header

* added more definitions

* jens excellent idea

* restructure the Layouts content

* tweaks

* links fix

* links still

* fighting links and cache

* argh links

* ditto

* remove link

* anothe link

* Jens' edit

* listed default flows set by brand

* add links back

* tweaks

* used import for list

* tweak

* rewrite some stuff

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

* format

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

* mangled rebase, fixed

* bump

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana M Berry <tana@goauthentik.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2024-10-31 08:26:51 -05:00
e2f8574b6a website: fix docs redirect (#11873)
fix docs redirect
2024-10-31 00:48:21 +00:00
d43940d5d6 website: remove RC disclaimer for version 2024.10 (#11871) 2024-10-31 01:31:41 +01:00
faaba483a0 website: update supported versions (#11841)
update supported versions
2024-10-31 01:02:37 +01:00
fa78c24516 web: bump API Client version (#11870)
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>
2024-10-30 23:59:56 +00:00
4bfd06e034 Labeling error. 2024-10-30 16:52:22 -07:00
8245d08ddb root: backport version bump 2024.10.0 (#11868)
* release: 2024.10.0-rc1

* root: `bumpversion` 2024.10 (#11865)

release: 2024.10.0
2024-10-31 00:39:41 +01:00
f452617f29 website/docs: 2024.8.4 release notes (#11862)
* website/docs: 2024.8.4 release notes

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

* typo

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-10-30 20:05:02 +01:00
107dff39af Updating these to correspond to changes in MAIN. 2024-10-30 10:36:54 -07:00
ed6d1880a0 web/admin: provide default invalidation flows for LDAP and Radius (#11861)
* web: Add InvalidationFlow to Radius Provider dialogues

## What

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

## Note

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

* web/admin: provide default invalidation flows for LDAP provider.

* admin/web: the default invalidation flows for LDAP and Radius are different from the others.
2024-10-30 17:36:02 +00:00
2909a15009 core, web: update translations (#11858)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-10-30 15:27:59 +01:00
401850c5e2 Merge branch 'main' into web/update-provider-forms-for-invalidation
* main:
  web/admin: fix code-based MFA toggle not working in wizard (#11854)
  sources/kerberos: add kiprop to ignored system principals (#11852)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11846)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#11845)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#11847)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#11848)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11849)
  translate: Updates for file web/xliff/en.xlf in it (#11850)
  website: 2024.10 Release Notes (#11839)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#11814)
  core, web: update translations (#11821)
  core: bump goauthentik.io/api/v3 from 3.2024083.13 to 3.2024083.14 (#11830)
  core: bump service-identity from 24.1.0 to 24.2.0 (#11831)
  core: bump twilio from 9.3.5 to 9.3.6 (#11832)
  core: bump pytest-randomly from 3.15.0 to 3.16.0 (#11833)
  website/docs: Update social-logins github (#11822)
  website/docs: remove � (#11823)
  lifecycle: fix kdc5-config missing (#11826)
  website/docs: update preview status of different features (#11817)
2024-10-29 15:56:05 -07:00
11bc9b8041 Not sure how *that* got lost, but... 2024-10-29 15:51:19 -07:00
807e2a9fb0 web/admin: Unify the forms for providers between the ./admin/providers and ./admin/applications/wizard
## What

- For LDAP, OAuth2, Radius, SAML, SCIM, and Proxy providers, extract the literal form rendering
  component of each provider into a function.  After all, that's what they are: they take input (the
  render state) and produce output (HTML with event handlers).
- Rip out all of the forms in the wizard and replace them with ☝️
- Write E2E tests that exercise *all* of the components in *all* of the forms mentioned. See test
  results.  These tests come in two flavors, "simple" (minimum amount needed to make the provider
  "pass" the backend's parsers) and "complete" (touches every legal field in the form according to
  the authentik `./schema.yml` file).  As a result, every field is validated against the schema
  (although the schema is currently ported into the test by hand.
- Fixed some serious bugginess in the way the wizard `commit` phase handles errors.

## Details

### Providers

In some cases, I broke up the forms into smaller units:

- Proxy, especially, with standalone units now for `renderHttpBasic`, `renderModeSelector`,
`renderSettings`, and the differing modes)
- SAML now has a `renderHasSigningKp` object, which makes that part of the code much more readable.

I also extracted a few of static `options` collections into static const objects, so that the form
object itself would be a bit more readable.

### Wizard

Just ripped out all of the Provider forms.  All of them.  They weren't going to be needed in our
glorious new future.

Using the information provided by the `providerTypes` object, it was easy to extract all of the
information that had once been in `ak-application-wizard-authentication-method-choice.choices`. The
only thing left now is the renderers, one for each of the forms ripped out. Everything else is just
gone.

As a result, though, that's no longer a static list. It has to be derived from information sent via
the API.  So now it's in a context that's built when the wizard is initialized, and accessed by the
`createTypes` pass as well as the specific provider.

The error handling in the `commit` pass was just broken.  I have improved it quite a bit, and now it
actually displays helpful messages when things go wrong.

### Tests

Wrote a simple test runner that iterates through a collection of fields, setting their values via
field-type instructions contained in each line. For example, the "simple" OAuth2 Provider test looks
like this:

```
export const simpleOAuth2ProviderForm: TestProvider = () => [
    [setTypeCreate, "selectProviderType", "OAuth2/OpenID Provider"],
    [clickButton, "Next"],
    [setTextInput, "name", newObjectName("New Oauth2 Provider")],
    [setSearchSelect, "authorizationFlow", /default-provider-authorization-explicit-consent/],
];
```

Each control checks for the existence of the object, and in most cases its current `display`.
(SearchSelect only checks existence, due to the oddness of the portaled popup.)  Where a field can't
reasonably be modified and still pass, we at least verify that the name provided in `schema.yml`
corresponds to an existing, available control on the form or wizard panel.

Combined with a routine for logging in and navigating to the Provider page, and another one to
validate that a new and uniqute "Successfully Created Provider" notification appeared, this makes
testing each provider a simple message of filling out the table of fields you want populated.

Equally simple: these *exact same tests* can be incorporated into a wrapper for logging in,
navigating to the Application page, and filling out an Application, and then a new and unique
Provider for that Application, by Provider Type.

As a special case, the Wizard variant checks the `TestSequence` object returned by the
`TestProvider` function and removes the `name` field, since the Wizard pre-populates that
automatically.

As a result of this, the contents of `./web/src` has lost 1,504 lines of code. And results like
these, where the behavior has been cross-checked three ways (the forms, the tests (and so the
back-end), *and the schema* all agree on field names and behaviors, gives me much more confidence
that the refactor works as expected:

```
[chrome 130.0.6723.70 mac #0-1] Running: chrome (v130.0.6723.70) on mac
[chrome 130.0.6723.70 mac #0-1] Session ID: 039c70690eebc83ffbc2eef97043c774
[chrome 130.0.6723.70 mac #0-1]
[chrome 130.0.6723.70 mac #0-1] » /tests/specs/providers.ts
[chrome 130.0.6723.70 mac #0-1] Configuring Providers
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple LDAP provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple OAuth2 provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple Radius provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple SAML provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple SCIM provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple Proxy provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple Forward Auth (single application) provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Simple Forward Auth (domain level) provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete OAuth2 provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete LDAP provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete Radius provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete SAML provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete SCIM provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete Proxy provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete Forward Auth (single application) provider
[chrome 130.0.6723.70 mac #0-1]    ✓ Should successfully configure a Complete Forward Auth (domain level) provider
[chrome 130.0.6723.70 mac #0-1]
[chrome 130.0.6723.70 mac #0-1] 16 passing (1m 48.5s)
------------------------------------------------------------------
[chrome 130.0.6723.70 mac #0-2] Running: chrome (v130.0.6723.70) on mac
[chrome 130.0.6723.70 mac #0-2] Session ID: 5a3ae12c851eff8fffd2686096759146
[chrome 130.0.6723.70 mac #0-2]
[chrome 130.0.6723.70 mac #0-2] » /tests/specs/new-application-by-wizard.ts
[chrome 130.0.6723.70 mac #0-2] Configuring Applications Via the Wizard
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple LDAP provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple OAuth2 provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple Radius provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple SAML provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple SCIM provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple Proxy provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple Forward Auth (single) provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Simple Forward Auth (domain) provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete OAuth2 provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete LDAP provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete Radius provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete SAML provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete SCIM provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete Proxy provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete Forward Auth (single) provider
[chrome 130.0.6723.70 mac #0-2]    ✓ Should successfully configure an application with a Complete Forward Auth (domain) provider
[chrome 130.0.6723.70 mac #0-2]
[chrome 130.0.6723.70 mac #0-2] 16 passing (2m 3s)
```

🎉
2024-10-29 15:50:51 -07:00
8601638831 web/admin: fix code-based MFA toggle not working in wizard (#11854)
closes #11834

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-10-29 20:18:49 +01:00
c38adcf25a sources/kerberos: add kiprop to ignored system principals (#11852) 2024-10-29 17:30:33 +01:00
ce92f77372 translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11846)
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>
2024-10-29 16:01:08 +01:00
ceb702b19e translate: Updates for file locale/en/LC_MESSAGES/django.po in it (#11845)
Translate locale/en/LC_MESSAGES/django.po in it

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-29 16:00:36 +01:00
c445fbf544 translate: Updates for file web/xliff/en.xlf in zh_CN (#11847)
Translate web/xliff/en.xlf in zh_CN

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-29 16:00:17 +01:00
087fa4306f translate: Updates for file web/xliff/en.xlf in zh-Hans (#11848)
Translate web/xliff/en.xlf in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-29 16:00:03 +01:00
88b90a365c translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11849)
Translate django.po in zh-Hans

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-29 15:59:48 +01:00
626a5397ca translate: Updates for file web/xliff/en.xlf in it (#11850)
Translate web/xliff/en.xlf in it

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-29 15:59:34 +01:00
5bd7cedaba Merge branch 'main' into web/update-provider-forms-for-invalidation
* main: (22 commits)
  lifecycle: fix missing krb5 deps for full testing in image (#11815)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#11810)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#11809)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#11808)
  web: bump API Client version (#11807)
  core: bump goauthentik.io/api/v3 from 3.2024083.12 to 3.2024083.13 (#11806)
  core: bump ruff from 0.7.0 to 0.7.1 (#11805)
  core: bump twilio from 9.3.4 to 9.3.5 (#11804)
  core, web: update translations (#11803)
  providers/scim: handle no members in group in consistency check (#11801)
  stages/identification: add captcha to identification stage (#11711)
  website/docs: improve root page and redirect (#11798)
  providers/scim: clamp batch size for patch requests (#11797)
  web/admin: fix missing div in wizard forms (#11794)
  providers/proxy: fix handling of AUTHENTIK_HOST_BROWSER (#11722)
  core, web: update translations (#11789)
  core: bump goauthentik.io/api/v3 from 3.2024083.11 to 3.2024083.12 (#11790)
  core: bump gssapi from 1.8.3 to 1.9.0 (#11791)
  web: bump API Client version (#11792)
  stages/authenticator_validate: autoselect last used 2fa device (#11087)
  ...
2024-10-28 09:37:16 -07:00
cace69d6f8 website: 2024.10 Release Notes (#11839)
* generate diffs and changelog

* add 2024.10 release notes

* reorder release note highlights

* lint website

* reorder release note new features

* reword Kerberos

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

* extend JWE description

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

---------

Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2024-10-28 16:13:31 +00:00
5d1e7a847a translate: Updates for file web/xliff/en.xlf in zh-Hans (#11814)
* Translate web/xliff/en.xlf in zh-Hans

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

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

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

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2024-10-28 15:28:33 +01:00
d27d222ab3 core, web: update translations (#11821)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2024-10-28 13:23:12 +01:00
b16e1e7f96 core: bump goauthentik.io/api/v3 from 3.2024083.13 to 3.2024083.14 (#11830)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2024083.13 to 3.2024083.14.
- [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.2024083.13...v3.2024083.14)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-28 13:23:01 +01:00
c0128945e3 core: bump service-identity from 24.1.0 to 24.2.0 (#11831)
Bumps [service-identity](https://github.com/sponsors/hynek) from 24.1.0 to 24.2.0.
- [Commits](https://github.com/sponsors/hynek/commits)

---
updated-dependencies:
- dependency-name: service-identity
  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>
2024-10-28 13:22:50 +01:00
5447c2e78e core: bump twilio from 9.3.5 to 9.3.6 (#11832)
Bumps [twilio](https://github.com/twilio/twilio-python) from 9.3.5 to 9.3.6.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/9.3.5...9.3.6)

---
updated-dependencies:
- dependency-name: twilio
  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>
2024-10-28 13:22:33 +01:00
15f173d8d4 core: bump pytest-randomly from 3.15.0 to 3.16.0 (#11833)
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.15.0 to 3.16.0.
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.15.0...3.16.0)

---
updated-dependencies:
- dependency-name: pytest-randomly
  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>
2024-10-28 13:21:27 +01:00
b533f416b8 website/docs: Update social-logins github (#11822)
Update index.md

Signed-off-by: Tobias <5702338+T0biii@users.noreply.github.com>
2024-10-28 13:04:54 +01:00
57dc595cfb website/docs: remove � (#11823)
remove 

Signed-off-by: Tobias <5702338+T0biii@users.noreply.github.com>
2024-10-28 13:04:38 +01:00
88a90e241a lifecycle: fix kdc5-config missing (#11826)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-10-27 21:26:55 +01:00
eac3e88126 website/docs: update preview status of different features (#11817)
* remove preview from RAC

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

* add preview page instead of info box

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

* remove preview from rbac

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

* add preview to gdtc

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

* add preview to kerberos source

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-10-25 21:37:20 +02:00
c0814ad279 Almost there! 2024-10-25 10:27:06 -07:00
abfc907ad6 lifecycle: fix missing krb5 deps for full testing in image (#11815)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-10-25 18:42:54 +02:00
99af95b10c Committed harmony on SAML. Streamlined the tests even further. 2024-10-24 09:35:31 -07:00
a36cc820bd Radius form has been isolated. 2024-10-23 15:24:47 -07:00
6ff260df01 Merge branch 'main' into web/update-provider-forms-for-invalidation
* main:
  web/admin: Add InvalidationFlow to Radius Provider dialogues (#11786)
  core, web: update translations (#11782)
  providers/oauth2: fix amr claim not set due to login event not associated (#11780)
2024-10-23 14:45:21 -07:00
e497dbc314 Merge branch 'main' into web/update-provider-forms-for-invalidation
* main: (44 commits)
  web/admin: add strict dompurify config for diagram (#11783)
  core: bump cryptography from 43.0.1 to 43.0.3 (#11750)
  web: bump API Client version (#11781)
  sources: add Kerberos (#10815)
  root: rework CSRF middleware to set secure flag (#11753)
  web/admin: improve invalidation flow default & field grouping (#11769)
  providers/scim: add comparison with existing group on update and delta update users (#11414)
  website: bump mermaid from 10.6.0 to 10.9.3 in /website (#11766)
  web/flows: use dompurify for footer links (#11773)
  core, web: update translations (#11775)
  core: bump goauthentik.io/api/v3 from 3.2024083.10 to 3.2024083.11 (#11776)
  website: bump @types/react from 18.3.11 to 18.3.12 in /website (#11777)
  website: bump http-proxy-middleware from 2.0.6 to 2.0.7 in /website (#11771)
  web: bump API Client version (#11770)
  stages: authenticator_endpoint_gdtc (#10477)
  core: add prompt_data to auth flow (#11702)
  tests/e2e: fix dex tests failing (#11761)
  web/rac: disable DPI scaling (#11757)
  web/admin: update flow background (#11758)
  website/docs: fix some broken links (#11742)
  ...
2024-10-23 14:00:31 -07:00
f9f849574b We have working tests!!!!!! 2024-10-23 10:50:27 -07:00
4439b298bd Still trying to find components by internal text. Still not working. 2024-10-22 14:21:16 -07:00
4af6ecf629 web: Isolate the OAuth2 Provider Form into a reusable rendering function
- Pull the OAuth2 Provider Form `render()` method out into a standalone function.
  - Why: So it can be shared by both the Wizard and the Provider function. The renderer is (or at
    least, can be) a pure function: you give it input and it produces HTML, *and then it stops*.
- Provide a test harness that can test the OAuth2 provider form.
2024-10-22 07:13:04 -07:00
282 changed files with 31496 additions and 10532 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2024.8.3
current_version = 2024.10.4
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?

View File

@ -116,7 +116,7 @@ jobs:
poetry run make test
poetry run coverage xml
- if: ${{ always() }}
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
flags: unit
token: ${{ secrets.CODECOV_TOKEN }}
@ -140,7 +140,7 @@ jobs:
poetry run coverage run manage.py test tests/integration
poetry run coverage xml
- if: ${{ always() }}
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
flags: integration
token: ${{ secrets.CODECOV_TOKEN }}
@ -198,7 +198,7 @@ jobs:
poetry run coverage run manage.py test ${{ matrix.job.glob }}
poetry run coverage xml
- if: ${{ always() }}
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
flags: e2e
token: ${{ secrets.CODECOV_TOKEN }}

View File

@ -80,7 +80,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
go build -o /go/authentik ./cmd/server
# Stage 4: MaxMind GeoIP
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.0.1 AS geoip
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN"
ENV GEOIPUPDATE_VERBOSE="1"

View File

@ -18,10 +18,10 @@ Even if the issue is not a CVE, we still greatly appreciate your help in hardeni
(.x being the latest patch release for each version)
| Version | Supported |
| -------- | --------- |
| 2024.6.x | ✅ |
| 2024.8.x | ✅ |
| Version | Supported |
| --------- | --------- |
| 2024.8.x | ✅ |
| 2024.10.x | ✅ |
## Reporting a Vulnerability

View File

@ -2,7 +2,7 @@
from os import environ
__version__ = "2024.8.3"
__version__ = "2024.10.4"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -7,7 +7,7 @@ API Browser - {{ brand.branding_title }}
{% endblock %}
{% block head %}
{% versioned_script "dist/standalone/api-browser/index-%v.js" %}
<script src="{% versioned_script 'dist/standalone/api-browser/index-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
{% endblock %}

View File

@ -27,7 +27,8 @@ def blueprint_tester(file_name: Path) -> Callable:
base = Path("blueprints/")
rel_path = Path(file_name).relative_to(base)
importer = Importer.from_string(BlueprintInstance(path=str(rel_path)).retrieve())
self.assertTrue(importer.validate()[0])
validation, logs = importer.validate()
self.assertTrue(validation, logs)
self.assertTrue(importer.apply())
return tester

View File

@ -293,7 +293,11 @@ class Importer:
serializer_kwargs = {}
model_instance = existing_models.first()
if not isinstance(model(), BaseMetaModel) and model_instance:
if (
not isinstance(model(), BaseMetaModel)
and model_instance
and entry.state != BlueprintEntryDesiredState.MUST_CREATED
):
self.logger.debug(
"Initialise serializer with instance",
model=model,
@ -303,11 +307,12 @@ class Importer:
serializer_kwargs["instance"] = model_instance
serializer_kwargs["partial"] = True
elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
msg = (
f"State is set to {BlueprintEntryDesiredState.MUST_CREATED.value} "
"and object exists already",
)
raise EntryInvalidError.from_entry(
(
f"State is set to {BlueprintEntryDesiredState.MUST_CREATED} "
"and object exists already",
),
ValidationError({k: msg for k in entry.identifiers.keys()}, "unique"),
entry,
)
else:

View File

@ -4,7 +4,7 @@ from collections.abc import Callable
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.utils.translation import activate
from django.utils.translation import override
from authentik.brands.utils import get_brand_for_request
@ -18,10 +18,12 @@ class BrandMiddleware:
self.get_response = get_response
def __call__(self, request: HttpRequest) -> HttpResponse:
locale_to_set = None
if not hasattr(request, "brand"):
brand = get_brand_for_request(request)
request.brand = brand
locale = brand.default_locale
if locale != "":
activate(locale)
return self.get_response(request)
locale_to_set = locale
with override(locale_to_set):
return self.get_response(request)

View File

@ -1,5 +1,6 @@
"""Authenticator Devices API Views"""
from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, extend_schema
from rest_framework.fields import (
@ -40,7 +41,11 @@ class DeviceSerializer(MetaNameSerializer):
def get_extra_description(self, instance: Device) -> str:
"""Get extra description"""
if isinstance(instance, WebAuthnDevice):
return instance.device_type.description
return (
instance.device_type.description
if instance.device_type
else _("Extra description not available")
)
if isinstance(instance, EndpointDevice):
return instance.data.get("deviceSignals", {}).get("deviceModel")
return ""

View File

@ -1,10 +1,12 @@
"""transactional application and provider creation"""
from django.apps import apps
from django.db.models import Model
from django.utils.translation import gettext as _
from drf_spectacular.utils import PolymorphicProxySerializer, extend_schema, extend_schema_field
from rest_framework.exceptions import ValidationError
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework.fields import BooleanField, CharField, ChoiceField, DictField, ListField
from rest_framework.permissions import IsAdminUser
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
@ -22,6 +24,7 @@ from authentik.core.api.applications import ApplicationSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import Provider
from authentik.lib.utils.reflection import all_subclasses
from authentik.policies.api.bindings import PolicyBindingSerializer
def get_provider_serializer_mapping():
@ -45,6 +48,13 @@ class TransactionProviderField(DictField):
"""Dictionary field which can hold provider creation data"""
class TransactionPolicyBindingSerializer(PolicyBindingSerializer):
"""PolicyBindingSerializer which does not require target as target is set implicitly"""
class Meta(PolicyBindingSerializer.Meta):
fields = [x for x in PolicyBindingSerializer.Meta.fields if x != "target"]
class TransactionApplicationSerializer(PassiveSerializer):
"""Serializer for creating a provider and an application in one transaction"""
@ -52,6 +62,8 @@ class TransactionApplicationSerializer(PassiveSerializer):
provider_model = ChoiceField(choices=list(get_provider_serializer_mapping().keys()))
provider = TransactionProviderField()
policy_bindings = TransactionPolicyBindingSerializer(many=True, required=False)
_provider_model: type[Provider] = None
def validate_provider_model(self, fq_model_name: str) -> str:
@ -96,6 +108,19 @@ class TransactionApplicationSerializer(PassiveSerializer):
id="app",
)
)
for binding in attrs.get("policy_bindings", []):
binding["target"] = KeyOf(None, ScalarNode(tag="", value="app"))
for key, value in binding.items():
if not isinstance(value, Model):
continue
binding[key] = value.pk
blueprint.entries.append(
BlueprintEntry(
model="authentik_policies.policybinding",
state=BlueprintEntryDesiredState.MUST_CREATED,
identifiers=binding,
)
)
importer = Importer(blueprint, {})
try:
valid, _ = importer.validate(raise_validation_errors=True)
@ -120,8 +145,7 @@ class TransactionApplicationResponseSerializer(PassiveSerializer):
class TransactionalApplicationView(APIView):
"""Create provider and application and attach them in a single transaction"""
# TODO: Migrate to a more specific permission
permission_classes = [IsAdminUser]
permission_classes = [IsAuthenticated]
@extend_schema(
request=TransactionApplicationSerializer(),
@ -133,8 +157,23 @@ class TransactionalApplicationView(APIView):
"""Convert data into a blueprint, validate it and apply it"""
data = TransactionApplicationSerializer(data=request.data)
data.is_valid(raise_exception=True)
importer = Importer(data.validated_data, {})
blueprint: Blueprint = data.validated_data
for entry in blueprint.entries:
full_model = entry.get_model(blueprint)
app, __, model = full_model.partition(".")
if not request.user.has_perm(f"{app}.add_{model}"):
raise PermissionDenied(
{
entry.id: _(
"User lacks permission to create {model}".format_map(
{
"model": full_model,
}
)
)
}
)
importer = Importer(blueprint, {})
applied = importer.apply()
response = {"applied": False, "logs": []}
response["applied"] = applied

View File

@ -666,7 +666,12 @@ class UserViewSet(UsedByMixin, ModelViewSet):
@permission_required("authentik_core.impersonate")
@extend_schema(
request=OpenApiTypes.NONE,
request=inline_serializer(
"ImpersonationSerializer",
{
"reason": CharField(required=True),
},
),
responses={
"204": OpenApiResponse(description="Successfully started impersonation"),
"401": OpenApiResponse(description="Access denied"),
@ -679,6 +684,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
LOGGER.debug("User attempted to impersonate", user=request.user)
return Response(status=401)
user_to_be = self.get_object()
reason = request.data.get("reason", "")
# Check both object-level perms and global perms
if not request.user.has_perm(
"authentik_core.impersonate", user_to_be
@ -688,11 +694,16 @@ class UserViewSet(UsedByMixin, ModelViewSet):
if user_to_be.pk == self.request.user.pk:
LOGGER.debug("User attempted to impersonate themselves", user=request.user)
return Response(status=401)
if not reason and request.tenant.impersonation_require_reason:
LOGGER.debug(
"User attempted to impersonate without providing a reason", user=request.user
)
return Response(status=401)
request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER] = request.user
request.session[SESSION_KEY_IMPERSONATE_USER] = user_to_be
Event.new(EventAction.IMPERSONATION_STARTED).from_http(request, user_to_be)
Event.new(EventAction.IMPERSONATION_STARTED, reason=reason).from_http(request, user_to_be)
return Response(status=201)

View File

@ -5,7 +5,7 @@ from contextvars import ContextVar
from uuid import uuid4
from django.http import HttpRequest, HttpResponse
from django.utils.translation import activate
from django.utils.translation import override
from sentry_sdk.api import set_tag
from structlog.contextvars import STRUCTLOG_KEY_PREFIX
@ -31,17 +31,19 @@ class ImpersonateMiddleware:
def __call__(self, request: HttpRequest) -> HttpResponse:
# No permission checks are done here, they need to be checked before
# SESSION_KEY_IMPERSONATE_USER is set.
locale_to_set = None
if request.user.is_authenticated:
locale = request.user.locale(request)
if locale != "":
activate(locale)
locale_to_set = locale
if SESSION_KEY_IMPERSONATE_USER in request.session:
request.user = request.session[SESSION_KEY_IMPERSONATE_USER]
# Ensure that the user is active, otherwise nothing will work
request.user.is_active = True
return self.get_response(request)
with override(locale_to_set):
return self.get_response(request)
class RequestIDMiddleware:

View File

@ -129,6 +129,11 @@ class SourceFlowManager:
)
new_connection.user = self.request.user
new_connection = self.update_user_connection(new_connection, **kwargs)
if existing := self.user_connection_type.objects.filter(
source=self.source, identifier=self.identifier
).first():
existing = self.update_user_connection(existing)
return Action.AUTH, existing
return Action.LINK, new_connection
action, connection = self.matcher.get_user_action(self.identifier, self.user_properties)

View File

@ -15,8 +15,8 @@
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
{% versioned_script "dist/poly-%v.js" %}
{% versioned_script "dist/standalone/loading/index-%v.js" %}
<script src="{% versioned_script 'dist/poly-%v.js' %}" type="module"></script>
<script src="{% versioned_script 'dist/standalone/loading/index-%v.js' %}" type="module"></script>
{% block head %}
{% endblock %}
<meta name="sentry-trace" content="{{ sentry_trace }}" />

View File

@ -3,7 +3,7 @@
{% load authentik_core %}
{% block head %}
{% versioned_script "dist/admin/AdminInterface-%v.js" %}
<script src="{% versioned_script 'dist/admin/AdminInterface-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
{% include "base/header_js.html" %}

View File

@ -3,7 +3,7 @@
{% load authentik_core %}
{% block head %}
{% versioned_script "dist/user/UserInterface-%v.js" %}
<script src="{% versioned_script 'dist/user/UserInterface-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
{% include "base/header_js.html" %}

View File

@ -2,7 +2,6 @@
from django import template
from django.templatetags.static import static as static_loader
from django.utils.safestring import mark_safe
from authentik import get_full_version
@ -12,10 +11,4 @@ register = template.Library()
@register.simple_tag()
def versioned_script(path: str) -> str:
"""Wrapper around {% static %} tag that supports setting the version"""
returned_lines = [
(
f'<script src="{static_loader(path.replace("%v", get_full_version()))}'
'" type="module"></script>'
),
]
return mark_safe("".join(returned_lines)) # nosec
return static_loader(path.replace("%v", get_full_version()))

View File

@ -12,7 +12,7 @@ from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.lib.generators import generate_id
from authentik.policies.dummy.models import DummyPolicy
from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.models import OAuth2Provider
from authentik.providers.oauth2.models import OAuth2Provider, RedirectURI, RedirectURIMatchingMode
from authentik.providers.proxy.models import ProxyProvider
from authentik.providers.saml.models import SAMLProvider
@ -24,7 +24,7 @@ class TestApplicationsAPI(APITestCase):
self.user = create_test_admin_user()
self.provider = OAuth2Provider.objects.create(
name="test",
redirect_uris="http://some-other-domain",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://some-other-domain")],
authorization_flow=create_test_flow(),
)
self.allowed: Application = Application.objects.create(

View File

@ -29,7 +29,8 @@ class TestImpersonation(APITestCase):
reverse(
"authentik_api:user-impersonate",
kwargs={"pk": self.other_user.pk},
)
),
data={"reason": "some reason"},
)
response = self.client.get(reverse("authentik_api:user-me"))
@ -55,7 +56,8 @@ class TestImpersonation(APITestCase):
reverse(
"authentik_api:user-impersonate",
kwargs={"pk": self.other_user.pk},
)
),
data={"reason": "some reason"},
)
self.assertEqual(response.status_code, 201)
@ -75,7 +77,8 @@ class TestImpersonation(APITestCase):
reverse(
"authentik_api:user-impersonate",
kwargs={"pk": self.other_user.pk},
)
),
data={"reason": "some reason"},
)
self.assertEqual(response.status_code, 201)
@ -89,7 +92,8 @@ class TestImpersonation(APITestCase):
self.client.force_login(self.other_user)
response = self.client.post(
reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk})
reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk}),
data={"reason": "some reason"},
)
self.assertEqual(response.status_code, 403)
@ -105,7 +109,8 @@ class TestImpersonation(APITestCase):
self.client.force_login(self.user)
response = self.client.post(
reverse("authentik_api:user-impersonate", kwargs={"pk": self.other_user.pk})
reverse("authentik_api:user-impersonate", kwargs={"pk": self.other_user.pk}),
data={"reason": "some reason"},
)
self.assertEqual(response.status_code, 401)
@ -118,7 +123,22 @@ class TestImpersonation(APITestCase):
self.client.force_login(self.user)
response = self.client.post(
reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk})
reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk}),
data={"reason": "some reason"},
)
self.assertEqual(response.status_code, 401)
response = self.client.get(reverse("authentik_api:user-me"))
response_body = loads(response.content.decode())
self.assertEqual(response_body["user"]["username"], self.user.username)
def test_impersonate_reason_required(self):
"""test impersonation that user must provide reason"""
self.client.force_login(self.user)
response = self.client.post(
reverse("authentik_api:user-impersonate", kwargs={"pk": self.user.pk}),
data={"reason": ""},
)
self.assertEqual(response.status_code, 401)

View File

@ -81,6 +81,22 @@ class TestSourceFlowManager(TestCase):
reverse("authentik_core:if-user") + "#/settings;page-sources",
)
def test_authenticated_auth(self):
"""Test authenticated user linking"""
user = User.objects.create(username="foo", email="foo@bar.baz")
UserOAuthSourceConnection.objects.create(
user=user, source=self.source, identifier=self.identifier
)
request = get_request("/", user=user)
flow_manager = OAuthSourceFlowManager(
self.source, request, self.identifier, {"info": {}}, {}
)
action, connection = flow_manager.get_action()
self.assertEqual(action, Action.AUTH)
self.assertIsNotNone(connection.pk)
response = flow_manager.get_flow()
self.assertEqual(response.status_code, 302)
def test_unauthenticated_link(self):
"""Test un-authenticated user linking"""
flow_manager = OAuthSourceFlowManager(

View File

@ -1,11 +1,13 @@
"""Test Transactional API"""
from django.urls import reverse
from guardian.shortcuts import assign_perm
from rest_framework.test import APITestCase
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.core.models import Application, Group
from authentik.core.tests.utils import create_test_flow, create_test_user
from authentik.lib.generators import generate_id
from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.models import OAuth2Provider
@ -13,7 +15,9 @@ class TestTransactionalApplicationsAPI(APITestCase):
"""Test Transactional API"""
def setUp(self) -> None:
self.user = create_test_admin_user()
self.user = create_test_user()
assign_perm("authentik_core.add_application", self.user)
assign_perm("authentik_providers_oauth2.add_oauth2provider", self.user)
def test_create_transactional(self):
"""Test transactional Application + provider creation"""
@ -31,6 +35,7 @@ class TestTransactionalApplicationsAPI(APITestCase):
"name": uid,
"authorization_flow": str(create_test_flow().pk),
"invalidation_flow": str(create_test_flow().pk),
"redirect_uris": [],
},
},
)
@ -41,6 +46,66 @@ class TestTransactionalApplicationsAPI(APITestCase):
self.assertIsNotNone(app)
self.assertEqual(app.provider.pk, provider.pk)
def test_create_transactional_permission_denied(self):
"""Test transactional Application + provider creation (missing permissions)"""
self.client.force_login(self.user)
uid = generate_id()
response = self.client.put(
reverse("authentik_api:core-transactional-application"),
data={
"app": {
"name": uid,
"slug": uid,
},
"provider_model": "authentik_providers_saml.samlprovider",
"provider": {
"name": uid,
"authorization_flow": str(create_test_flow().pk),
"invalidation_flow": str(create_test_flow().pk),
"acs_url": "https://goauthentik.io",
},
},
)
self.assertJSONEqual(
response.content.decode(),
{"provider": "User lacks permission to create authentik_providers_saml.samlprovider"},
)
def test_create_transactional_bindings(self):
"""Test transactional Application + provider creation"""
assign_perm("authentik_policies.add_policybinding", self.user)
self.client.force_login(self.user)
uid = generate_id()
group = Group.objects.create(name=generate_id())
authorization_flow = create_test_flow()
response = self.client.put(
reverse("authentik_api:core-transactional-application"),
data={
"app": {
"name": uid,
"slug": uid,
},
"provider_model": "authentik_providers_oauth2.oauth2provider",
"provider": {
"name": uid,
"authorization_flow": str(authorization_flow.pk),
"invalidation_flow": str(authorization_flow.pk),
"redirect_uris": [],
},
"policy_bindings": [{"group": group.pk, "order": 0}],
},
)
self.assertJSONEqual(response.content.decode(), {"applied": True, "logs": []})
provider = OAuth2Provider.objects.filter(name=uid).first()
self.assertIsNotNone(provider)
app = Application.objects.filter(slug=uid).first()
self.assertIsNotNone(app)
self.assertEqual(app.provider.pk, provider.pk)
binding = PolicyBinding.objects.filter(target=app).first()
self.assertIsNotNone(binding)
self.assertEqual(binding.target, app)
self.assertEqual(binding.group, group)
def test_create_transactional_invalid(self):
"""Test transactional Application + provider creation"""
self.client.force_login(self.user)
@ -57,6 +122,7 @@ class TestTransactionalApplicationsAPI(APITestCase):
"name": uid,
"authorization_flow": "",
"invalidation_flow": "",
"redirect_uris": [],
},
},
)
@ -69,3 +135,32 @@ class TestTransactionalApplicationsAPI(APITestCase):
}
},
)
def test_create_transactional_duplicate_name_provider(self):
"""Test transactional Application + provider creation"""
self.client.force_login(self.user)
uid = generate_id()
OAuth2Provider.objects.create(
name=uid,
authorization_flow=create_test_flow(),
invalidation_flow=create_test_flow(),
)
response = self.client.put(
reverse("authentik_api:core-transactional-application"),
data={
"app": {
"name": uid,
"slug": uid,
},
"provider_model": "authentik_providers_oauth2.oauth2provider",
"provider": {
"name": uid,
"authorization_flow": str(create_test_flow().pk),
"invalidation_flow": str(create_test_flow().pk),
},
},
)
self.assertJSONEqual(
response.content.decode(),
{"provider": {"name": ["State is set to must_created and object exists already"]}},
)

View File

@ -24,6 +24,7 @@ from rest_framework.fields import (
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
@ -181,7 +182,10 @@ class CertificateDataSerializer(PassiveSerializer):
class CertificateGenerationSerializer(PassiveSerializer):
"""Certificate generation parameters"""
common_name = CharField()
common_name = CharField(
validators=[UniqueValidator(queryset=CertificateKeyPair.objects.all())],
source="name",
)
subject_alt_name = CharField(required=False, allow_blank=True, label=_("Subject-alt name"))
validity_days = IntegerField(initial=365)
alg = ChoiceField(default=PrivateKeyAlg.RSA, choices=PrivateKeyAlg.choices)
@ -242,11 +246,10 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet):
def generate(self, request: Request) -> Response:
"""Generate a new, self-signed certificate-key pair"""
data = CertificateGenerationSerializer(data=request.data)
if not data.is_valid():
return Response(data.errors, status=400)
data.is_valid(raise_exception=True)
raw_san = data.validated_data.get("subject_alt_name", "")
sans = raw_san.split(",") if raw_san != "" else []
builder = CertificateBuilder(data.validated_data["common_name"])
builder = CertificateBuilder(data.validated_data["name"])
builder.alg = data.validated_data["alg"]
builder.build(
subject_alt_names=sans,

View File

@ -18,7 +18,7 @@ from authentik.crypto.models import CertificateKeyPair
from authentik.crypto.tasks import MANAGED_DISCOVERED, certificate_discovery
from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id, generate_key
from authentik.providers.oauth2.models import OAuth2Provider
from authentik.providers.oauth2.models import OAuth2Provider, RedirectURI, RedirectURIMatchingMode
class TestCrypto(APITestCase):
@ -89,6 +89,17 @@ class TestCrypto(APITestCase):
self.assertIsInstance(ext[1], DNSName)
self.assertEqual(ext[1].value, "baz")
def test_builder_api_duplicate(self):
"""Test Builder (via API)"""
cert = create_test_cert()
self.client.force_login(create_test_admin_user())
res = self.client.post(
reverse("authentik_api:certificatekeypair-generate"),
data={"common_name": cert.name, "subject_alt_name": "bar,baz", "validity_days": 3},
)
self.assertEqual(res.status_code, 400)
self.assertJSONEqual(res.content, {"common_name": ["This field must be unique."]})
def test_builder_api_empty_san(self):
"""Test Builder (via API)"""
self.client.force_login(create_test_admin_user())
@ -263,7 +274,7 @@ class TestCrypto(APITestCase):
client_id="test",
client_secret=generate_key(),
authorization_flow=create_test_flow(),
redirect_uris="http://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
signing_key=keypair,
)
response = self.client.get(
@ -295,7 +306,7 @@ class TestCrypto(APITestCase):
client_id="test",
client_secret=generate_key(),
authorization_flow=create_test_flow(),
redirect_uris="http://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
signing_key=keypair,
)
response = self.client.get(

View File

@ -16,13 +16,28 @@ class RACProviderSerializer(EnterpriseRequiredMixin, ProviderSerializer):
class Meta:
model = RACProvider
fields = ProviderSerializer.Meta.fields + [
fields = [
"pk",
"name",
"authentication_flow",
"authorization_flow",
"property_mappings",
"component",
"assigned_application_slug",
"assigned_application_name",
"assigned_backchannel_application_slug",
"assigned_backchannel_application_name",
"verbose_name",
"verbose_name_plural",
"meta_model_name",
"settings",
"outpost_set",
"connection_expiry",
"delete_token_on_disconnect",
]
extra_kwargs = ProviderSerializer.Meta.extra_kwargs
extra_kwargs = {
"authorization_flow": {"required": True, "allow_null": False},
}
class RACProviderViewSet(UsedByMixin, ModelViewSet):

View File

@ -3,7 +3,7 @@
{% load authentik_core %}
{% block head %}
{% versioned_script "dist/enterprise/rac/index-%v.js" %}
<script src="{% versioned_script 'dist/enterprise/rac/index-%v.js' %}" type="module"></script>
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<link rel="icon" href="{{ tenant.branding_favicon }}">

View File

@ -0,0 +1,46 @@
"""Test RAC Provider"""
from datetime import timedelta
from time import mktime
from unittest.mock import MagicMock, patch
from django.urls import reverse
from django.utils.timezone import now
from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.enterprise.license import LicenseKey
from authentik.enterprise.models import License
from authentik.lib.generators import generate_id
class TestAPI(APITestCase):
"""Test Provider API"""
def setUp(self) -> None:
self.user = create_test_admin_user()
@patch(
"authentik.enterprise.license.LicenseKey.validate",
MagicMock(
return_value=LicenseKey(
aud="",
exp=int(mktime((now() + timedelta(days=3000)).timetuple())),
name=generate_id(),
internal_users=100,
external_users=100,
)
),
)
def test_create(self):
"""Test creation of RAC Provider"""
License.objects.create(key=generate_id())
self.client.force_login(self.user)
response = self.client.post(
reverse("authentik_api:racprovider-list"),
data={
"name": generate_id(),
"authorization_flow": create_test_flow().pk,
},
)
self.assertEqual(response.status_code, 201)

View File

@ -68,7 +68,6 @@ class TestEndpointsAPI(APITestCase):
"name": self.provider.name,
"authentication_flow": None,
"authorization_flow": None,
"invalidation_flow": None,
"property_mappings": [],
"connection_expiry": "hours=8",
"delete_token_on_disconnect": False,
@ -121,7 +120,6 @@ class TestEndpointsAPI(APITestCase):
"name": self.provider.name,
"authentication_flow": None,
"authorization_flow": None,
"invalidation_flow": None,
"property_mappings": [],
"component": "ak-provider-rac-form",
"assigned_application_slug": self.app.slug,
@ -151,7 +149,6 @@ class TestEndpointsAPI(APITestCase):
"name": self.provider.name,
"authentication_flow": None,
"authorization_flow": None,
"invalidation_flow": None,
"property_mappings": [],
"component": "ak-provider-rac-form",
"assigned_application_slug": self.app.slug,

View File

@ -60,7 +60,7 @@ def default_event_duration():
"""Default duration an Event is saved.
This is used as a fallback when no brand is available"""
try:
tenant = get_current_tenant()
tenant = get_current_tenant(only=["event_retention"])
return now() + timedelta_from_string(tenant.event_retention)
except Tenant.DoesNotExist:
return now() + timedelta(days=365)

View File

@ -18,7 +18,7 @@ window.authentik.flow = {
{% endblock %}
{% block head %}
{% versioned_script "dist/flow/FlowInterface-%v.js" %}
<script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script>
<style>
:root {
--ak-flow-background: url("{{ flow.background_url }}");

View File

@ -89,6 +89,10 @@ class PasswordPolicy(Policy):
def passes_static(self, password: str, request: PolicyRequest) -> PolicyResult:
"""Check static rules"""
error_message = self.error_message
if error_message == "":
error_message = _("Invalid password.")
if len(password) < self.length_min:
LOGGER.debug("password failed", check="static", reason="length")
return PolicyResult(False, self.error_message)

View File

@ -159,7 +159,10 @@ class LDAPOutpostConfigViewSet(ListModelMixin, GenericViewSet):
access_response = PolicyResult(result.passing)
response = self.LDAPCheckAccessSerializer(
instance={
"has_search_permission": request.user.has_perm("search_full_directory", provider),
"has_search_permission": (
request.user.has_perm("search_full_directory", provider)
or request.user.has_perm("authentik_providers_ldap.search_full_directory")
),
"access": access_response,
}
)

View File

@ -1,15 +1,18 @@
"""OAuth2Provider API Views"""
from copy import copy
from re import compile
from re import error as RegexError
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField
from rest_framework.fields import CharField, ChoiceField
from rest_framework.generics import get_object_or_404
from rest_framework.request import Request
from rest_framework.response import Response
@ -20,13 +23,39 @@ from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer, PropertyMappingPreviewSerializer
from authentik.core.models import Provider
from authentik.providers.oauth2.id_token import IDToken
from authentik.providers.oauth2.models import AccessToken, OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.models import (
AccessToken,
OAuth2Provider,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.rbac.decorators import permission_required
class RedirectURISerializer(PassiveSerializer):
"""A single allowed redirect URI entry"""
matching_mode = ChoiceField(choices=RedirectURIMatchingMode.choices)
url = CharField()
class OAuth2ProviderSerializer(ProviderSerializer):
"""OAuth2Provider Serializer"""
redirect_uris = RedirectURISerializer(many=True, source="_redirect_uris")
def validate_redirect_uris(self, data: list) -> list:
for entry in data:
if entry.get("matching_mode") == RedirectURIMatchingMode.REGEX:
url = entry.get("url")
try:
compile(url)
except RegexError:
raise ValidationError(
_("Invalid Regex Pattern: {url}".format(url=url))
) from None
return data
class Meta:
model = OAuth2Provider
fields = ProviderSerializer.Meta.fields + [
@ -79,7 +108,6 @@ class OAuth2ProviderViewSet(UsedByMixin, ModelViewSet):
"refresh_token_validity",
"include_claims_in_id_token",
"signing_key",
"redirect_uris",
"sub_mode",
"property_mappings",
"issuer_mode",

View File

@ -7,7 +7,7 @@ from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from authentik.events.models import Event, EventAction
from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.views import bad_request_message
from authentik.providers.oauth2.models import GrantTypes
from authentik.providers.oauth2.models import GrantTypes, RedirectURI
class OAuth2Error(SentryIgnoredException):
@ -46,9 +46,9 @@ class RedirectUriError(OAuth2Error):
)
provided_uri: str
allowed_uris: list[str]
allowed_uris: list[RedirectURI]
def __init__(self, provided_uri: str, allowed_uris: list[str]) -> None:
def __init__(self, provided_uri: str, allowed_uris: list[RedirectURI]) -> None:
super().__init__()
self.provided_uri = provided_uri
self.allowed_uris = allowed_uris

View File

@ -11,13 +11,16 @@ class Migration(migrations.Migration):
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddIndex(
model_name="accesstoken",
index=models.Index(fields=["token"], name="authentik_p_token_4bc870_idx"),
),
migrations.AddIndex(
model_name="refreshtoken",
index=models.Index(fields=["token"], name="authentik_p_token_1a841f_idx"),
),
]
# Original preserved
# See https://github.com/goauthentik/authentik/issues/11874
# operations = [
# migrations.AddIndex(
# model_name="accesstoken",
# index=models.Index(fields=["token"], name="authentik_p_token_4bc870_idx"),
# ),
# migrations.AddIndex(
# model_name="refreshtoken",
# index=models.Index(fields=["token"], name="authentik_p_token_1a841f_idx"),
# ),
# ]
operations = []

View File

@ -11,21 +11,24 @@ class Migration(migrations.Migration):
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveIndex(
model_name="accesstoken",
name="authentik_p_token_4bc870_idx",
),
migrations.RemoveIndex(
model_name="refreshtoken",
name="authentik_p_token_1a841f_idx",
),
migrations.AddIndex(
model_name="accesstoken",
index=models.Index(fields=["token", "provider"], name="authentik_p_token_f99422_idx"),
),
migrations.AddIndex(
model_name="refreshtoken",
index=models.Index(fields=["token", "provider"], name="authentik_p_token_a1d921_idx"),
),
]
# Original preserved
# See https://github.com/goauthentik/authentik/issues/11874
# operations = [
# migrations.RemoveIndex(
# model_name="accesstoken",
# name="authentik_p_token_4bc870_idx",
# ),
# migrations.RemoveIndex(
# model_name="refreshtoken",
# name="authentik_p_token_1a841f_idx",
# ),
# migrations.AddIndex(
# model_name="accesstoken",
# index=models.Index(fields=["token", "provider"], name="authentik_p_token_f99422_idx"),
# ),
# migrations.AddIndex(
# model_name="refreshtoken",
# index=models.Index(fields=["token", "provider"], name="authentik_p_token_a1d921_idx"),
# ),
# ]
operations = []

View File

@ -37,7 +37,7 @@ def migrate_session(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0040_provider_invalidation_flow"),
("authentik_core", "0039_source_group_matching_mode_alter_group_name_and_more"),
("authentik_providers_oauth2", "0021_oauth2provider_encryption_key_and_more"),
]

View File

@ -0,0 +1,31 @@
# Generated by Django 5.0.9 on 2024-10-31 14:28
import django.contrib.postgres.indexes
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0039_source_group_matching_mode_alter_group_name_and_more"),
("authentik_providers_oauth2", "0022_remove_accesstoken_session_id_and_more"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RunSQL("DROP INDEX IF EXISTS authentik_p_token_f99422_idx;"),
migrations.RunSQL("DROP INDEX IF EXISTS authentik_p_token_a1d921_idx;"),
migrations.AddIndex(
model_name="accesstoken",
index=django.contrib.postgres.indexes.HashIndex(
fields=["token"], name="authentik_p_token_e00883_hash"
),
),
migrations.AddIndex(
model_name="refreshtoken",
index=django.contrib.postgres.indexes.HashIndex(
fields=["token"], name="authentik_p_token_32e2b7_hash"
),
),
]

View File

@ -0,0 +1,49 @@
# Generated by Django 5.0.9 on 2024-11-04 12:56
from dataclasses import asdict
from django.apps.registry import Apps
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db import migrations, models
def migrate_redirect_uris(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
from authentik.providers.oauth2.models import RedirectURI, RedirectURIMatchingMode
OAuth2Provider = apps.get_model("authentik_providers_oauth2", "oauth2provider")
db_alias = schema_editor.connection.alias
for provider in OAuth2Provider.objects.using(db_alias).all():
uris = []
for old in provider.old_redirect_uris.split("\n"):
mode = RedirectURIMatchingMode.STRICT
if old == "*" or old == ".*":
mode = RedirectURIMatchingMode.REGEX
uris.append(asdict(RedirectURI(mode, url=old)))
provider._redirect_uris = uris
provider.save()
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_oauth2", "0023_alter_accesstoken_refreshtoken_use_hash_index"),
]
operations = [
migrations.RenameField(
model_name="oauth2provider",
old_name="redirect_uris",
new_name="old_redirect_uris",
),
migrations.AddField(
model_name="oauth2provider",
name="_redirect_uris",
field=models.JSONField(default=dict, verbose_name="Redirect URIs"),
),
migrations.RunPython(migrate_redirect_uris, lambda *args: ...),
migrations.RemoveField(
model_name="oauth2provider",
name="old_redirect_uris",
),
]

View File

@ -3,7 +3,7 @@
import base64
import binascii
import json
from dataclasses import asdict
from dataclasses import asdict, dataclass
from functools import cached_property
from hashlib import sha256
from typing import Any
@ -12,7 +12,9 @@ from urllib.parse import urlparse, urlunparse
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
from dacite import Config
from dacite.core import from_dict
from django.contrib.postgres.indexes import HashIndex
from django.db import models
from django.http import HttpRequest
from django.templatetags.static import static
@ -76,11 +78,25 @@ class IssuerMode(models.TextChoices):
"""Configure how the `iss` field is created."""
GLOBAL = "global", _("Same identifier is used for all providers")
PER_PROVIDER = "per_provider", _(
"Each provider has a different issuer, based on the application slug."
PER_PROVIDER = (
"per_provider",
_("Each provider has a different issuer, based on the application slug."),
)
class RedirectURIMatchingMode(models.TextChoices):
STRICT = "strict", _("Strict URL comparison")
REGEX = "regex", _("Regular Expression URL matching")
@dataclass
class RedirectURI:
"""A single redirect URI entry"""
matching_mode: RedirectURIMatchingMode
url: str
class ResponseTypes(models.TextChoices):
"""Response Type required by the client."""
@ -155,11 +171,9 @@ class OAuth2Provider(WebfingerProvider, Provider):
verbose_name=_("Client Secret"),
default=generate_client_secret,
)
redirect_uris = models.TextField(
default="",
blank=True,
_redirect_uris = models.JSONField(
default=dict,
verbose_name=_("Redirect URIs"),
help_text=_("Enter each URI on a new line."),
)
include_claims_in_id_token = models.BooleanField(
@ -270,12 +284,33 @@ class OAuth2Provider(WebfingerProvider, Provider):
except Provider.application.RelatedObjectDoesNotExist:
return None
@property
def redirect_uris(self) -> list[RedirectURI]:
uris = []
for entry in self._redirect_uris:
uris.append(
from_dict(
RedirectURI,
entry,
config=Config(type_hooks={RedirectURIMatchingMode: RedirectURIMatchingMode}),
)
)
return uris
@redirect_uris.setter
def redirect_uris(self, value: list[RedirectURI]):
cleansed = []
for entry in value:
cleansed.append(asdict(entry))
self._redirect_uris = cleansed
@property
def launch_url(self) -> str | None:
"""Guess launch_url based on first redirect_uri"""
if self.redirect_uris == "":
redirects = self.redirect_uris
if len(redirects) < 1:
return None
main_url = self.redirect_uris.split("\n", maxsplit=1)[0]
main_url = redirects[0].url
try:
launch_url = urlparse(main_url)._replace(path="")
return urlunparse(launch_url)
@ -418,7 +453,7 @@ class AccessToken(SerializerModel, ExpiringModel, BaseGrantModel):
class Meta:
indexes = [
models.Index(fields=["token", "provider"]),
HashIndex(fields=["token"]),
]
verbose_name = _("OAuth2 Access Token")
verbose_name_plural = _("OAuth2 Access Tokens")
@ -464,7 +499,7 @@ class RefreshToken(SerializerModel, ExpiringModel, BaseGrantModel):
class Meta:
indexes = [
models.Index(fields=["token", "provider"]),
HashIndex(fields=["token"]),
]
verbose_name = _("OAuth2 Refresh Token")
verbose_name_plural = _("OAuth2 Refresh Tokens")

View File

@ -10,7 +10,13 @@ from rest_framework.test import APITestCase
from authentik.blueprints.tests import apply_blueprint
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import (
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
class TestAPI(APITestCase):
@ -21,7 +27,7 @@ class TestAPI(APITestCase):
self.provider: OAuth2Provider = OAuth2Provider.objects.create(
name="test",
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
)
self.provider.property_mappings.set(ScopeMapping.objects.all())
self.app = Application.objects.create(name="test", slug="test", provider=self.provider)
@ -50,9 +56,29 @@ class TestAPI(APITestCase):
@skipUnless(version_info >= (3, 11, 4), "This behaviour is only Python 3.11.4 and up")
def test_launch_url(self):
"""Test launch_url"""
self.provider.redirect_uris = (
"https://[\\d\\w]+.pr.test.goauthentik.io/source/oauth/callback/authentik/\n"
)
self.provider.redirect_uris = [
RedirectURI(
RedirectURIMatchingMode.REGEX,
"https://[\\d\\w]+.pr.test.goauthentik.io/source/oauth/callback/authentik/",
),
]
self.provider.save()
self.provider.refresh_from_db()
self.assertIsNone(self.provider.launch_url)
def test_validate_redirect_uris(self):
"""Test redirect_uris API"""
response = self.client.post(
reverse("authentik_api:oauth2provider-list"),
data={
"name": generate_id(),
"authorization_flow": create_test_flow().pk,
"invalidation_flow": create_test_flow().pk,
"redirect_uris": [
{"matching_mode": "strict", "url": "http://goauthentik.io"},
{"matching_mode": "regex", "url": "**"},
],
},
)
self.assertJSONEqual(response.content, {"redirect_uris": ["Invalid Regex Pattern: **"]})
self.assertEqual(response.status_code, 400)

View File

@ -19,6 +19,8 @@ from authentik.providers.oauth2.models import (
AuthorizationCode,
GrantTypes,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -39,7 +41,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid/Foo",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid/Foo")],
)
with self.assertRaises(AuthorizeError):
request = self.factory.get(
@ -64,7 +66,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid/Foo",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid/Foo")],
)
with self.assertRaises(AuthorizeError):
request = self.factory.get(
@ -84,7 +86,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
@ -106,7 +108,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="data:local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "data:local.invalid")],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get(
@ -125,7 +127,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="",
redirect_uris=[],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
@ -140,7 +142,7 @@ class TestAuthorize(OAuthTestCase):
)
OAuthAuthorizationParams.from_request(request)
provider.refresh_from_db()
self.assertEqual(provider.redirect_uris, "+")
self.assertEqual(provider.redirect_uris, [RedirectURI(RedirectURIMatchingMode.STRICT, "+")])
def test_invalid_redirect_uri_regex(self):
"""test missing/invalid redirect URI"""
@ -148,7 +150,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid?",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid?")],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
@ -170,7 +172,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="+",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "+")],
)
with self.assertRaises(RedirectUriError):
request = self.factory.get("/", data={"response_type": "code", "client_id": "test"})
@ -213,7 +215,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid/Foo",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid/Foo")],
)
provider.property_mappings.set(
ScopeMapping.objects.filter(
@ -301,7 +303,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="foo://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "foo://localhost")],
access_code_validity="seconds=100",
)
Application.objects.create(name="app", slug="app", provider=provider)
@ -343,7 +345,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="http://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
signing_key=self.keypair,
)
provider.property_mappings.set(
@ -420,7 +422,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="http://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
signing_key=self.keypair,
encryption_key=self.keypair,
)
@ -486,7 +488,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="http://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
signing_key=self.keypair,
)
Application.objects.create(name="app", slug="app", provider=provider)
@ -541,7 +543,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id=generate_id(),
authorization_flow=flow,
redirect_uris="http://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
signing_key=self.keypair,
)
provider.property_mappings.set(
@ -599,7 +601,7 @@ class TestAuthorize(OAuthTestCase):
name=generate_id(),
client_id=generate_id(),
authorization_flow=flow,
redirect_uris="http://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://localhost")],
signing_key=self.keypair,
)
app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)

View File

@ -3,6 +3,7 @@
from urllib.parse import urlencode
from django.urls import reverse
from rest_framework.test import APIClient
from authentik.core.models import Application, Group
from authentik.core.tests.utils import create_test_admin_user, create_test_brand, create_test_flow
@ -34,7 +35,10 @@ class TesOAuth2DeviceInit(OAuthTestCase):
self.brand.flow_device_code = self.device_flow
self.brand.save()
def test_device_init(self):
self.api_client = APIClient()
self.api_client.force_login(self.user)
def test_device_init_get(self):
"""Test device init"""
res = self.client.get(reverse("authentik_providers_oauth2_root:device-login"))
self.assertEqual(res.status_code, 302)
@ -48,6 +52,76 @@ class TesOAuth2DeviceInit(OAuthTestCase):
),
)
def test_device_init_post(self):
"""Test device init"""
res = self.api_client.get(reverse("authentik_providers_oauth2_root:device-login"))
self.assertEqual(res.status_code, 302)
self.assertEqual(
res.url,
reverse(
"authentik_core:if-flow",
kwargs={
"flow_slug": self.device_flow.slug,
},
),
)
res = self.api_client.get(
reverse(
"authentik_api:flow-executor",
kwargs={
"flow_slug": self.device_flow.slug,
},
),
)
self.assertEqual(res.status_code, 200)
self.assertJSONEqual(
res.content,
{
"component": "ak-provider-oauth2-device-code",
"flow_info": {
"background": "/static/dist/assets/images/flow_background.jpg",
"cancel_url": "/flows/-/cancel/",
"layout": "stacked",
"title": self.device_flow.title,
},
},
)
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
)
Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider)
token = DeviceToken.objects.create(
provider=provider,
)
res = self.api_client.post(
reverse(
"authentik_api:flow-executor",
kwargs={
"flow_slug": self.device_flow.slug,
},
),
data={
"component": "ak-provider-oauth2-device-code",
"code": token.user_code,
},
)
self.assertEqual(res.status_code, 200)
self.assertJSONEqual(
res.content,
{
"component": "xak-flow-redirect",
"to": reverse(
"authentik_core:if-flow",
kwargs={
"flow_slug": provider.authorization_flow.slug,
},
),
},
)
def test_no_flow(self):
"""Test no flow"""
self.brand.flow_device_code = None

View File

@ -11,7 +11,14 @@ from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.constants import ACR_AUTHENTIK_DEFAULT
from authentik.providers.oauth2.models import AccessToken, IDToken, OAuth2Provider, RefreshToken
from authentik.providers.oauth2.models import (
AccessToken,
IDToken,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
RefreshToken,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -23,7 +30,7 @@ class TesOAuth2Introspection(OAuthTestCase):
self.provider: OAuth2Provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "")],
signing_key=create_test_cert(),
)
self.app = Application.objects.create(
@ -118,7 +125,7 @@ class TesOAuth2Introspection(OAuthTestCase):
provider: OAuth2Provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "")],
signing_key=create_test_cert(),
)
auth = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()

View File

@ -13,7 +13,7 @@ from authentik.core.tests.utils import create_test_cert, create_test_flow
from authentik.crypto.builder import PrivateKeyAlg
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import OAuth2Provider
from authentik.providers.oauth2.models import OAuth2Provider, RedirectURI, RedirectURIMatchingMode
from authentik.providers.oauth2.tests.utils import OAuthTestCase
TEST_CORDS_CERT = """
@ -49,7 +49,7 @@ class TestJWKS(OAuthTestCase):
name="test",
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=create_test_cert(),
)
app = Application.objects.create(name="test", slug="test", provider=provider)
@ -68,7 +68,7 @@ class TestJWKS(OAuthTestCase):
name="test",
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
)
app = Application.objects.create(name="test", slug="test", provider=provider)
response = self.client.get(
@ -82,7 +82,7 @@ class TestJWKS(OAuthTestCase):
name="test",
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=create_test_cert(PrivateKeyAlg.ECDSA),
)
app = Application.objects.create(name="test", slug="test", provider=provider)
@ -99,7 +99,7 @@ class TestJWKS(OAuthTestCase):
name="test",
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=create_test_cert(PrivateKeyAlg.ECDSA),
encryption_key=create_test_cert(PrivateKeyAlg.ECDSA),
)
@ -122,7 +122,7 @@ class TestJWKS(OAuthTestCase):
name="test",
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=cert,
)
app = Application.objects.create(name="test", slug="test", provider=provider)

View File

@ -10,7 +10,14 @@ from django.utils import timezone
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import AccessToken, IDToken, OAuth2Provider, RefreshToken
from authentik.providers.oauth2.models import (
AccessToken,
IDToken,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
RefreshToken,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -22,7 +29,7 @@ class TesOAuth2Revoke(OAuthTestCase):
self.provider: OAuth2Provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "")],
signing_key=create_test_cert(),
)
self.app = Application.objects.create(

View File

@ -22,6 +22,8 @@ from authentik.providers.oauth2.models import (
AccessToken,
AuthorizationCode,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
RefreshToken,
ScopeMapping,
)
@ -42,7 +44,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://TestServer",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://TestServer")],
signing_key=self.keypair,
)
header = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()
@ -69,7 +71,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
signing_key=self.keypair,
)
header = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()
@ -90,7 +92,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=self.keypair,
)
header = b64encode(f"{provider.client_id}:{provider.client_secret}".encode()).decode()
@ -118,7 +120,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=self.keypair,
)
# Needs to be assigned to an application for iss to be set
@ -157,7 +159,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=self.keypair,
encryption_key=self.keypair,
)
@ -188,7 +190,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=self.keypair,
)
provider.property_mappings.set(
@ -250,7 +252,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://local.invalid")],
signing_key=self.keypair,
)
provider.property_mappings.set(
@ -308,7 +310,7 @@ class TestToken(OAuthTestCase):
provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
signing_key=self.keypair,
)
provider.property_mappings.set(

View File

@ -19,7 +19,12 @@ from authentik.providers.oauth2.constants import (
SCOPE_OPENID_PROFILE,
TOKEN_TYPE,
)
from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.models import (
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
from authentik.providers.oauth2.views.jwks import JWKSView
from authentik.sources.oauth.models import OAuthSource
@ -54,7 +59,7 @@ class TestTokenClientCredentialsJWTSource(OAuthTestCase):
self.provider: OAuth2Provider = OAuth2Provider.objects.create(
name="test",
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
signing_key=self.cert,
)
self.provider.jwks_sources.add(self.source)

View File

@ -19,7 +19,13 @@ from authentik.providers.oauth2.constants import (
TOKEN_TYPE,
)
from authentik.providers.oauth2.errors import TokenError
from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.models import (
AccessToken,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -33,7 +39,7 @@ class TestTokenClientCredentialsStandard(OAuthTestCase):
self.provider = OAuth2Provider.objects.create(
name="test",
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
signing_key=create_test_cert(),
)
self.provider.property_mappings.set(ScopeMapping.objects.all())
@ -107,6 +113,48 @@ class TestTokenClientCredentialsStandard(OAuthTestCase):
{"error": "invalid_grant", "error_description": TokenError.errors["invalid_grant"]},
)
def test_incorrect_scopes(self):
"""test scope that isn't configured"""
response = self.client.post(
reverse("authentik_providers_oauth2:token"),
{
"grant_type": GRANT_TYPE_CLIENT_CREDENTIALS,
"scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} {SCOPE_OPENID_PROFILE} extra_scope",
"client_id": self.provider.client_id,
"client_secret": self.provider.client_secret,
},
)
self.assertEqual(response.status_code, 200)
body = loads(response.content.decode())
self.assertEqual(body["token_type"], TOKEN_TYPE)
token = AccessToken.objects.filter(
provider=self.provider, token=body["access_token"]
).first()
self.assertSetEqual(
set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL, SCOPE_OPENID_PROFILE}
)
_, alg = self.provider.jwt_key
jwt = decode(
body["access_token"],
key=self.provider.signing_key.public_key,
algorithms=[alg],
audience=self.provider.client_id,
)
self.assertEqual(
jwt["given_name"], "Autogenerated user from application test (client credentials)"
)
self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
jwt = decode(
body["id_token"],
key=self.provider.signing_key.public_key,
algorithms=[alg],
audience=self.provider.client_id,
)
self.assertEqual(
jwt["given_name"], "Autogenerated user from application test (client credentials)"
)
self.assertEqual(jwt["preferred_username"], "ak-test-client_credentials")
def test_successful(self):
"""test successful"""
response = self.client.post(

View File

@ -20,7 +20,12 @@ from authentik.providers.oauth2.constants import (
TOKEN_TYPE,
)
from authentik.providers.oauth2.errors import TokenError
from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.models import (
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -34,7 +39,7 @@ class TestTokenClientCredentialsStandardCompat(OAuthTestCase):
self.provider = OAuth2Provider.objects.create(
name="test",
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
signing_key=create_test_cert(),
)
self.provider.property_mappings.set(ScopeMapping.objects.all())

View File

@ -19,7 +19,12 @@ from authentik.providers.oauth2.constants import (
TOKEN_TYPE,
)
from authentik.providers.oauth2.errors import TokenError
from authentik.providers.oauth2.models import OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.models import (
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -33,7 +38,7 @@ class TestTokenClientCredentialsUserNamePassword(OAuthTestCase):
self.provider = OAuth2Provider.objects.create(
name="test",
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
signing_key=create_test_cert(),
)
self.provider.property_mappings.set(ScopeMapping.objects.all())

View File

@ -9,8 +9,19 @@ from authentik.blueprints.tests import apply_blueprint
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
from authentik.lib.generators import generate_code_fixed_length, generate_id
from authentik.providers.oauth2.constants import GRANT_TYPE_DEVICE_CODE
from authentik.providers.oauth2.models import DeviceToken, OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.constants import (
GRANT_TYPE_DEVICE_CODE,
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
)
from authentik.providers.oauth2.models import (
AccessToken,
DeviceToken,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -24,7 +35,7 @@ class TestTokenDeviceCode(OAuthTestCase):
self.provider = OAuth2Provider.objects.create(
name="test",
authorization_flow=create_test_flow(),
redirect_uris="http://testserver",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "http://testserver")],
signing_key=create_test_cert(),
)
self.provider.property_mappings.set(ScopeMapping.objects.all())
@ -80,3 +91,28 @@ class TestTokenDeviceCode(OAuthTestCase):
},
)
self.assertEqual(res.status_code, 200)
def test_code_mismatched_scope(self):
"""Test code with user (mismatched scopes)"""
device_token = DeviceToken.objects.create(
provider=self.provider,
user_code=generate_code_fixed_length(),
device_code=generate_id(),
user=self.user,
scope=[SCOPE_OPENID, SCOPE_OPENID_EMAIL],
)
res = self.client.post(
reverse("authentik_providers_oauth2:token"),
data={
"client_id": self.provider.client_id,
"grant_type": GRANT_TYPE_DEVICE_CODE,
"device_code": device_token.device_code,
"scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} invalid",
},
)
self.assertEqual(res.status_code, 200)
body = loads(res.content)
token = AccessToken.objects.filter(
provider=self.provider, token=body["access_token"]
).first()
self.assertSetEqual(set(token.scope), {SCOPE_OPENID, SCOPE_OPENID_EMAIL})

View File

@ -10,7 +10,12 @@ from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.constants import GRANT_TYPE_AUTHORIZATION_CODE
from authentik.providers.oauth2.models import AuthorizationCode, OAuth2Provider
from authentik.providers.oauth2.models import (
AuthorizationCode,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -30,7 +35,7 @@ class TestTokenPKCE(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="foo://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "foo://localhost")],
access_code_validity="seconds=100",
)
Application.objects.create(name="app", slug="app", provider=provider)
@ -93,7 +98,7 @@ class TestTokenPKCE(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="foo://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "foo://localhost")],
access_code_validity="seconds=100",
)
Application.objects.create(name="app", slug="app", provider=provider)
@ -154,7 +159,7 @@ class TestTokenPKCE(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="foo://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "foo://localhost")],
access_code_validity="seconds=100",
)
Application.objects.create(name="app", slug="app", provider=provider)
@ -210,7 +215,7 @@ class TestTokenPKCE(OAuthTestCase):
name=generate_id(),
client_id="test",
authorization_flow=flow,
redirect_uris="foo://localhost",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "foo://localhost")],
access_code_validity="seconds=100",
)
Application.objects.create(name="app", slug="app", provider=provider)

View File

@ -11,7 +11,14 @@ from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
from authentik.events.models import Event, EventAction
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import AccessToken, IDToken, OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.models import (
AccessToken,
IDToken,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
from authentik.providers.oauth2.tests.utils import OAuthTestCase
@ -25,7 +32,7 @@ class TestUserinfo(OAuthTestCase):
self.provider: OAuth2Provider = OAuth2Provider.objects.create(
name=generate_id(),
authorization_flow=create_test_flow(),
redirect_uris="",
redirect_uris=[RedirectURI(RedirectURIMatchingMode.STRICT, "")],
signing_key=create_test_cert(),
)
self.provider.property_mappings.set(ScopeMapping.objects.all())

View File

@ -56,6 +56,8 @@ from authentik.providers.oauth2.models import (
AuthorizationCode,
GrantTypes,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ResponseMode,
ResponseTypes,
ScopeMapping,
@ -187,40 +189,39 @@ class OAuthAuthorizationParams:
def check_redirect_uri(self):
"""Redirect URI validation."""
allowed_redirect_urls = self.provider.redirect_uris.split()
allowed_redirect_urls = self.provider.redirect_uris
if not self.redirect_uri:
LOGGER.warning("Missing redirect uri.")
raise RedirectUriError("", allowed_redirect_urls)
if self.provider.redirect_uris == "":
if len(allowed_redirect_urls) < 1:
LOGGER.info("Setting redirect for blank redirect_uris", redirect=self.redirect_uri)
self.provider.redirect_uris = self.redirect_uri
self.provider.redirect_uris = [
RedirectURI(RedirectURIMatchingMode.STRICT, self.redirect_uri)
]
self.provider.save()
allowed_redirect_urls = self.provider.redirect_uris.split()
allowed_redirect_urls = self.provider.redirect_uris
if self.provider.redirect_uris == "*":
LOGGER.info("Converting redirect_uris to regex", redirect=self.redirect_uri)
self.provider.redirect_uris = ".*"
self.provider.save()
allowed_redirect_urls = self.provider.redirect_uris.split()
try:
if not any(fullmatch(x, self.redirect_uri) for x in allowed_redirect_urls):
LOGGER.warning(
"Invalid redirect uri (regex comparison)",
redirect_uri_given=self.redirect_uri,
redirect_uri_expected=allowed_redirect_urls,
)
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls)
except RegexError as exc:
LOGGER.info("Failed to parse regular expression, checking directly", exc=exc)
if not any(x == self.redirect_uri for x in allowed_redirect_urls):
LOGGER.warning(
"Invalid redirect uri (strict comparison)",
redirect_uri_given=self.redirect_uri,
redirect_uri_expected=allowed_redirect_urls,
)
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls) from None
match_found = False
for allowed in allowed_redirect_urls:
if allowed.matching_mode == RedirectURIMatchingMode.STRICT:
if self.redirect_uri == allowed.url:
match_found = True
break
if allowed.matching_mode == RedirectURIMatchingMode.REGEX:
try:
if fullmatch(allowed.url, self.redirect_uri):
match_found = True
break
except RegexError as exc:
LOGGER.warning(
"Failed to parse regular expression",
exc=exc,
url=allowed.url,
provider=self.provider,
)
if not match_found:
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls)
# Check against forbidden schemes
if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES:
raise RedirectUriError(self.redirect_uri, allowed_redirect_urls)

View File

@ -5,7 +5,7 @@ from typing import Any
from django.http import HttpRequest, HttpResponse
from django.utils.translation import gettext as _
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, IntegerField
from rest_framework.fields import CharField
from structlog.stdlib import get_logger
from authentik.brands.models import Brand
@ -47,6 +47,9 @@ class CodeValidatorView(PolicyAccessView):
self.provider = self.token.provider
self.application = self.token.provider.application
def post(self, request: HttpRequest, *args, **kwargs):
return self.get(request, *args, **kwargs)
def get(self, request: HttpRequest, *args, **kwargs):
scope_descriptions = UserInfoView().get_scope_descriptions(self.token.scope, self.provider)
planner = FlowPlanner(self.provider.authorization_flow)
@ -122,7 +125,7 @@ class OAuthDeviceCodeChallenge(Challenge):
class OAuthDeviceCodeChallengeResponse(ChallengeResponse):
"""Response that includes the user-entered device code"""
code = IntegerField()
code = CharField()
component = CharField(default="ak-provider-oauth2-device-code")
def validate_code(self, code: int) -> HttpResponse | None:

View File

@ -162,5 +162,5 @@ class ProviderInfoView(View):
OAuth2Provider, pk=application.provider_id
)
response = super().dispatch(request, *args, **kwargs)
cors_allow(request, response, *self.provider.redirect_uris.split("\n"))
cors_allow(request, response, *[x.url for x in self.provider.redirect_uris])
return response

View File

@ -58,7 +58,9 @@ from authentik.providers.oauth2.models import (
ClientTypes,
DeviceToken,
OAuth2Provider,
RedirectURIMatchingMode,
RefreshToken,
ScopeMapping,
)
from authentik.providers.oauth2.utils import TokenResponse, cors_allow, extract_client_auth
from authentik.providers.oauth2.views.authorize import FORBIDDEN_URI_SCHEMES
@ -77,7 +79,7 @@ class TokenParams:
redirect_uri: str
grant_type: str
state: str
scope: list[str]
scope: set[str]
provider: OAuth2Provider
@ -112,11 +114,26 @@ class TokenParams:
redirect_uri=request.POST.get("redirect_uri", ""),
grant_type=request.POST.get("grant_type", ""),
state=request.POST.get("state", ""),
scope=request.POST.get("scope", "").split(),
scope=set(request.POST.get("scope", "").split()),
# PKCE parameter.
code_verifier=request.POST.get("code_verifier"),
)
def __check_scopes(self):
allowed_scope_names = set(
ScopeMapping.objects.filter(provider__in=[self.provider]).values_list(
"scope_name", flat=True
)
)
scopes_to_check = self.scope
if not scopes_to_check.issubset(allowed_scope_names):
LOGGER.info(
"Application requested scopes not configured, setting to overlap",
scope_allowed=allowed_scope_names,
scope_given=self.scope,
)
self.scope = self.scope.intersection(allowed_scope_names)
def __check_policy_access(self, app: Application, request: HttpRequest, **kwargs):
with start_span(
op="authentik.providers.oauth2.token.policy",
@ -149,7 +166,7 @@ class TokenParams:
client_id=self.provider.client_id,
)
raise TokenError("invalid_client")
self.__check_scopes()
if self.grant_type == GRANT_TYPE_AUTHORIZATION_CODE:
with start_span(
op="authentik.providers.oauth2.post.parse.code",
@ -179,42 +196,7 @@ class TokenParams:
LOGGER.warning("Missing authorization code")
raise TokenError("invalid_grant")
allowed_redirect_urls = self.provider.redirect_uris.split()
# At this point, no provider should have a blank redirect_uri, in case they do
# this will check an empty array and raise an error
try:
if not any(fullmatch(x, self.redirect_uri) for x in allowed_redirect_urls):
LOGGER.warning(
"Invalid redirect uri (regex comparison)",
redirect_uri=self.redirect_uri,
expected=allowed_redirect_urls,
)
Event.new(
EventAction.CONFIGURATION_ERROR,
message="Invalid redirect URI used by provider",
provider=self.provider,
redirect_uri=self.redirect_uri,
expected=allowed_redirect_urls,
).from_http(request)
raise TokenError("invalid_client")
except RegexError as exc:
LOGGER.info("Failed to parse regular expression, checking directly", exc=exc)
if not any(x == self.redirect_uri for x in allowed_redirect_urls):
LOGGER.warning(
"Invalid redirect uri (strict comparison)",
redirect_uri=self.redirect_uri,
expected=allowed_redirect_urls,
)
Event.new(
EventAction.CONFIGURATION_ERROR,
message="Invalid redirect_uri configured",
provider=self.provider,
).from_http(request)
raise TokenError("invalid_client") from None
# Check against forbidden schemes
if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES:
raise TokenError("invalid_request")
self.__check_redirect_uri(request)
self.authorization_code = AuthorizationCode.objects.filter(code=raw_code).first()
if not self.authorization_code:
@ -254,6 +236,48 @@ class TokenParams:
if not self.authorization_code.code_challenge and self.code_verifier:
raise TokenError("invalid_grant")
def __check_redirect_uri(self, request: HttpRequest):
allowed_redirect_urls = self.provider.redirect_uris
# At this point, no provider should have a blank redirect_uri, in case they do
# this will check an empty array and raise an error
match_found = False
for allowed in allowed_redirect_urls:
if allowed.matching_mode == RedirectURIMatchingMode.STRICT:
if self.redirect_uri == allowed.url:
match_found = True
break
if allowed.matching_mode == RedirectURIMatchingMode.REGEX:
try:
if fullmatch(allowed.url, self.redirect_uri):
match_found = True
break
except RegexError as exc:
LOGGER.warning(
"Failed to parse regular expression",
exc=exc,
url=allowed.url,
provider=self.provider,
)
Event.new(
EventAction.CONFIGURATION_ERROR,
message="Invalid redirect_uri configured",
provider=self.provider,
).from_http(request)
if not match_found:
Event.new(
EventAction.CONFIGURATION_ERROR,
message="Invalid redirect URI used by provider",
provider=self.provider,
redirect_uri=self.redirect_uri,
expected=allowed_redirect_urls,
).from_http(request)
raise TokenError("invalid_client")
# Check against forbidden schemes
if urlparse(self.redirect_uri).scheme in FORBIDDEN_URI_SCHEMES:
raise TokenError("invalid_request")
def __post_init_refresh(self, raw_token: str, request: HttpRequest):
if not raw_token:
LOGGER.warning("Missing refresh token")
@ -497,7 +521,7 @@ class TokenView(View):
response = super().dispatch(request, *args, **kwargs)
allowed_origins = []
if self.provider:
allowed_origins = self.provider.redirect_uris.split("\n")
allowed_origins = [x.url for x in self.provider.redirect_uris]
cors_allow(self.request, response, *allowed_origins)
return response
@ -710,7 +734,7 @@ class TokenView(View):
"id_token": access_token.id_token.to_jwt(self.provider),
}
if SCOPE_OFFLINE_ACCESS in self.params.scope:
if SCOPE_OFFLINE_ACCESS in self.params.device_code.scope:
refresh_token_expiry = now + timedelta_from_string(self.provider.refresh_token_validity)
refresh_token = RefreshToken(
user=self.params.device_code.user,

View File

@ -108,7 +108,7 @@ class UserInfoView(View):
response = super().dispatch(request, *args, **kwargs)
allowed_origins = []
if self.token:
allowed_origins = self.token.provider.redirect_uris.split("\n")
allowed_origins = [x.url for x in self.token.provider.redirect_uris]
cors_allow(self.request, response, *allowed_origins)
return response

View File

@ -13,6 +13,7 @@ from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.lib.utils.time import timedelta_from_string
from authentik.providers.oauth2.api.providers import RedirectURISerializer
from authentik.providers.oauth2.models import ScopeMapping
from authentik.providers.oauth2.views.provider import ProviderInfoView
from authentik.providers.proxy.models import ProxyMode, ProxyProvider
@ -39,7 +40,7 @@ class ProxyProviderSerializer(ProviderSerializer):
"""ProxyProvider Serializer"""
client_id = CharField(read_only=True)
redirect_uris = CharField(read_only=True)
redirect_uris = RedirectURISerializer(many=True, read_only=True, source="_redirect_uris")
outpost_set = ListField(child=CharField(), read_only=True, source="outpost_set.all")
def validate_basic_auth_enabled(self, value: bool) -> bool:
@ -121,7 +122,6 @@ class ProxyProviderViewSet(UsedByMixin, ModelViewSet):
"basic_auth_password_attribute": ["iexact"],
"basic_auth_user_attribute": ["iexact"],
"mode": ["iexact"],
"redirect_uris": ["iexact"],
"cookie_domain": ["iexact"],
}
search_fields = ["name"]

View File

@ -13,7 +13,13 @@ from rest_framework.serializers import Serializer
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.models import DomainlessURLValidator
from authentik.outposts.models import OutpostModel
from authentik.providers.oauth2.models import ClientTypes, OAuth2Provider, ScopeMapping
from authentik.providers.oauth2.models import (
ClientTypes,
OAuth2Provider,
RedirectURI,
RedirectURIMatchingMode,
ScopeMapping,
)
SCOPE_AK_PROXY = "ak_proxy"
OUTPOST_CALLBACK_SIGNATURE = "X-authentik-auth-callback"
@ -24,14 +30,14 @@ def get_cookie_secret():
return "".join(SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(32))
def _get_callback_url(uri: str) -> str:
return "\n".join(
[
urljoin(uri, "outpost.goauthentik.io/callback")
+ f"\\?{OUTPOST_CALLBACK_SIGNATURE}=true",
uri + f"\\?{OUTPOST_CALLBACK_SIGNATURE}=true",
]
)
def _get_callback_url(uri: str) -> list[RedirectURI]:
return [
RedirectURI(
RedirectURIMatchingMode.STRICT,
urljoin(uri, "outpost.goauthentik.io/callback") + f"?{OUTPOST_CALLBACK_SIGNATURE}=true",
),
RedirectURI(RedirectURIMatchingMode.STRICT, uri + f"?{OUTPOST_CALLBACK_SIGNATURE}=true"),
]
class ProxyMode(models.TextChoices):

View File

@ -19,6 +19,7 @@ SCIM_GROUP_SCHEMA = "urn:ietf:params:scim:schemas:core:2.0:Group"
class User(BaseUser):
"""Modified User schema with added externalId field"""
id: str | int | None = None
schemas: list[str] = [SCIM_USER_SCHEMA]
externalId: str | None = None
meta: dict | None = None
@ -27,6 +28,7 @@ class User(BaseUser):
class Group(BaseGroup):
"""Modified Group schema with added externalId field"""
id: str | int | None = None
schemas: list[str] = [SCIM_GROUP_SCHEMA]
externalId: str | None = None
meta: dict | None = None

View File

@ -53,7 +53,7 @@ class ExtraRoleObjectPermissionSerializer(RoleObjectPermissionSerializer):
except LookupError:
return None
objects = get_objects_for_group(instance.group, f"{app_label}.view_{model}", model_class)
obj = objects.first()
obj = objects.filter(pk=instance.object_pk).first()
if not obj:
return None
return str(obj)

View File

@ -53,7 +53,7 @@ class ExtraUserObjectPermissionSerializer(UserObjectPermissionSerializer):
except LookupError:
return None
objects = get_objects_for_user(instance.user, f"{app_label}.view_{model}", model_class)
obj = objects.first()
obj = objects.filter(pk=instance.object_pk).first()
if not obj:
return None
return str(obj)

View File

@ -1,6 +1,8 @@
"""Metrics view"""
from base64 import b64encode
from hmac import compare_digest
from pathlib import Path
from tempfile import gettempdir
from django.conf import settings
from django.db import connections
@ -16,22 +18,21 @@ monitoring_set = Signal()
class MetricsView(View):
"""Wrapper around ExportToDjangoView, using http-basic auth"""
"""Wrapper around ExportToDjangoView with authentication, accessed by the authentik router"""
def __init__(self, **kwargs):
_tmp = Path(gettempdir())
with open(_tmp / "authentik-core-metrics.key") as _f:
self.monitoring_key = _f.read()
def get(self, request: HttpRequest) -> HttpResponse:
"""Check for HTTP-Basic auth"""
auth_header = request.META.get("HTTP_AUTHORIZATION", "")
auth_type, _, given_credentials = auth_header.partition(" ")
credentials = f"monitor:{settings.SECRET_KEY}"
expected = b64encode(str.encode(credentials)).decode()
authed = auth_type == "Basic" and given_credentials == expected
authed = auth_type == "Bearer" and compare_digest(given_credentials, self.monitoring_key)
if not authed and not settings.DEBUG:
response = HttpResponse(status=401)
response["WWW-Authenticate"] = 'Basic realm="authentik-monitoring"'
return response
return HttpResponse(status=401)
monitoring_set.send_robust(self)
return ExportToDjangoView(request)

View File

@ -1,8 +1,9 @@
"""root tests"""
from base64 import b64encode
from pathlib import Path
from secrets import token_urlsafe
from tempfile import gettempdir
from django.conf import settings
from django.test import TestCase
from django.urls import reverse
@ -10,6 +11,16 @@ from django.urls import reverse
class TestRoot(TestCase):
"""Test root application"""
def setUp(self):
_tmp = Path(gettempdir())
self.token = token_urlsafe(32)
with open(_tmp / "authentik-core-metrics.key", "w") as _f:
_f.write(self.token)
def tearDown(self):
_tmp = Path(gettempdir())
(_tmp / "authentik-core-metrics.key").unlink()
def test_monitoring_error(self):
"""Test monitoring without any credentials"""
response = self.client.get(reverse("metrics"))
@ -17,8 +28,7 @@ class TestRoot(TestCase):
def test_monitoring_ok(self):
"""Test monitoring with credentials"""
creds = "Basic " + b64encode(f"monitor:{settings.SECRET_KEY}".encode()).decode("utf-8")
auth_headers = {"HTTP_AUTHORIZATION": creds}
auth_headers = {"HTTP_AUTHORIZATION": f"Bearer {self.token}"}
response = self.client.get(reverse("metrics"), **auth_headers)
self.assertEqual(response.status_code, 200)

View File

@ -6,7 +6,6 @@ from tempfile import gettempdir
from typing import Any
import gssapi
import kadmin
import pglock
from django.db import connection, models
from django.db.models.fields import b64decode
@ -14,6 +13,8 @@ from django.http import HttpRequest
from django.shortcuts import reverse
from django.templatetags.static import static
from django.utils.translation import gettext_lazy as _
from kadmin import KAdmin
from kadmin.exceptions import PyKAdminException
from rest_framework.serializers import Serializer
from structlog.stdlib import get_logger
@ -30,9 +31,8 @@ from authentik.flows.challenge import RedirectChallenge
LOGGER = get_logger()
# python-kadmin leaks file descriptors. As such, this global is used to reuse
# existing kadmin connections instead of creating new ones, which results in less to no file
# descriptors leaks
# Creating kadmin connections is expensive. As such, this global is used to reuse
# existing kadmin connections instead of creating new ones
_kadmin_connections: dict[str, Any] = {}
@ -198,13 +198,13 @@ class KerberosSource(Source):
conf_path.write_text(self.krb5_conf)
return str(conf_path)
def _kadmin_init(self) -> "kadmin.KAdmin | None":
def _kadmin_init(self) -> KAdmin | None:
# kadmin doesn't use a ccache for its connection
# as such, we don't need to create a separate ccache for each source
if not self.sync_principal:
return None
if self.sync_password:
return kadmin.init_with_password(
return KAdmin.with_password(
self.sync_principal,
self.sync_password,
)
@ -215,18 +215,18 @@ class KerberosSource(Source):
keytab_path.touch(mode=0o600)
keytab_path.write_bytes(b64decode(self.sync_keytab))
keytab = f"FILE:{keytab_path}"
return kadmin.init_with_keytab(
return KAdmin.with_keytab(
self.sync_principal,
keytab,
)
if self.sync_ccache:
return kadmin.init_with_ccache(
return KAdmin.with_ccache(
self.sync_principal,
self.sync_ccache,
)
return None
def connection(self) -> "kadmin.KAdmin | None":
def connection(self) -> KAdmin | None:
"""Get kadmin connection"""
if str(self.pk) not in _kadmin_connections:
kadm = self._kadmin_init()
@ -246,7 +246,7 @@ class KerberosSource(Source):
status["status"] = "no connection"
return status
status["principal_exists"] = kadm.principal_exists(self.sync_principal)
except kadmin.KAdminError as exc:
except PyKAdminException as exc:
status["status"] = str(exc)
return status

View File

@ -1,8 +1,8 @@
"""authentik kerberos source signals"""
import kadmin
from django.db.models.signals import post_save
from django.dispatch import receiver
from kadmin.exceptions import PyKAdminException
from rest_framework.serializers import ValidationError
from structlog.stdlib import get_logger
@ -48,7 +48,7 @@ def kerberos_sync_password(sender, user: User, password: str, **_):
source.connection().getprinc(user_source_connection.identifier).change_password(
password
)
except kadmin.KAdminError as exc:
except PyKAdminException as exc:
LOGGER.warning("failed to set Kerberos password", exc=exc, source=source)
Event.new(
EventAction.CONFIGURATION_ERROR,

View File

@ -2,9 +2,9 @@
from typing import Any
import kadmin
from django.core.exceptions import FieldError
from django.db import IntegrityError, transaction
from kadmin import KAdmin
from structlog.stdlib import BoundLogger, get_logger
from authentik.core.expression.exceptions import (
@ -30,7 +30,7 @@ class KerberosSync:
_source: KerberosSource
_logger: BoundLogger
_connection: "kadmin.KAdmin"
_connection: KAdmin
mapper: SourceMapper
user_manager: PropertyMappingManager
group_manager: PropertyMappingManager
@ -161,7 +161,7 @@ class KerberosSync:
user_count = 0
with Krb5ConfContext(self._source):
for principal in self._connection.principals():
for principal in self._connection.list_principals(None):
if self._handle_principal(principal):
user_count += 1
return user_count

View File

@ -23,6 +23,7 @@ class TestKerberosAuth(KerberosTestCase):
)
self.user = User.objects.create(username=generate_id())
self.user.set_unusable_password()
self.user.save()
UserKerberosSourceConnection.objects.create(
source=self.source, user=self.user, identifier=self.realm.user_princ
)

View File

@ -2,6 +2,8 @@
from base64 import b64decode, b64encode
from pathlib import Path
from sys import platform
from unittest import skipUnless
import gssapi
from django.urls import reverse
@ -36,6 +38,7 @@ class TestSPNEGOSource(KerberosTestCase):
)
self.assertEqual(response.status_code, 200)
@skipUnless(platform.startswith("linux"), "Requires compatible GSSAPI implementation")
def test_source_login(self):
"""test login view"""
response = self.client.get(

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,7 @@ class CaptchaStageSerializer(StageSerializer):
"private_key",
"js_url",
"api_url",
"interactive",
"score_min_threshold",
"score_max_threshold",
"error_on_invalid_score",

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.9 on 2024-10-30 14:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_captcha", "0003_captchastage_error_on_invalid_score_and_more"),
]
operations = [
migrations.AddField(
model_name="captchastage",
name="interactive",
field=models.BooleanField(default=False),
),
]

View File

@ -9,11 +9,13 @@ from authentik.flows.models import Stage
class CaptchaStage(Stage):
"""Verify the user is human using Google's reCaptcha."""
"""Verify the user is human using Google's reCaptcha/other compatible CAPTCHA solutions."""
public_key = models.TextField(help_text=_("Public key, acquired your captcha Provider."))
private_key = models.TextField(help_text=_("Private key, acquired your captcha Provider."))
interactive = models.BooleanField(default=False)
score_min_threshold = models.FloatField(default=0.5) # Default values for reCaptcha
score_max_threshold = models.FloatField(default=1.0) # Default values for reCaptcha

View File

@ -3,7 +3,7 @@
from django.http.response import HttpResponse
from django.utils.translation import gettext as _
from requests import RequestException
from rest_framework.fields import CharField
from rest_framework.fields import BooleanField, CharField
from rest_framework.serializers import ValidationError
from structlog.stdlib import get_logger
@ -24,10 +24,12 @@ PLAN_CONTEXT_CAPTCHA = "captcha"
class CaptchaChallenge(WithUserInfoChallenge):
"""Site public key"""
site_key = CharField()
js_url = CharField()
component = CharField(default="ak-stage-captcha")
site_key = CharField(required=True)
js_url = CharField(required=True)
interactive = BooleanField(required=True)
def verify_captcha_token(stage: CaptchaStage, token: str, remote_ip: str):
"""Validate captcha token"""
@ -103,6 +105,7 @@ class CaptchaStageView(ChallengeStageView):
data={
"js_url": self.executor.current_stage.js_url,
"site_key": self.executor.current_stage.public_key,
"interactive": self.executor.current_stage.interactive,
}
)

View File

@ -223,6 +223,7 @@ class IdentificationStageView(ChallengeStageView):
{
"js_url": current_stage.captcha_stage.js_url,
"site_key": current_stage.captcha_stage.public_key,
"interactive": current_stage.captcha_stage.interactive,
}
if current_stage.captcha_stage
else None

View File

@ -21,7 +21,7 @@ from authentik.flows.challenge import (
WithUserInfoChallenge,
)
from authentik.flows.exceptions import StageInvalidException
from authentik.flows.models import Flow, FlowDesignation, Stage
from authentik.flows.models import Flow, Stage
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
from authentik.flows.stage import ChallengeStageView
from authentik.lib.utils.reflection import path_to_class
@ -141,11 +141,11 @@ class PasswordStageView(ChallengeStageView):
"allow_show_password": self.executor.current_stage.allow_show_password,
}
)
recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY)
if recovery_flow.exists():
recovery_flow: Flow | None = self.request.brand.flow_recovery
if recovery_flow:
recover_url = reverse(
"authentik_core:if-flow",
kwargs={"flow_slug": recovery_flow.first().slug},
kwargs={"flow_slug": recovery_flow.slug},
)
challenge.initial_data["recovery_url"] = self.request.build_absolute_uri(recover_url)
return challenge

View File

@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch
from django.core.exceptions import PermissionDenied
from django.urls import reverse
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_brand, create_test_flow
from authentik.flows.markers import StageMarker
from authentik.flows.models import FlowDesignation, FlowStageBinding
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
@ -57,6 +57,9 @@ class TestPasswordStage(FlowTestCase):
def test_recovery_flow_link(self):
"""Test link to the default recovery flow"""
flow = create_test_flow(designation=FlowDesignation.RECOVERY)
brand = create_test_brand()
brand.flow_recovery = flow
brand.save()
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
session = self.client.session

View File

@ -23,6 +23,7 @@ class SettingsSerializer(ModelSerializer):
"footer_links",
"gdpr_compliance",
"impersonation",
"impersonation_require_reason",
"default_token_duration",
"default_token_length",
]

View File

@ -0,0 +1,21 @@
# Generated by Django 5.0.9 on 2024-11-07 15:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_tenants", "0003_alter_tenant_default_token_duration"),
]
operations = [
migrations.AddField(
model_name="tenant",
name="impersonation_require_reason",
field=models.BooleanField(
default=True,
help_text="Require administrators to provide a reason for impersonating a user.",
),
),
]

View File

@ -85,6 +85,10 @@ class Tenant(TenantMixin, SerializerModel):
impersonation = models.BooleanField(
help_text=_("Globally enable/disable impersonation."), default=True
)
impersonation_require_reason = models.BooleanField(
help_text=_("Require administrators to provide a reason for impersonating a user."),
default=True,
)
default_token_duration = models.TextField(
help_text=_("Default token duration"),
default=DEFAULT_TOKEN_DURATION,

View File

@ -8,9 +8,11 @@ from authentik.root.install_id import get_install_id
from authentik.tenants.models import Tenant
def get_current_tenant() -> Tenant:
def get_current_tenant(only: list[str] | None = None) -> Tenant:
"""Get tenant for current request"""
return Tenant.objects.get(schema_name=connection.schema_name)
if only is None:
only = []
return Tenant.objects.only(*only).get(schema_name=connection.schema_name)
def get_unique_identifier() -> str:

View File

@ -101,7 +101,6 @@ entries:
- !KeyOf prompt-field-email
- !KeyOf prompt-field-password
- !KeyOf prompt-field-password-repeat
validation_policies: []
id: stage-default-oobe-password
identifiers:
name: stage-default-oobe-password

View File

@ -2,6 +2,17 @@ version: 1
metadata:
name: Default - Password change flow
entries:
- attrs:
check_static_rules: true
check_zxcvbn: true
length_min: 8
password_field: password
zxcvbn_score_threshold: 2
error_message: Password needs to be 8 characters or longer.
identifiers:
name: default-password-change-password-policy
model: authentik_policies_password.passwordpolicy
id: default-password-change-password-policy
- attrs:
designation: stage_configuration
name: Change Password
@ -39,6 +50,8 @@ entries:
fields:
- !KeyOf prompt-field-password
- !KeyOf prompt-field-password-repeat
validation_policies:
- !KeyOf default-password-change-password-policy
identifiers:
name: default-password-change-prompt
id: default-password-change-prompt

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 2024.8.3 Blueprint schema",
"title": "authentik 2024.10.4 Blueprint schema",
"required": [
"version",
"entries"
@ -5570,9 +5570,30 @@
"description": "Key used to encrypt the tokens. When set, tokens will be encrypted and returned as JWEs."
},
"redirect_uris": {
"type": "string",
"title": "Redirect URIs",
"description": "Enter each URI on a new line."
"type": "array",
"items": {
"type": "object",
"properties": {
"matching_mode": {
"type": "string",
"enum": [
"strict",
"regex"
],
"title": "Matching mode"
},
"url": {
"type": "string",
"minLength": 1,
"title": "Url"
}
},
"required": [
"matching_mode",
"url"
]
},
"title": "Redirect uris"
},
"sub_mode": {
"type": "string",
@ -6974,7 +6995,7 @@
"spnego_server_name": {
"type": "string",
"title": "Spnego server name",
"description": "Force the use of a specific server name for SPNEGO"
"description": "Force the use of a specific server name for SPNEGO. Must be in the form HTTP@hostname"
},
"spnego_keytab": {
"type": "string",
@ -9781,6 +9802,10 @@
"minLength": 1,
"title": "Api url"
},
"interactive": {
"type": "boolean",
"title": "Interactive"
},
"score_min_threshold": {
"type": "number",
"title": "Score min threshold"
@ -13383,12 +13408,6 @@
"title": "Authorization flow",
"description": "Flow used when authorizing this provider."
},
"invalidation_flow": {
"type": "string",
"format": "uuid",
"title": "Invalidation flow",
"description": "Flow used ending the session from a provider."
},
"property_mappings": {
"type": "array",
"items": {

View File

@ -38,7 +38,7 @@ entries:
name: "authentik default Kerberos User Mapping: Ignore system principals"
expression: |
localpart, realm = principal.rsplit("@", 1)
denied_prefixes = ["kadmin/", "krbtgt/", "K/M", "WELLKNOWN/"]
denied_prefixes = ["kadmin/", "krbtgt/", "K/M", "WELLKNOWN/", "kiprop/", "changepw/"]
for prefix in denied_prefixes:
if localpart.lower().startswith(prefix.lower()):
raise SkipObject

View File

@ -31,7 +31,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.3}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.10.4}
restart: unless-stopped
command: server
environment:
@ -52,7 +52,7 @@ services:
- postgresql
- redis
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.3}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.10.4}
restart: unless-stopped
command: worker
environment:

6
go.mod
View File

@ -29,10 +29,10 @@ require (
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2024083.13
goauthentik.io/api/v3 v3.2024104.1
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.23.0
golang.org/x/sync v0.8.0
golang.org/x/oauth2 v0.24.0
golang.org/x/sync v0.9.0
gopkg.in/yaml.v2 v2.4.0
layeh.com/radius v0.0.0-20210819152912-ad72663a72ab
)

12
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.2024083.13 h1:xKh3feJYUeLw583zZ5ifgV0qjD37ZCOzgXPfbHQSbHM=
goauthentik.io/api/v3 v3.2024083.13/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2024104.1 h1:N09HAJ66W965QEYpx6sJzcaQxPsnFykVwkzVjVK/zH0=
goauthentik.io/api/v3 v3.2024104.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -388,8 +388,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -400,8 +400,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

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

View File

@ -65,7 +65,7 @@ func (ls *LDAPServer) StartLDAPServer() error {
ls.log.WithField("listen", listen).WithError(err).Warning("Failed to listen (SSL)")
return err
}
proxyListener := &proxyproto.Listener{Listener: ln}
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
ls.log.WithField("listen", listen).Info("Starting LDAP server")

View File

@ -48,7 +48,7 @@ func (ls *LDAPServer) StartLDAPTLSServer() error {
return err
}
proxyListener := &proxyproto.Listener{Listener: ln}
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
tln := tls.NewListener(proxyListener, tlsConfig)

View File

@ -23,6 +23,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
"goauthentik.io/api/v3"
"goauthentik.io/internal/config"
"goauthentik.io/internal/outpost/ak"
"goauthentik.io/internal/outpost/proxyv2/constants"
"goauthentik.io/internal/outpost/proxyv2/hs256"
@ -121,6 +122,14 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server, old
bs := string(h.Sum([]byte(*p.ClientId)))
sessionName := fmt.Sprintf("authentik_proxy_%s", bs[:8])
// When HOST_BROWSER is set, use that as Host header for token requests to make the issuer match
// otherwise we use the internally configured authentik_host
tokenEndpointHost := server.API().Outpost.Config["authentik_host"].(string)
if config.Get().AuthentikHostBrowser != "" {
tokenEndpointHost = config.Get().AuthentikHostBrowser
}
publicHTTPClient := web.NewHostInterceptor(c, tokenEndpointHost)
a := &Application{
Host: externalHost.Host,
log: muxLogger,
@ -131,7 +140,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server, old
tokenVerifier: verifier,
proxyConfig: p,
httpClient: c,
publicHostHTTPClient: web.NewHostInterceptor(c, server.API().Outpost.Config["authentik_host"].(string)),
publicHostHTTPClient: publicHTTPClient,
mux: mux,
errorTemplates: templates.GetTemplates(),
ak: server.API(),

View File

@ -129,7 +129,7 @@ func (ps *ProxyServer) ServeHTTP() {
ps.log.WithField("listen", listenAddress).WithError(err).Warning("Failed to listen")
return
}
proxyListener := &proxyproto.Listener{Listener: listener}
proxyListener := &proxyproto.Listener{Listener: listener, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
ps.log.WithField("listen", listenAddress).Info("Starting HTTP server")
@ -148,7 +148,7 @@ func (ps *ProxyServer) ServeHTTPS() {
ps.log.WithError(err).Warning("Failed to listen (TLS)")
return
}
proxyListener := &proxyproto.Listener{Listener: web.TCPKeepAliveListener{TCPListener: ln.(*net.TCPListener)}}
proxyListener := &proxyproto.Listener{Listener: web.TCPKeepAliveListener{TCPListener: ln.(*net.TCPListener)}, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
tlsListener := tls.NewListener(proxyListener, tlsConfig)

34
internal/utils/proxy.go Normal file
View File

@ -0,0 +1,34 @@
package utils
import (
"net"
"github.com/pires/go-proxyproto"
log "github.com/sirupsen/logrus"
"goauthentik.io/internal/config"
)
func GetProxyConnectionPolicy() proxyproto.ConnPolicyFunc {
nets := []*net.IPNet{}
for _, rn := range config.Get().Listen.TrustedProxyCIDRs {
_, cidr, err := net.ParseCIDR(rn)
if err != nil {
continue
}
nets = append(nets, cidr)
}
return func(connPolicyOptions proxyproto.ConnPolicyOptions) (proxyproto.Policy, error) {
host, _, err := net.SplitHostPort(connPolicyOptions.Upstream.String())
if err == nil {
// remoteAddr will be nil if the IP cannot be parsed
remoteAddr := net.ParseIP(host)
for _, allowedCidr := range nets {
if remoteAddr != nil && allowedCidr.Contains(remoteAddr) {
log.WithField("remoteAddr", remoteAddr).WithField("cidr", allowedCidr.String()).Trace("Using remote IP from proxy protocol")
return proxyproto.USE, nil
}
}
}
return proxyproto.SKIP, nil
}
}

View File

@ -14,8 +14,10 @@ type hostInterceptor struct {
}
func (t hostInterceptor) RoundTrip(r *http.Request) (*http.Response, error) {
r.Host = t.host
r.Header.Set("X-Forwarded-Proto", t.scheme)
if r.Host != t.host {
r.Host = t.host
r.Header.Set("X-Forwarded-Proto", t.scheme)
}
return t.inner.RoundTrip(r)
}

View File

@ -1,11 +1,15 @@
package web
import (
"encoding/base64"
"fmt"
"io"
"net/http"
"os"
"path"
"github.com/gorilla/mux"
"github.com/gorilla/securecookie"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
@ -14,14 +18,25 @@ import (
"goauthentik.io/internal/utils/sentry"
)
const MetricsKeyFile = "authentik-core-metrics.key"
var Requests = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "authentik_main_request_duration_seconds",
Help: "API request latencies in seconds",
}, []string{"dest"})
func (ws *WebServer) runMetricsServer() {
m := mux.NewRouter()
l := log.WithField("logger", "authentik.router.metrics")
tmp := os.TempDir()
key := base64.StdEncoding.EncodeToString(securecookie.GenerateRandomKey(64))
keyPath := path.Join(tmp, MetricsKeyFile)
err := os.WriteFile(keyPath, []byte(key), 0o600)
if err != nil {
l.WithError(err).Warning("failed to save metrics key")
return
}
m := mux.NewRouter()
m.Use(sentry.SentryNoSampleMiddleware)
m.Path("/metrics").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
promhttp.InstrumentMetricHandler(
@ -36,7 +51,7 @@ func (ws *WebServer) runMetricsServer() {
l.WithError(err).Warning("failed to get upstream metrics")
return
}
re.SetBasicAuth("monitor", config.Get().SecretKey)
re.Header.Set("Authorization", fmt.Sprintf("Bearer %s", key))
res, err := ws.upstreamHttpClient().Do(re)
if err != nil {
l.WithError(err).Warning("failed to get upstream metrics")
@ -49,9 +64,13 @@ func (ws *WebServer) runMetricsServer() {
}
})
l.WithField("listen", config.Get().Listen.Metrics).Info("Starting Metrics server")
err := http.ListenAndServe(config.Get().Listen.Metrics, m)
err = http.ListenAndServe(config.Get().Listen.Metrics, m)
if err != nil {
l.WithError(err).Warning("Failed to start metrics server")
}
l.WithField("listen", config.Get().Listen.Metrics).Info("Stopping Metrics server")
err = os.Remove(keyPath)
if err != nil {
l.WithError(err).Warning("failed to remove metrics key file")
}
}

View File

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

View File

@ -19,6 +19,7 @@ import (
"goauthentik.io/internal/config"
"goauthentik.io/internal/gounicorn"
"goauthentik.io/internal/outpost/proxyv2"
"goauthentik.io/internal/utils"
"goauthentik.io/internal/utils/web"
"goauthentik.io/internal/web/brand_tls"
)
@ -52,7 +53,7 @@ func NewWebServer() *WebServer {
loggingHandler.Use(web.NewLoggingHandler(l, nil))
tmp := os.TempDir()
socketPath := path.Join(tmp, "authentik-core.sock")
socketPath := path.Join(tmp, UnixSocketName)
// create http client to talk to backend, normal client if we're in debug more
// and a client that connects to our socket when in non debug mode
@ -149,7 +150,7 @@ func (ws *WebServer) listenPlain() {
ws.log.WithError(err).Warning("failed to listen")
return
}
proxyListener := &proxyproto.Listener{Listener: ln}
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
defer proxyListener.Close()
ws.log.WithField("listen", config.Get().Listen.HTTP).Info("Starting HTTP server")

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