Compare commits

...

150 Commits

Author SHA1 Message Date
4a1acd377b release: 2022.2.1 2022-02-16 10:51:55 +01:00
c5b84a91d1 website/docs: add 2022.2 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-16 10:27:25 +01:00
e77ecda3b8 root: update security
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-16 10:20:32 +01:00
4e317c10c5 Revert "website/docs: revert to akprox for now"
This reverts commit 9070df6c26.

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

# Conflicts:
#	website/docs/providers/proxy/_nginx_ingress.md
#	website/docs/providers/proxy/_nginx_proxy_manager.md
#	website/docs/providers/proxy/_nginx_standalone.md
2022-02-16 10:19:33 +01:00
eb05a3ddb8 build(deps): bump @sentry/browser from 6.17.7 to 6.17.8 in /web (#2318) 2022-02-16 09:13:04 +01:00
a22d6a0924 build(deps): bump @sentry/tracing from 6.17.7 to 6.17.8 in /web (#2319) 2022-02-16 09:10:54 +01:00
3f0d67779a build(deps): bump lit from 2.1.3 to 2.1.4 in /web (#2320) 2022-02-16 09:10:38 +01:00
0a937ae8e9 build(deps): bump @babel/core from 7.17.2 to 7.17.4 in /web (#2321) 2022-02-16 09:10:23 +01:00
f8d94f3039 build(deps): bump github.com/go-ldap/ldap/v3 from 3.4.1 to 3.4.2 (#2323) 2022-02-16 09:10:04 +01:00
6bb261ac62 build(deps): bump github.com/gorilla/websocket from 1.4.2 to 1.5.0 (#2324) 2022-02-16 09:09:39 +01:00
45f2c5bae7 web/admin: fix invalid URLs in example proxy config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-15 23:24:27 +01:00
5d8c1aa0b0 outposts/proxy: correctly check host in forward domain redirect
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1997
2022-02-15 14:58:19 +01:00
0101368369 outposts/proxy: fix logic error in rd argument
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1997
2022-02-15 13:43:55 +01:00
4854f81592 outposts/proxy: correctly handle ?rd= param
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1997
2022-02-15 11:05:03 +01:00
4bed6e02e5 Revert "build(deps): bump sentry-sdk from 1.5.4 to 1.5.5 (#2315)"
This reverts commit b6edf990e0.
2022-02-15 10:24:11 +01:00
908f123d0e website/docs: update nginx config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-15 10:24:08 +01:00
256dd24a1e build(deps): bump @typescript-eslint/parser in /web (#2312)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.11.0 to 5.12.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.12.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-02-15 10:06:18 +01:00
d4284407f9 build(deps): bump @typescript-eslint/eslint-plugin in /web (#2313)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.11.0 to 5.12.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.12.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-02-15 10:04:33 +01:00
80da5dfc52 build(deps): bump webauthn from 1.2.1 to 1.3.0 (#2314)
Bumps [webauthn](https://github.com/duo-labs/py_webauthn) from 1.2.1 to 1.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/v1.2.1...v1.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>
2022-02-15 10:04:17 +01:00
b6edf990e0 build(deps): bump sentry-sdk from 1.5.4 to 1.5.5 (#2315)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.5.4 to 1.5.5.
- [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/1.5.4...1.5.5)

---
updated-dependencies:
- dependency-name: sentry-sdk
  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>
2022-02-15 09:56:32 +01:00
a66dcf9382 build(deps): bump kubernetes from 21.7.0 to 22.6.0 (#2316)
Bumps [kubernetes](https://github.com/kubernetes-client/python) from 21.7.0 to 22.6.0.
- [Release notes](https://github.com/kubernetes-client/python/releases)
- [Changelog](https://github.com/kubernetes-client/python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes-client/python/compare/v21.7.0...v22.6.0)

---
updated-dependencies:
- dependency-name: kubernetes
  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>
2022-02-15 09:56:22 +01:00
9095a840d5 build(deps-dev): bump importlib-metadata from 4.11.0 to 4.11.1 (#2317)
Bumps [importlib-metadata](https://github.com/python/importlib_metadata) from 4.11.0 to 4.11.1.
- [Release notes](https://github.com/python/importlib_metadata/releases)
- [Changelog](https://github.com/python/importlib_metadata/blob/main/CHANGES.rst)
- [Commits](https://github.com/python/importlib_metadata/compare/v4.11.0...v4.11.1)

---
updated-dependencies:
- dependency-name: importlib-metadata
  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>
2022-02-15 09:56:12 +01:00
72259f6479 events: fix lint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-14 23:15:45 +01:00
0973c74b9d providers/oauth2: fix redirect_uri being lowercased on successful validation
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-14 23:04:00 +01:00
c7ed4f7ac1 events: check mtime on geoip database
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-14 22:42:46 +01:00
3d577cf15e *: add placeholder custom.css to easily allow user customisation
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-14 20:05:00 +01:00
5474a32573 Translate /web/src/locales/en.po in zh_TW (#2308) 2022-02-14 15:36:54 +01:00
a5940b88e3 Translate /web/src/locales/en.po in zh-Hant (#2307) 2022-02-14 15:36:37 +01:00
ff15716012 Translate /web/src/locales/en.po in zh-Hans (#2306) 2022-02-14 15:36:27 +01:00
c040b13b29 providers/proxy: remove leading slash to allow subdirectories in proxy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2305
2022-02-14 12:51:04 +01:00
4915e980c5 providers/proxy: revert Host header behaviour
closes #2284

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-14 12:39:16 +01:00
df362dd9ea core: handle error when formatting launch URL fails closes #2304 2022-02-14 12:02:51 +01:00
d4e4f93cb4 Revert "build(deps): bump sentry-sdk from 1.5.4 to 1.5.5 (#2303)"
This reverts commit 3de224690a.
2022-02-14 09:55:39 +01:00
3af0de6a00 Revert "root: disable sentry's auto_session_tracking"
This reverts commit 4f24d61290.
2022-02-14 09:55:35 +01:00
4f24d61290 root: disable sentry's auto_session_tracking
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-14 09:44:12 +01:00
4c5c4dcf2c build(deps): bump @sentry/tracing from 6.17.6 to 6.17.7 in /web (#2296) 2022-02-14 08:57:12 +01:00
660b5cb6c6 build(deps): bump chart.js from 3.7.0 to 3.7.1 in /web (#2297) 2022-02-14 08:56:52 +01:00
6ff1ea73a9 build(deps): bump @sentry/browser from 6.17.6 to 6.17.7 in /web (#2298) 2022-02-14 08:56:13 +01:00
3de224690a build(deps): bump sentry-sdk from 1.5.4 to 1.5.5 (#2303) 2022-02-14 08:56:02 +01:00
d4624b510a build(deps): bump eslint from 8.8.0 to 8.9.0 in /web (#2299) 2022-02-14 08:55:42 +01:00
8856d762d0 build(deps): bump @rollup/plugin-replace from 3.0.1 to 3.1.0 in /web (#2300) 2022-02-14 08:55:27 +01:00
5d1cbf14d1 build(deps): bump actions/github-script from 5 to 6 (#2301) 2022-02-14 08:55:11 +01:00
6d5207f644 build(deps-dev): bump pytest from 7.0.0 to 7.0.1 (#2302) 2022-02-14 08:54:53 +01:00
3b6497cd51 outposts: ensure keypair is set for SSH connections
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-13 15:39:37 +01:00
ff7320b0f8 website/docs: update nginx ingress docs again
closes #2235

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-13 14:48:47 +01:00
e5a393c534 internal: increase logging for no hostname found
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-13 14:36:56 +01:00
bb4be944dc sources/ldap: use merger that only appends unique items to list
closes #2211

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-13 14:20:13 +01:00
21efee8f44 admin: add additional logging when restarting a task
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-12 18:40:21 +01:00
f61549a60f providers/proxy: enable TLS in ingress via traefik annotation
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1997
2022-02-12 18:35:24 +01:00
0a7bafd1b2 website/docs: add nginx note for domain auth
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-12 18:14:14 +01:00
b3987c5fa0 website/docs: update nginx ingress docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2235
2022-02-12 18:06:04 +01:00
0da043a9fe outposts: make local discovery configurable
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-12 17:27:41 +01:00
f336f204cb stages/authenticator_validate: fix handling when single configuration stage is selected
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-12 17:27:33 +01:00
3bfcf18492 build(deps): bump follow-redirects from 1.14.6 to 1.14.8 in /website (#2293)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.6 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.6...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-12 16:59:10 +01:00
dfafe8b43d web: Update Web API Client version (#2292)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-02-12 16:58:10 +01:00
b5d43b15f8 providers/oauth2: add support for explicit response_mode
closes #1953

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-12 16:56:47 +01:00
2ccab75021 stages/authenticator_validate: add ability to select multiple configuration stages which the user can choose
closes #1843

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-12 16:55:50 +01:00
9070df6c26 website/docs: revert to akprox for now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-11 23:37:46 +01:00
a1c8ad55ad web: add german locale
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-11 22:09:05 +01:00
872c05c690 Translate /web/src/locales/en.po in de (#2291)
translation completed for the source file '/web/src/locales/en.po'
on the 'de' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-11 20:16:47 +01:00
a9528dc1b5 build(deps): bump golang from 1.17.6-bullseye to 1.17.7-bullseye (#2286) 2022-02-11 09:45:53 +01:00
0e59ade1f2 build(deps): bump rollup from 2.67.1 to 2.67.2 in /web (#2287) 2022-02-11 09:45:35 +01:00
5ac49c695d build(deps): bump country-flag-icons from 1.4.20 to 1.4.21 in /web (#2288) 2022-02-11 09:45:22 +01:00
3a30ecbe76 build(deps-dev): bump importlib-metadata from 4.10.1 to 4.11.0 (#2289) 2022-02-11 09:45:03 +01:00
1f838bb2aa outposts/proxy: add X-Forwarded-Host since Host now gets changed by the proxy
closes #2284

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-10 23:09:55 +01:00
cc42830e23 website/integrations: add Paperless-ng instructions (#2225)
* Update instructions

I've updated the steps to provide some clarity around certain areas that tripped me up as a newcomer to authentik trying to follow these instructions.

* Added Paperless

Added authentik instructions for Paperless-ng

* Moved to paperless-ng directory

* Minor update to remove redundant part

Removed example authentik.company as these instructions do not require referencing authentik host name directly.

* Added Paperless-ng

* Typo fix

* Formatting changes

Updated changes based on feedback
2022-02-10 09:45:22 +01:00
593eb959ca Translate /web/src/locales/en.po in zh-Hans (#2278)
translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-10 09:44:55 +01:00
5bb6785ad6 Translate /web/src/locales/en.po in zh-Hant (#2279)
translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hant' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-10 09:44:47 +01:00
535c11a729 Translate /web/src/locales/en.po in zh_TW (#2280)
translation completed for the source file '/web/src/locales/en.po'
on the 'zh_TW' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-10 09:44:39 +01:00
a0fa8d8524 web: Update Web API Client version (#2277)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-02-09 22:46:16 +01:00
c14025c579 Merge branch 'version-2022.1'
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	poetry.lock
2022-02-09 22:45:26 +01:00
8bc3db7c90 release: 2022.1.5 2022-02-09 22:42:34 +01:00
e194715c3e internal: fix CSRF error caused by Host header
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 14:34:55 +01:00
787f02d5dc Translate /web/src/locales/en.po in pl (#2274)
translation completed for the source file '/web/src/locales/en.po'
on the 'pl' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-09 14:07:05 +01:00
a0ed01a610 Translate /web/src/locales/en.po in pl_PL (#2275)
translation completed for the source file '/web/src/locales/en.po'
on the 'pl_PL' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-09 14:06:41 +01:00
02ba493759 internal: trace headers and url for backend requests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 12:48:17 +01:00
a7fea5434d internal: remove uvicorn server header
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 12:38:47 +01:00
4fb783e953 internal: improve error handling for internal reverse proxy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 12:33:37 +01:00
affbf85699 internal: don't attempt to lookup SNI Certificate if no SNI is sent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 12:33:25 +01:00
0d92112a3f website/docs: add backend_override docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 10:41:42 +01:00
b1ad3ec9db website/docs: highlight breaking nginx header change
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 10:33:04 +01:00
c0601baca6 web: add additional locales
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-09 10:09:07 +01:00
057c5c5e9a build(deps): bump @sentry/tracing from 6.17.5 to 6.17.6 in /web (#2270) 2022-02-09 09:04:15 +01:00
05429ab848 build(deps): bump @babel/plugin-proposal-decorators in /web (#2272) 2022-02-09 09:04:02 +01:00
b66d51a699 Translate /web/src/locales/en.po in zh-Hans (#2267) 2022-02-09 09:03:51 +01:00
f834bc0ff2 Translate /web/src/locales/en.po in zh-Hant (#2269) 2022-02-09 09:03:29 +01:00
93fd883d7a Translate /web/src/locales/en.po in zh_TW (#2268) 2022-02-09 09:03:16 +01:00
7e080d4d68 build(deps): bump @babel/core from 7.17.0 to 7.17.2 in /web (#2271) 2022-02-09 09:02:34 +01:00
3e3ca22d04 build(deps): bump @sentry/browser from 6.17.5 to 6.17.6 in /web (#2273) 2022-02-09 09:02:15 +01:00
e741caa6b3 core: allow formatting strings to be used for applications' launch URLs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-08 23:46:23 +01:00
4343246a41 *: rename akprox to outpost.goauthentik.io (#2266)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-08 20:25:38 +01:00
3f6f83b4b6 web/admin: fix mismatched icons in overview and lists
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-08 19:03:57 +01:00
c63e1c9b87 outposts: fix compare_ports to support both service and container ports
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-08 17:40:49 +01:00
f44cf06d22 outposts: fix service reconciler re-creating services
closes #2095

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-08 17:23:00 +01:00
3f609b8601 Translate /web/src/locales/en.po in zh_TW (#2263)
translation completed for the source file '/web/src/locales/en.po'
on the 'zh_TW' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-08 16:36:25 +01:00
edd89b44a4 Translate /web/src/locales/en.po in zh-Hans (#2262)
translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-08 16:36:12 +01:00
3e58748862 Translate /web/src/locales/en.po in zh-Hant (#2261)
translation completed for the source file '/web/src/locales/en.po'
on the 'zh-Hant' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-08 16:36:02 +01:00
7088a6b0e6 providers/proxy: fix Host/:Authority not being modified
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-08 16:30:26 +01:00
6c880e0e62 website/docs: Enable 'secure' option for pwgen (#2260)
* Enable 'secure' option for pwgen

As per the [pwgen manual](https://linux.die.net/man/1/pwgen, "pwgen manual"), the "-s"(secure) option instructs pwgen to generate completely random passwords, where as the default for pwgen is to generate more memorable passwords. Since, the passwords generated in this part of the installation process are to be "remembered" by the dot env file, I believe that users may benefit from the additional entropy provided by the "-s" option in pwgen.

* Enable 'secure' option for pwgen
2022-02-08 12:24:29 +01:00
cb1e70be7f website/integrations: add documentation for roundcube webmail client (#2104)
* Add documentation for roundcube webmail client

Includes required dovecot configuration snippet.

* added roundcube to sidebar links

* fixed typo

* clean up formatting 

Tighten up extra info and match format to other integration documents

* fix roundcube wiki url display
2022-02-08 12:24:14 +01:00
6ba150f737 build(deps): bump @sentry/browser from 6.17.4 to 6.17.5 in /web (#2252)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 6.17.4 to 6.17.5.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.17.4...6.17.5)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2022-02-08 09:49:33 +01:00
131769ea73 build(deps): bump @typescript-eslint/parser in /web (#2253)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.10.2 to 5.11.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.11.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-02-08 09:49:15 +01:00
e68adbb30d build(deps): bump rollup from 2.67.0 to 2.67.1 in /web (#2254)
Bumps [rollup](https://github.com/rollup/rollup) from 2.67.0 to 2.67.1.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.67.0...v2.67.1)

---
updated-dependencies:
- dependency-name: rollup
  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>
2022-02-08 09:48:54 +01:00
f1eef09099 build(deps): bump @sentry/tracing from 6.17.4 to 6.17.5 in /web (#2255)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.17.4 to 6.17.5.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.17.4...6.17.5)

---
updated-dependencies:
- dependency-name: "@sentry/tracing"
  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>
2022-02-08 09:48:46 +01:00
5ab3c7fa9f build(deps): bump lit from 2.1.2 to 2.1.3 in /web (#2256)
Bumps [lit](https://github.com/lit/lit/tree/HEAD/packages/lit) from 2.1.2 to 2.1.3.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/lit/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/lit@2.1.3/packages/lit)

---
updated-dependencies:
- dependency-name: lit
  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>
2022-02-08 09:48:41 +01:00
d0cec39a0f build(deps): bump @typescript-eslint/eslint-plugin in /web (#2257)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.10.2 to 5.11.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.11.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-02-08 09:48:00 +01:00
e15f53a39a build(deps): bump @fortawesome/fontawesome-free in /web (#2258)
Bumps [@fortawesome/fontawesome-free](https://github.com/FortAwesome/Font-Awesome) from 5.15.4 to 6.0.0.
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/master/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/5.15.4...6.0.0)

---
updated-dependencies:
- dependency-name: "@fortawesome/fontawesome-free"
  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>
2022-02-08 09:47:44 +01:00
25fb995663 build(deps): bump twisted from 21.7.0 to 22.1.0 (#2259)
Bumps [twisted](https://github.com/twisted/twisted) from 21.7.0 to 22.1.0.
- [Release notes](https://github.com/twisted/twisted/releases)
- [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst)
- [Commits](https://github.com/twisted/twisted/compare/twisted-21.7.0...twisted-22.1.0)

---
updated-dependencies:
- dependency-name: twisted
  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>
2022-02-08 09:44:32 +01:00
eac658c64f web: update background image
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-07 20:46:47 +01:00
15e2032493 stages/authenticator_validate: handle non-existent device_challenges
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-07 20:31:49 +01:00
c87f6cd9d9 outposts: remove node_port on V1ServicePort checks to prevent service creation loops
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2095
2022-02-07 20:26:14 +01:00
e758995458 providers/proxy: improve error handling for invalid backend_override
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-07 19:59:06 +01:00
20c284a188 website/docs: improve docs for application access
closes #2245

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-07 19:42:42 +01:00
b0936ea8f3 sources/ldap: log entire exception
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-07 19:37:39 +01:00
bfc0f4a413 build(deps): bump github.com/go-openapi/runtime from 0.22.0 to 0.23.0 (#2249)
Bumps [github.com/go-openapi/runtime](https://github.com/go-openapi/runtime) from 0.22.0 to 0.23.0.
- [Release notes](https://github.com/go-openapi/runtime/releases)
- [Commits](https://github.com/go-openapi/runtime/compare/v0.22.0...v0.23.0)

---
updated-dependencies:
- dependency-name: github.com/go-openapi/runtime
  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>
2022-02-07 10:04:05 +01:00
1a9a90cf6a build(deps): bump @formatjs/intl-listformat from 6.5.1 to 6.5.2 in /web (#2248)
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 6.5.1 to 6.5.2.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@6.5.1...@formatjs/intl-listformat@6.5.2)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  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>
2022-02-07 10:03:36 +01:00
00f1a6fa48 build(deps): bump github.com/go-openapi/strfmt from 0.21.1 to 0.21.2 (#2250)
Bumps [github.com/go-openapi/strfmt](https://github.com/go-openapi/strfmt) from 0.21.1 to 0.21.2.
- [Release notes](https://github.com/go-openapi/strfmt/releases)
- [Commits](https://github.com/go-openapi/strfmt/compare/v0.21.1...v0.21.2)

---
updated-dependencies:
- dependency-name: github.com/go-openapi/strfmt
  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>
2022-02-07 10:03:20 +01:00
33754a06d2 website/integrations: update gitea integration documentation (#2182)
Newer gitea versions now expose "additional OIDC mapping" to admin GUI.
The configuration file change required in previous versions can now be
done in the GUI.
2022-02-06 15:17:52 +01:00
69b838e1cf web: Update Web API Client version (#2244)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-02-05 18:56:13 +01:00
d5e04a2301 *: remove deprecated backup (#2129)
* *: remove backup

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

* fix lint

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

* website/docs: add docs

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

* *: final cleanup

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

* ci: use correct pyproject when migrating from stable

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

* website/docs: fix broken docs

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-05 18:54:15 +01:00
fbf251280f core: compile backend translations (#2243)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-02-05 16:52:38 +01:00
eaadf62f01 Apply translations in zh-Hant (#2242)
translation completed for the source file '/locale/en/LC_MESSAGES/django.po'
on the 'zh-Hant' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-05 16:23:51 +01:00
8c33e7a7c1 Apply translations in zh_TW (#2241)
translation completed for the source file '/locale/en/LC_MESSAGES/django.po'
on the 'zh_TW' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-05 16:23:43 +01:00
a7d9a80a28 Apply translations in zh-Hans (#2240)
translation completed for the source file '/locale/en/LC_MESSAGES/django.po'
on the 'zh-Hans' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-05 16:23:36 +01:00
2ea5dce8d3 build(deps): bump uvicorn from 0.17.3 to 0.17.4 (#2238)
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.17.3 to 0.17.4.
- [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.17.3...0.17.4)

---
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>
2022-02-05 16:23:27 +01:00
14bf01efe4 build(deps-dev): bump pytest from 6.2.5 to 7.0.0 (#2237)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.5 to 7.0.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.5...7.0.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-05 16:23:19 +01:00
67b24a60e4 build(deps): bump boto3 from 1.20.48 to 1.20.49 (#2236)
Bumps [boto3](https://github.com/boto/boto3) from 1.20.48 to 1.20.49.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.20.48...1.20.49)

---
updated-dependencies:
- dependency-name: boto3
  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>
2022-02-05 16:23:03 +01:00
e6775297cb build(deps): bump pycryptodome from 3.14.0 to 3.14.1 (#2239)
Bumps [pycryptodome](https://github.com/Legrandin/pycryptodome) from 3.14.0 to 3.14.1.
- [Release notes](https://github.com/Legrandin/pycryptodome/releases)
- [Changelog](https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst)
- [Commits](https://github.com/Legrandin/pycryptodome/compare/v3.14.0...v3.14.1)

---
updated-dependencies:
- dependency-name: pycryptodome
  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>
2022-02-05 16:22:51 +01:00
4e4e2b36b6 sources/saml: fix server error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-05 15:41:26 +01:00
3189c56fc3 website/docs: default to upgrade with install flag set (#2234) 2022-02-04 22:36:34 +01:00
5b5ea47b7a Translate /web/src/locales/en.po in pl_PL (#2233)
translation completed for the source file '/web/src/locales/en.po'
on the 'pl_PL' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2022-02-04 21:59:00 +01:00
caa382f898 build(deps): bump @trivago/prettier-plugin-sort-imports in /web (#2227)
Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/master/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v3.1.1...v3.2.0)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  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>
2022-02-04 10:17:21 +01:00
2d63488197 build(deps): bump boto3 from 1.20.47 to 1.20.48 (#2228)
Bumps [boto3](https://github.com/boto/boto3) from 1.20.47 to 1.20.48.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.20.47...1.20.48)

---
updated-dependencies:
- dependency-name: boto3
  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>
2022-02-04 10:16:52 +01:00
c1c8e4c8d4 build(deps): bump uvicorn from 0.17.1 to 0.17.3 (#2229)
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.17.1 to 0.17.3.
- [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.17.1...0.17.3)

---
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>
2022-02-04 10:16:37 +01:00
a0e451c5e5 website/integrations: clarify some steps Nextcloud SAML (#2222)
I've updated the steps to provide some clarity around certain areas that tripped me up as a newcomer to authentik trying to follow these instructions.
2022-02-03 23:15:57 +01:00
eaba8006e6 sources/saml: fix incorrect ProtocolBinding being sent
closes #2213

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-03 18:20:06 +01:00
39ff202f8c outposts: fix channel not always having a logger attribute
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-03 17:58:54 +01:00
654e0d6245 providers/proxy: fix nil error in claims
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-02-03 17:58:38 +01:00
ec04443493 build(deps): bump @babel/plugin-proposal-decorators in /web (#2215)
Bumps [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) from 7.16.7 to 7.17.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.0/packages/babel-plugin-proposal-decorators)

---
updated-dependencies:
- dependency-name: "@babel/plugin-proposal-decorators"
  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>
2022-02-03 09:40:17 +01:00
d247c262af build(deps): bump @sentry/tracing from 6.17.3 to 6.17.4 in /web (#2214)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.17.3 to 6.17.4.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.17.3...6.17.4)

---
updated-dependencies:
- dependency-name: "@sentry/tracing"
  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>
2022-02-03 09:39:32 +01:00
dff49b2bef build(deps): bump @sentry/browser from 6.17.3 to 6.17.4 in /web (#2216)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 6.17.3 to 6.17.4.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.17.3...6.17.4)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2022-02-03 09:38:53 +01:00
50666a76fb build(deps): bump flowchart.js from 1.17.0 to 1.17.1 in /web (#2217)
Bumps [flowchart.js](https://github.com/adrai/flowchart.js) from 1.17.0 to 1.17.1.
- [Release notes](https://github.com/adrai/flowchart.js/releases)
- [Changelog](https://github.com/adrai/flowchart.js/blob/master/releasenotes.md)
- [Commits](https://github.com/adrai/flowchart.js/compare/v1.17.0...v1.17.1)

---
updated-dependencies:
- dependency-name: flowchart.js
  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>
2022-02-03 09:38:43 +01:00
b51a7f9746 build(deps): bump @babel/plugin-transform-runtime in /web (#2218)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.10 to 7.17.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.0/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  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>
2022-02-03 09:38:32 +01:00
001dfd9f6c build(deps): bump @babel/core from 7.16.12 to 7.17.0 in /web (#2219)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.16.12 to 7.17.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.17.0/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  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>
2022-02-03 09:38:21 +01:00
5e4fbeeb25 build(deps): bump rollup from 2.66.1 to 2.67.0 in /web (#2220)
Bumps [rollup](https://github.com/rollup/rollup) from 2.66.1 to 2.67.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v2.66.1...v2.67.0)

---
updated-dependencies:
- dependency-name: rollup
  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>
2022-02-03 09:38:03 +01:00
2c910bf6ca build(deps): bump boto3 from 1.20.46 to 1.20.47 (#2221)
Bumps [boto3](https://github.com/boto/boto3) from 1.20.46 to 1.20.47.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.20.46...1.20.47)

---
updated-dependencies:
- dependency-name: boto3
  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>
2022-02-03 09:37:26 +01:00
9b11319e81 build(deps-dev): bump coverage from 6.3 to 6.3.1 (#2209)
Bumps [coverage](https://github.com/nedbat/coveragepy) from 6.3 to 6.3.1.
- [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/6.3...6.3.1)

---
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>
2022-02-02 09:49:44 +01:00
40dc4b3fb8 build(deps): bump postcss from 8.4.5 to 8.4.6 in /website (#2207) 2022-02-02 09:41:37 +01:00
0e37b98968 build(deps): bump drf-spectacular from 0.21.1 to 0.21.2 (#2210) 2022-02-02 09:40:22 +01:00
7e132eb014 web: Update Web API Client version (#2206)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-02-01 21:04:47 +01:00
126 changed files with 38337 additions and 1524 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2022.1.5
current_version = 2022.2.1
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)

View File

@ -86,10 +86,9 @@ jobs:
cp authentik/lib/default.yml local.env.yml
cp -R .github ..
cp -R scripts ..
cp -R poetry.lock pyproject.toml ..
git checkout $(git describe --abbrev=0 --match 'version/*')
rm -rf .github/ scripts/
mv ../.github ../scripts ../poetry.lock ../pyproject.toml .
mv ../.github ../scripts .
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}

View File

@ -30,14 +30,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2022.1.5,
beryju/authentik:2022.2.1,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2022.1.5,
ghcr.io/goauthentik/server:2022.2.1,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64
context: .
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2022.1.5', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2022.2.1', 'rc') }}
run: |
docker pull beryju/authentik:latest
docker tag beryju/authentik:latest beryju/authentik:stable
@ -78,14 +78,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-${{ matrix.type }}:2022.1.5,
beryju/authentik-${{ matrix.type }}:2022.2.1,
beryju/authentik-${{ matrix.type }}:latest,
ghcr.io/goauthentik/${{ matrix.type }}:2022.1.5,
ghcr.io/goauthentik/${{ matrix.type }}:2022.2.1,
ghcr.io/goauthentik/${{ matrix.type }}:latest
file: ${{ matrix.type }}.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2022.1.5', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2022.2.1', 'rc') }}
run: |
docker pull beryju/authentik-${{ matrix.type }}:latest
docker tag beryju/authentik-${{ matrix.type }}:latest beryju/authentik-${{ matrix.type }}:stable
@ -170,7 +170,7 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2022.1.5
version: authentik@2022.2.1
environment: beryjuorg-prod
sourcemaps: './web/dist'
url_prefix: '~/static/dist'

View File

@ -27,7 +27,7 @@ jobs:
docker-compose run -u root server test
- name: Extract version number
id: get_version
uses: actions/github-script@v5
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@ -16,7 +16,7 @@ ENV NODE_ENV=production
RUN cd /work/web && npm i && npm run build
# Stage 3: Build go proxy
FROM docker.io/golang:1.17.6-bullseye AS builder
FROM docker.io/golang:1.17.7-bullseye AS builder
WORKDIR /work

View File

@ -6,8 +6,8 @@
| Version | Supported |
| ---------- | ------------------ |
| 2021.10.x | :white_check_mark: |
| 2021.12.x | :white_check_mark: |
| 2022.1.x | :white_check_mark: |
| 2022.2.x | :white_check_mark: |
## Reporting a Vulnerability

View File

@ -2,7 +2,7 @@
from os import environ
from typing import Optional
__version__ = "2022.1.5"
__version__ = "2022.2.1"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -12,10 +12,13 @@ from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from structlog.stdlib import get_logger
from authentik.core.api.utils import PassiveSerializer
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
LOGGER = get_logger()
class TaskSerializer(PassiveSerializer):
"""Serialize TaskInfo and TaskResult"""
@ -89,6 +92,7 @@ class TaskViewSet(ViewSet):
try:
task_module = import_module(task.task_call_module)
task_func = getattr(task_module, task.task_call_func)
LOGGER.debug("Running task", task=task_func)
task_func.delay(*task.task_call_args, **task.task_call_kwargs)
messages.success(
self.request,
@ -96,6 +100,7 @@ class TaskViewSet(ViewSet):
)
return Response(status=204)
except (ImportError, AttributeError): # pragma: no cover
LOGGER.warning("Failed to run task, remove state", task=task)
# if we get an import error, the module path has probably changed
task.delete()
return Response(status=500)

View File

@ -1,10 +1,9 @@
"""core Configs API"""
from os import environ, path
from os import path
from django.conf import settings
from django.db import models
from drf_spectacular.utils import extend_schema
from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME
from rest_framework.fields import (
BooleanField,
CharField,
@ -28,7 +27,6 @@ class Capabilities(models.TextChoices):
CAN_SAVE_MEDIA = "can_save_media"
CAN_GEO_IP = "can_geo_ip"
CAN_BACKUP = "can_backup"
class ErrorReportingConfigSerializer(PassiveSerializer):
@ -65,13 +63,6 @@ class ConfigView(APIView):
caps.append(Capabilities.CAN_SAVE_MEDIA)
if GEOIP_READER.enabled:
caps.append(Capabilities.CAN_GEO_IP)
if SERVICE_HOST_ENV_NAME in environ:
# Running in k8s, only s3 backup is supported
if CONFIG.y("postgresql.s3_backup"):
caps.append(Capabilities.CAN_BACKUP)
else:
# Running in compose, backup is always supported
caps.append(Capabilities.CAN_BACKUP)
return caps
@extend_schema(responses={200: ConfigSerializer(many=False)})

View File

@ -56,7 +56,11 @@ class ApplicationSerializer(ModelSerializer):
if isinstance(user, SimpleLazyObject):
user._setup()
user = user._wrapped
return url % user.__dict__
try:
return url % user.__dict__
except ValueError as exc:
LOGGER.warning("Failed to format launch url", exc=exc)
return url
class Meta:

View File

@ -1,17 +1,7 @@
"""authentik core tasks"""
from datetime import datetime
from io import StringIO
from os import environ
from boto3.exceptions import Boto3Error
from botocore.exceptions import BotoCoreError, ClientError
from dbbackup.db.exceptions import CommandConnectorError
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core import management
from django.core.cache import cache
from django.utils.timezone import now
from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME
from structlog.stdlib import get_logger
from authentik.core.models import AuthenticatedSession, ExpiringModel
@ -21,7 +11,6 @@ from authentik.events.monitored_tasks import (
TaskResultStatus,
prefill_task,
)
from authentik.lib.config import CONFIG
from authentik.root.celery import CELERY_APP
LOGGER = get_logger()
@ -53,46 +42,3 @@ def clean_expired_models(self: MonitoredTask):
LOGGER.debug("Expired sessions", model=AuthenticatedSession, amount=amount)
messages.append(f"Expired {amount} {AuthenticatedSession._meta.verbose_name_plural}")
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, messages))
def should_backup() -> bool:
"""Check if we should be doing backups"""
if SERVICE_HOST_ENV_NAME in environ and not CONFIG.y("postgresql.s3_backup.bucket"):
LOGGER.info("Running in k8s and s3 backups are not configured, skipping")
return False
if not CONFIG.y_bool("postgresql.backup.enabled"):
return False
return True
@CELERY_APP.task(bind=True, base=MonitoredTask)
@prefill_task
def backup_database(self: MonitoredTask): # pragma: no cover
"""Database backup"""
self.result_timeout_hours = 25
if not should_backup():
self.set_status(TaskResult(TaskResultStatus.UNKNOWN, ["Backups are not configured."]))
return
try:
start = datetime.now()
out = StringIO()
management.call_command("dbbackup", quiet=True, stdout=out)
self.set_status(
TaskResult(
TaskResultStatus.SUCCESSFUL,
[
f"Successfully finished database backup {naturaltime(start)} {out.getvalue()}",
],
)
)
LOGGER.info("Successfully backed up database.")
except (
IOError,
BotoCoreError,
ClientError,
Boto3Error,
PermissionError,
CommandConnectorError,
ValueError,
) as exc:
self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc))

View File

@ -16,6 +16,7 @@
{% block head_before %}
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}">
<script src="{% static 'dist/poly.js' %}" type="module"></script>
{% block head %}
{% endblock %}

View File

@ -1,7 +1,5 @@
"""events GeoIP Reader"""
from datetime import datetime
from os import stat
from time import time
from typing import Optional, TypedDict
from geoip2.database import Reader
@ -46,14 +44,18 @@ class GeoIPReader:
LOGGER.warning("Failed to load GeoIP database", exc=exc)
def __check_expired(self):
"""Check if the geoip database has been opened longer than 8 hours,
and re-open it, as it will probably will have been re-downloaded"""
now = time()
diff = datetime.fromtimestamp(now) - datetime.fromtimestamp(self.__last_mtime)
diff_hours = diff.total_seconds() // 3600
if diff_hours >= 8:
LOGGER.info("GeoIP databased loaded too long, re-opening", diff=diff)
self.__open()
"""Check if the modification date of the GeoIP database has
changed, and reload it if so"""
path = CONFIG.y("geoip")
try:
mtime = stat(path).st_mtime
diff = self.__last_mtime < mtime
if diff > 0:
LOGGER.info("Found new GeoIP Database, reopening", diff=diff)
self.__open()
except OSError as exc:
LOGGER.warning("Failed to check GeoIP age", exc=exc)
return
@property
def enabled(self) -> bool:

View File

@ -5,16 +5,6 @@ postgresql:
user: authentik
port: 5432
password: 'env://POSTGRES_PASSWORD'
backup:
enabled: false
s3_backup:
access_key: ""
secret_key: ""
bucket: ""
region: eu-central-1
host: ""
location: ""
insecure_skip_verify: false
web:
listen: 0.0.0.0:9000
@ -65,6 +55,7 @@ outposts:
# %(version)s: Current version; 2021.4.1
# %(build_hash)s: Build hash if you're running a beta version
container_image_base: ghcr.io/goauthentik/%(type)s:%(version)s
discover: true
cookie_domain: null
disable_update_check: false

6
authentik/lib/merge.py Normal file
View File

@ -0,0 +1,6 @@
"""merge utils"""
from deepmerge import Merger
MERGE_LIST_UNIQUE = Merger(
[(list, ["append_unique"]), (dict, ["merge"]), (set, ["union"])], ["override"], ["override"]
)

View File

@ -3,8 +3,6 @@ from typing import Optional
from aioredis.errors import ConnectionClosedError, ReplyError
from billiard.exceptions import SoftTimeLimitExceeded, WorkerLostError
from botocore.client import ClientError
from botocore.exceptions import BotoCoreError
from celery.exceptions import CeleryError
from channels.middleware import BaseMiddleware
from channels_redis.core import ChannelFull
@ -81,9 +79,6 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
WorkerLostError,
CeleryError,
SoftTimeLimitExceeded,
# S3 errors
BotoCoreError,
ClientError,
# custom baseclass
SentryIgnoredException,
# ldap errors
@ -101,8 +96,6 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
return None
if "logger" in event:
if event["logger"] in [
"dbbackup",
"botocore",
"kombu",
"asyncio",
"multiprocessing",

View File

@ -3,6 +3,8 @@ import os
from pathlib import Path
from tempfile import gettempdir
from docker.errors import DockerException
from authentik.crypto.models import CertificateKeyPair
HEADER = "### Managed by authentik"
@ -27,6 +29,8 @@ class DockerInlineSSH:
def __init__(self, host: str, keypair: CertificateKeyPair) -> None:
self.host = host
self.keypair = keypair
if not self.keypair:
raise DockerException("keypair must be set for SSH connections")
self.config_path = Path("~/.ssh/config").expanduser()
self.header = f"{HEADER} - {self.host}\n"

View File

@ -23,6 +23,7 @@ from authentik.events.monitored_tasks import (
TaskResultStatus,
prefill_task,
)
from authentik.lib.config import CONFIG
from authentik.lib.utils.reflection import path_to_class
from authentik.outposts.controllers.base import BaseController, ControllerException
from authentik.outposts.controllers.docker import DockerClient
@ -231,6 +232,9 @@ def _outpost_single_update(outpost: Outpost, layer=None):
@CELERY_APP.task()
def outpost_local_connection():
"""Checks the local environment and create Service connections."""
if not CONFIG.y_bool("outposts.discover"):
LOGGER.debug("outpost integration discovery is disabled")
return
# Explicitly check against token filename, as that's
# only present when the integration is enabled
if Path(SERVICE_TOKEN_FILENAME).exists():

View File

@ -45,6 +45,13 @@ class GrantTypes(models.TextChoices):
HYBRID = "hybrid"
class ResponseMode(models.TextChoices):
"""https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#OAuth.Post"""
QUERY = "query"
FRAGMENT = "fragment"
class SubModes(models.TextChoices):
"""Mode after which 'sub' attribute is generateed, for compatibility reasons"""

View File

@ -43,7 +43,7 @@ class TestAuthorize(OAuthTestCase):
name="test",
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris="http://local.invalid/Foo",
)
with self.assertRaises(AuthorizeError):
request = self.factory.get(
@ -51,7 +51,7 @@ class TestAuthorize(OAuthTestCase):
data={
"response_type": "code",
"client_id": "test",
"redirect_uri": "http://local.invalid",
"redirect_uri": "http://local.invalid/Foo",
"request": "foo",
},
)
@ -105,26 +105,30 @@ class TestAuthorize(OAuthTestCase):
name="test",
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
redirect_uris="http://local.invalid/Foo",
)
request = self.factory.get(
"/",
data={
"response_type": "code",
"client_id": "test",
"redirect_uri": "http://local.invalid",
"redirect_uri": "http://local.invalid/Foo",
},
)
self.assertEqual(
OAuthAuthorizationParams.from_request(request).grant_type,
GrantTypes.AUTHORIZATION_CODE,
)
self.assertEqual(
OAuthAuthorizationParams.from_request(request).redirect_uri,
"http://local.invalid/Foo",
)
request = self.factory.get(
"/",
data={
"response_type": "id_token",
"client_id": "test",
"redirect_uri": "http://local.invalid",
"redirect_uri": "http://local.invalid/Foo",
"scope": "openid",
"state": "foo",
},
@ -140,7 +144,7 @@ class TestAuthorize(OAuthTestCase):
data={
"response_type": "id_token",
"client_id": "test",
"redirect_uri": "http://local.invalid",
"redirect_uri": "http://local.invalid/Foo",
"state": "foo",
},
)
@ -153,7 +157,7 @@ class TestAuthorize(OAuthTestCase):
data={
"response_type": "code token",
"client_id": "test",
"redirect_uri": "http://local.invalid",
"redirect_uri": "http://local.invalid/Foo",
"scope": "openid",
"state": "foo",
},
@ -167,7 +171,7 @@ class TestAuthorize(OAuthTestCase):
data={
"response_type": "invalid",
"client_id": "test",
"redirect_uri": "http://local.invalid",
"redirect_uri": "http://local.invalid/Foo",
},
)
OAuthAuthorizationParams.from_request(request)

View File

@ -44,6 +44,7 @@ from authentik.providers.oauth2.models import (
AuthorizationCode,
GrantTypes,
OAuth2Provider,
ResponseMode,
ResponseTypes,
)
from authentik.providers.oauth2.utils import HttpResponseRedirectScheme
@ -99,7 +100,7 @@ class OAuthAuthorizationParams:
# and POST request.
query_dict = request.POST if request.method == "POST" else request.GET
state = query_dict.get("state")
redirect_uri = query_dict.get("redirect_uri", "").lower()
redirect_uri = query_dict.get("redirect_uri", "")
response_type = query_dict.get("response_type", "")
grant_type = None
@ -153,7 +154,10 @@ class OAuthAuthorizationParams:
def check_redirect_uri(self):
"""Redirect URI validation."""
allowed_redirect_urls = self.provider.redirect_uris.split()
if not self.redirect_uri:
# We don't want to actually lowercase the final URL we redirect to,
# we only lowercase it for comparison
redirect_uri = self.redirect_uri.lower()
if not redirect_uri:
LOGGER.warning("Missing redirect uri.")
raise RedirectUriError("", allowed_redirect_urls)
@ -169,7 +173,7 @@ class OAuthAuthorizationParams:
allow=self.redirect_uri,
)
return
if self.redirect_uri not in [x.lower() for x in allowed_redirect_urls]:
if redirect_uri not in [x.lower() for x in allowed_redirect_urls]:
LOGGER.warning(
"Invalid redirect uri",
redirect_uri=self.redirect_uri,
@ -299,13 +303,23 @@ class OAuthFulfillmentStage(StageView):
code = self.params.create_code(self.request)
code.save(force_insert=True)
if self.params.grant_type == GrantTypes.AUTHORIZATION_CODE:
query_dict = self.request.POST if self.request.method == "POST" else self.request.GET
response_mode = ResponseMode.QUERY
# Get response mode from url param, otherwise decide based on grant type
if "response_mode" in query_dict:
response_mode = query_dict["response_mode"]
elif self.params.grant_type == GrantTypes.AUTHORIZATION_CODE:
response_mode = ResponseMode.QUERY
elif self.params.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID]:
response_mode = ResponseMode.FRAGMENT
if response_mode == ResponseMode.QUERY:
query_params["code"] = code.code
query_params["state"] = [str(self.params.state) if self.params.state else ""]
uri = uri._replace(query=urlencode(query_params, doseq=True))
return urlunsplit(uri)
if self.params.grant_type in [GrantTypes.IMPLICIT, GrantTypes.HYBRID]:
if response_mode == ResponseMode.FRAGMENT:
query_fragment = self.create_implicit_response(code)
uri = uri._replace(

View File

@ -12,4 +12,8 @@ class AuthentikProviderProxyConfig(AppConfig):
verbose_name = "authentik Providers.Proxy"
def ready(self) -> None:
from authentik.providers.proxy.tasks import proxy_set_defaults
import_module("authentik.providers.proxy.managed")
proxy_set_defaults.delay()

View File

@ -28,12 +28,12 @@ class ProxyDockerController(DockerController):
labels["traefik.enable"] = "true"
labels[
f"traefik.http.routers.{traefik_name}-router.rule"
] = f"Host({','.join(hosts)}) && PathPrefix(`/akprox`)"
] = f"Host({','.join(hosts)}) && PathPrefix(`/outpost.goauthentik.io`)"
labels[f"traefik.http.routers.{traefik_name}-router.tls"] = "true"
labels[f"traefik.http.routers.{traefik_name}-router.service"] = f"{traefik_name}-service"
labels[
f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.path"
] = "/akprox/ping"
] = "/outpost.goauthentik.io/ping"
labels[
f"traefik.http.services.{traefik_name}-service.loadbalancer.healthcheck.port"
] = "9300"

View File

@ -92,6 +92,8 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]):
# Buffer sizes for large headers with JWTs
"nginx.ingress.kubernetes.io/proxy-buffers-number": "4",
"nginx.ingress.kubernetes.io/proxy-buffer-size": "16k",
# Enable TLS in traefik
"traefik.ingress.kubernetes.io/router.tls": "true",
}
annotations.update(self.controller.outpost.config.kubernetes_ingress_annotations)
return annotations
@ -126,7 +128,7 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]):
port=V1ServiceBackendPort(name="http"),
),
),
path="/akprox",
path="/outpost.goauthentik.io",
path_type="ImplementationSpecific",
)
]

View File

@ -119,7 +119,10 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware])
),
spec=TraefikMiddlewareSpec(
forwardAuth=TraefikMiddlewareSpecForwardAuth(
address=f"http://{self.name}.{self.namespace}:9000/akprox/auth/traefik",
address=(
f"http://{self.name}.{self.namespace}:9000/"
"outpost.goauthentik.io/auth/traefik"
),
authResponseHeaders=[
"X-authentik-username",
"X-authentik-groups",

View File

@ -27,7 +27,7 @@ def get_cookie_secret():
def _get_callback_url(uri: str) -> str:
return urljoin(uri, "/akprox/callback")
return urljoin(uri, "outpost.goauthentik.io/callback")
class ProxyMode(models.TextChoices):

View File

@ -0,0 +1,11 @@
"""proxy provider tasks"""
from authentik.providers.proxy.models import ProxyProvider
from authentik.root.celery import CELERY_APP
@CELERY_APP.task()
def proxy_set_defaults():
"""Ensure correct defaults are set for all providers"""
for provider in ProxyProvider.objects.all():
provider.set_oauth_defaults()
provider.save()

View File

@ -6,7 +6,6 @@ import os
import sys
from hashlib import sha512
from json import dumps
from tempfile import gettempdir
from time import time
from urllib.parse import quote_plus
@ -137,7 +136,6 @@ INSTALLED_APPS = [
"guardian",
"django_prometheus",
"channels",
"dbbackup",
]
GUARDIAN_MONKEY_PATCH = False
@ -357,32 +355,6 @@ CELERY_RESULT_BACKEND = (
f"{_redis_url}/{CONFIG.y('redis.message_queue_db')}{REDIS_CELERY_TLS_REQUIREMENTS}"
)
# Database backup
DBBACKUP_STORAGE = "django.core.files.storage.FileSystemStorage"
DBBACKUP_STORAGE_OPTIONS = {"location": "./backups" if DEBUG else "/backups"}
DBBACKUP_FILENAME_TEMPLATE = f"authentik-backup-{__version__}-{{datetime}}.sql"
DBBACKUP_CONNECTOR_MAPPING = {
"django_prometheus.db.backends.postgresql": "dbbackup.db.postgresql.PgDumpConnector",
}
DBBACKUP_TMP_DIR = gettempdir() if DEBUG else "/tmp" # nosec
DBBACKUP_CLEANUP_KEEP = 10
if CONFIG.y("postgresql.s3_backup.bucket", "") != "":
DBBACKUP_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
DBBACKUP_STORAGE_OPTIONS = {
"access_key": CONFIG.y("postgresql.s3_backup.access_key"),
"secret_key": CONFIG.y("postgresql.s3_backup.secret_key"),
"bucket_name": CONFIG.y("postgresql.s3_backup.bucket"),
"region_name": CONFIG.y("postgresql.s3_backup.region", "eu-central-1"),
"default_acl": "private",
"endpoint_url": CONFIG.y("postgresql.s3_backup.host"),
"location": CONFIG.y("postgresql.s3_backup.location", ""),
"verify": not CONFIG.y_bool("postgresql.s3_backup.insecure_skip_verify", False),
}
j_print(
"Database backup to S3 is configured",
host=CONFIG.y("postgresql.s3_backup.host"),
)
# Sentry integration
SENTRY_DSN = "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8"
@ -493,12 +465,9 @@ _LOGGING_HANDLER_MAP = {
"urllib3": "WARNING",
"websockets": "WARNING",
"daphne": "WARNING",
"dbbackup": "ERROR",
"kubernetes": "INFO",
"asyncio": "WARNING",
"aioredis": "WARNING",
"s3transfer": "WARNING",
"botocore": "WARNING",
}
for handler_name, level in _LOGGING_HANDLER_MAP.items():
# pyright: reportGeneralTypeIssues=false

View File

@ -1,13 +1,13 @@
"""Sync LDAP Users and groups into authentik"""
from typing import Any
from deepmerge import always_merger
from django.db.models.base import Model
from django.db.models.query import QuerySet
from structlog.stdlib import BoundLogger, get_logger
from authentik.core.exceptions import PropertyMappingExpressionException
from authentik.events.models import Event, EventAction
from authentik.lib.merge import MERGE_LIST_UNIQUE
from authentik.sources.ldap.auth import LDAP_DISTINGUISHED_NAME
from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
@ -123,8 +123,8 @@ class BaseLDAPSynchronizer:
continue
setattr(instance, key, value)
final_atttributes = {}
always_merger.merge(final_atttributes, instance.attributes)
always_merger.merge(final_atttributes, data.get("attributes", {}))
MERGE_LIST_UNIQUE.merge(final_atttributes, instance.attributes)
MERGE_LIST_UNIQUE.merge(final_atttributes, data.get("attributes", {}))
instance.attributes = final_atttributes
instance.save()
return (instance, False)

View File

@ -13,8 +13,8 @@ class AuthenticatorValidateStageSerializer(StageSerializer):
def validate_not_configured_action(self, value):
"""Ensure that a configuration stage is set when not_configured_action is configure"""
configuration_stage = self.initial_data.get("configuration_stage")
if value == NotConfiguredAction.CONFIGURE and configuration_stage is None:
configuration_stages = self.initial_data.get("configuration_stages")
if value == NotConfiguredAction.CONFIGURE and configuration_stages is None:
raise ValidationError(
(
'When "Not configured action" is set to "Configure", '
@ -29,7 +29,7 @@ class AuthenticatorValidateStageSerializer(StageSerializer):
fields = StageSerializer.Meta.fields + [
"not_configured_action",
"device_classes",
"configuration_stage",
"configuration_stages",
]
@ -38,5 +38,5 @@ class AuthenticatorValidateStageViewSet(UsedByMixin, ModelViewSet):
queryset = AuthenticatorValidateStage.objects.all()
serializer_class = AuthenticatorValidateStageSerializer
filterset_fields = ["name", "not_configured_action", "configuration_stage"]
filterset_fields = ["name", "not_configured_action", "configuration_stages"]
ordering = ["name"]

View File

@ -0,0 +1,44 @@
# Generated by Django 4.0.1 on 2022-01-05 22:09
from django.apps.registry import Apps
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def migrate_configuration_stage(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
db_alias = schema_editor.connection.alias
AuthenticatorValidateStage = apps.get_model(
"authentik_stages_authenticator_validate", "AuthenticatorValidateStage"
)
for stage in AuthenticatorValidateStage.objects.using(db_alias).all():
if stage.configuration_stage:
stage.configuration_stages.set([stage.configuration_stage])
stage.save()
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0021_auto_20211227_2103"),
("authentik_stages_authenticator_validate", "0009_default_stage"),
]
operations = [
migrations.AddField(
model_name="authenticatorvalidatestage",
name="configuration_stages",
field=models.ManyToManyField(
blank=True,
default=None,
help_text="Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.",
related_name="+",
to="authentik_flows.Stage",
),
),
migrations.RunPython(migrate_configuration_stage),
migrations.RemoveField(
model_name="authenticatorvalidatestage",
name="configuration_stage",
),
]

View File

@ -38,16 +38,14 @@ class AuthenticatorValidateStage(Stage):
choices=NotConfiguredAction.choices, default=NotConfiguredAction.SKIP
)
configuration_stage = models.ForeignKey(
configuration_stages = models.ManyToManyField(
Stage,
null=True,
blank=True,
default=None,
on_delete=models.SET_DEFAULT,
related_name="+",
help_text=_(
(
"Stage used to configure Authenticator when user doesn't have any compatible "
"Stages used to configure Authenticator when user doesn't have any compatible "
"devices. After this configuration Stage passes, the user is not prompted again."
)
),

View File

@ -1,10 +1,12 @@
"""Authenticator Validation"""
from django.http import HttpRequest, HttpResponse
from django_otp import devices_for_user
from rest_framework.fields import CharField, IntegerField, JSONField, ListField
from rest_framework.fields import CharField, IntegerField, JSONField, ListField, UUIDField
from rest_framework.serializers import ValidationError
from structlog.stdlib import get_logger
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import User
from authentik.events.models import Event, EventAction
from authentik.events.utils import cleanse_dict, sanitize_dict
from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge
@ -26,6 +28,18 @@ from authentik.stages.authenticator_webauthn.models import WebAuthnDevice
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
LOGGER = get_logger()
SESSION_STAGES = "goauthentik.io/stages/authenticator_validate/stages"
SESSION_SELECTED_STAGE = "goauthentik.io/stages/authenticator_validate/selected_stage"
SESSION_DEVICE_CHALLENGES = "goauthentik.io/stages/authenticator_validate/device_challenges"
class SelectableStageSerializer(PassiveSerializer):
"""Serializer for stages which can be selected by users"""
pk = UUIDField()
name = CharField()
verbose_name = CharField()
meta_model_name = CharField()
class AuthenticatorValidationChallenge(WithUserInfoChallenge):
@ -33,12 +47,14 @@ class AuthenticatorValidationChallenge(WithUserInfoChallenge):
device_challenges = ListField(child=DeviceChallenge())
component = CharField(default="ak-stage-authenticator-validate")
configuration_stages = ListField(child=SelectableStageSerializer())
class AuthenticatorValidationChallengeResponse(ChallengeResponse):
"""Challenge used for Code-based and WebAuthn authenticators"""
selected_challenge = DeviceChallenge(required=False)
selected_stage = CharField(required=False)
code = CharField(required=False)
webauthn = JSONField(required=False)
@ -46,7 +62,7 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse):
component = CharField(default="ak-stage-authenticator-validate")
def _challenge_allowed(self, classes: list):
device_challenges: list[dict] = self.stage.request.session.get("device_challenges")
device_challenges: list[dict] = self.stage.request.session.get(SESSION_DEVICE_CHALLENGES)
if not any(x["device_class"] in classes for x in device_challenges):
raise ValidationError("No compatible device class allowed")
@ -71,7 +87,7 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse):
def validate_selected_challenge(self, challenge: dict) -> dict:
"""Check which challenge the user has selected. Actual logic only used for SMS stage."""
# First check if the challenge is valid
for device_challenge in self.stage.request.session.get("device_challenges"):
for device_challenge in self.stage.request.session.get(SESSION_DEVICE_CHALLENGES):
if device_challenge.get("device_class", "") != challenge.get("device_class", ""):
raise ValidationError("invalid challenge selected")
if device_challenge.get("device_uid", "") != challenge.get("device_uid", ""):
@ -84,6 +100,15 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse):
select_challenge(self.stage.request, devices.first())
return challenge
def validate_selected_stage(self, stage_pk: str) -> str:
"""Check that the selected stage is valid"""
stages = self.stage.request.session.get(SESSION_STAGES, [])
if not any(str(stage.pk) == stage_pk for stage in stages):
raise ValidationError("Selected stage is invalid")
LOGGER.debug("Setting selected stage to ", stage=stage_pk)
self.stage.request.session[SESSION_SELECTED_STAGE] = stage_pk
return stage_pk
def validate(self, attrs: dict):
# Checking if the given data is from a valid device class is done above
# Here we only check if the any data was sent at all
@ -164,7 +189,7 @@ class AuthenticatorValidateStageView(ChallengeStageView):
else:
LOGGER.debug("No pending user, continuing")
return self.executor.stage_ok()
self.request.session["device_challenges"] = challenges
self.request.session[SESSION_DEVICE_CHALLENGES] = challenges
# No allowed devices
if len(challenges) < 1:
@ -175,35 +200,74 @@ class AuthenticatorValidateStageView(ChallengeStageView):
LOGGER.debug("Authenticator not configured, denying")
return self.executor.stage_invalid()
if stage.not_configured_action == NotConfiguredAction.CONFIGURE:
if not stage.configuration_stage:
Event.new(
EventAction.CONFIGURATION_ERROR,
message=(
"Authenticator validation stage is set to configure user "
"but no configuration flow is set."
),
stage=self,
).from_http(self.request).set_user(user).save()
return self.executor.stage_invalid()
LOGGER.debug("Authenticator not configured, sending user to configure")
# Because the foreign key to stage.configuration_stage points to
# a base stage class, we need to do another lookup
stage = Stage.objects.get_subclass(pk=stage.configuration_stage.pk)
# plan.insert inserts at 1 index, so when stage_ok pops 0,
# the configuration stage is next
self.executor.plan.insert_stage(stage)
return self.executor.stage_ok()
LOGGER.debug("Authenticator not configured, forcing configure")
return self.prepare_stages(user)
return super().get(request, *args, **kwargs)
def get_challenge(self) -> AuthenticatorValidationChallenge:
challenges = self.request.session.get("device_challenges")
if not challenges:
LOGGER.debug("Authenticator Validation stage ran without challenges")
def prepare_stages(self, user: User, *args, **kwargs) -> HttpResponse:
"""Check how the user can configure themselves. If no stages are set, return an error.
If a single stage is set, insert that stage directly. If multiple are selected, include
them in the challenge."""
stage: AuthenticatorValidateStage = self.executor.current_stage
if not stage.configuration_stages.exists():
Event.new(
EventAction.CONFIGURATION_ERROR,
message=(
"Authenticator validation stage is set to configure user "
"but no configuration flow is set."
),
stage=self,
).from_http(self.request).set_user(user).save()
return self.executor.stage_invalid()
if stage.configuration_stages.count() == 1:
next_stage = Stage.objects.get_subclass(pk=stage.configuration_stages.first().pk)
LOGGER.debug("Single stage configured, auto-selecting", stage=next_stage)
self.request.session[SESSION_SELECTED_STAGE] = next_stage
# Because that normal insetion only happens on post, we directly inject it here and
# return it
self.executor.plan.insert_stage(next_stage)
return self.executor.stage_ok()
stages = Stage.objects.filter(pk__in=stage.configuration_stages.all()).select_subclasses()
self.request.session[SESSION_STAGES] = stages
return super().get(self.request, *args, **kwargs)
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
res = super().post(request, *args, **kwargs)
if (
SESSION_SELECTED_STAGE in self.request.session
and self.executor.current_stage.not_configured_action == NotConfiguredAction.CONFIGURE
):
LOGGER.debug("Got selected stage in session, running that")
stage_pk = self.request.session.get(SESSION_SELECTED_STAGE)
# Because the foreign key to stage.configuration_stage points to
# a base stage class, we need to do another lookup
stage = Stage.objects.get_subclass(pk=stage_pk)
# plan.insert inserts at 1 index, so when stage_ok pops 0,
# the configuration stage is next
self.executor.plan.insert_stage(stage)
return self.executor.stage_ok()
return res
def get_challenge(self) -> AuthenticatorValidationChallenge:
challenges = self.request.session.get(SESSION_DEVICE_CHALLENGES, [])
stages = self.request.session.get(SESSION_STAGES, [])
stage_challenges = []
for stage in stages:
serializer = SelectableStageSerializer(
data={
"pk": stage.pk,
"name": stage.name,
"verbose_name": str(stage._meta.verbose_name),
"meta_model_name": f"{stage._meta.app_label}.{stage._meta.model_name}",
}
)
serializer.is_valid()
stage_challenges.append(serializer.data)
return AuthenticatorValidationChallenge(
data={
"type": ChallengeTypes.NATIVE.value,
"device_challenges": challenges,
"configuration_stages": stage_challenges,
}
)

View File

@ -43,8 +43,8 @@ class AuthenticatorValidateStageTests(FlowTestCase):
stage = AuthenticatorValidateStage.objects.create(
name="foo",
not_configured_action=NotConfiguredAction.CONFIGURE,
configuration_stage=conf_stage,
)
stage.configuration_stages.set([conf_stage])
flow = Flow.objects.create(name="test", slug="test", title="test")
FlowStageBinding.objects.create(target=flow, stage=conf_stage, order=0)
FlowStageBinding.objects.create(target=flow, stage=stage, order=1)

View File

@ -17,7 +17,7 @@ services:
image: redis:alpine
restart: unless-stopped
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.5}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.2.1}
restart: unless-stopped
command: server
environment:
@ -38,7 +38,7 @@ services:
- "0.0.0.0:${AUTHENTIK_PORT_HTTP:-9000}:9000"
- "0.0.0.0:${AUTHENTIK_PORT_HTTPS:-9443}:9443"
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.5}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.2.1}
restart: unless-stopped
command: worker
environment:

8
go.mod
View File

@ -8,16 +8,16 @@ require (
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/garyburd/redigo v1.6.2 // indirect
github.com/getsentry/sentry-go v0.12.0
github.com/go-ldap/ldap/v3 v3.4.1
github.com/go-openapi/runtime v0.22.0
github.com/go-openapi/strfmt v0.21.1
github.com/go-ldap/ldap/v3 v3.4.2
github.com/go-openapi/runtime v0.23.0
github.com/go-openapi/strfmt v0.21.2
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.3.0
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/sessions v1.2.1
github.com/gorilla/websocket v1.4.2
github.com/gorilla/websocket v1.5.0
github.com/imdario/mergo v0.3.12
github.com/mailru/easyjson v0.7.7 // indirect
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484

16
go.sum
View File

@ -125,8 +125,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-ldap/ldap/v3 v3.4.1 h1:fU/0xli6HY02ocbMuozHAYsaHLcnkLjvho2r5a34BUU=
github.com/go-ldap/ldap/v3 v3.4.1/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
github.com/go-ldap/ldap/v3 v3.4.2 h1:zFZKcXKLqZpFMrMQGHeHWKXbDTdNCmhGY9AK41zPh+8=
github.com/go-ldap/ldap/v3 v3.4.2/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
@ -183,8 +183,8 @@ github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29g
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
github.com/go-openapi/runtime v0.22.0 h1:vY2D0u807kkcwidaj0YJuq4zyAWQnjLNDpJcVBrUFNs=
github.com/go-openapi/runtime v0.22.0/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs=
github.com/go-openapi/runtime v0.23.0 h1:HX6ET2sHCIvaKeDDQoU01CtO1ekg5EkekHSkLTtWXH0=
github.com/go-openapi/runtime v0.23.0/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
@ -208,8 +208,8 @@ github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLs
github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc=
github.com/go-openapi/strfmt v0.20.2/go.mod h1:43urheQI9dNtE5lTZQfuFJvjYJKPrxicATpEfZwHUNk=
github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
github.com/go-openapi/strfmt v0.21.1 h1:G6s2t5V5kGCHLVbSdZ/6lI8Wm4OzoPFkc3/cjAsKQrM=
github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
github.com/go-openapi/strfmt v0.21.2 h1:5NDNgadiX1Vhemth/TH4gCGopWSTdDjxl60H3B7f+os=
github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
@ -334,8 +334,8 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=

View File

@ -25,4 +25,4 @@ func OutpostUserAgent() string {
return fmt.Sprintf("authentik-outpost@%s", FullVersion())
}
const VERSION = "2022.1.5"
const VERSION = "2022.2.1"

View File

@ -25,7 +25,7 @@ var (
func RunServer() {
m := mux.NewRouter()
l := log.WithField("logger", "authentik.outpost.metrics")
m.HandleFunc("/akprox/ping", func(rw http.ResponseWriter, r *http.Request) {
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(204)
})
m.Path("/metrics").Handler(promhttp.Handler())

View File

@ -78,7 +78,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore
oauth2Config := oauth2.Config{
ClientID: *p.ClientId,
ClientSecret: *p.ClientSecret,
RedirectURL: urlJoin(p.ExternalHost, "/akprox/callback"),
RedirectURL: urlJoin(p.ExternalHost, "/outpost.goauthentik.io/callback"),
Endpoint: endpoint.Endpoint,
Scopes: p.ScopesToRequest,
}
@ -145,10 +145,10 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore
mux.Use(sentryhttp.New(sentryhttp.Options{}).Handle)
// Support /start and /sign_in for backwards compatibility
mux.HandleFunc("/akprox/start", a.handleRedirect)
mux.HandleFunc("/akprox/sign_in", a.handleRedirect)
mux.HandleFunc("/akprox/callback", a.handleCallback)
mux.HandleFunc("/akprox/sign_out", a.handleSignOut)
mux.HandleFunc("/outpost.goauthentik.io/start", a.handleRedirect)
mux.HandleFunc("/outpost.goauthentik.io/sign_in", a.handleRedirect)
mux.HandleFunc("/outpost.goauthentik.io/callback", a.handleCallback)
mux.HandleFunc("/outpost.goauthentik.io/sign_out", a.handleSignOut)
switch *p.Mode {
case api.PROXYMODE_PROXY:
err = a.configureProxy()

View File

@ -18,7 +18,7 @@ func (a *Application) ErrorPage(rw http.ResponseWriter, r *http.Request, err str
data := ErrorPageData{
Title: "Bad Gateway",
Message: "Error proxying to upstream server",
ProxyPrefix: "/akprox",
ProxyPrefix: "/outpost.goauthentik.io",
}
if claims != nil && len(err) > 0 {
data.Message = err

View File

@ -12,15 +12,15 @@ import (
)
func (a *Application) configureForward() error {
a.mux.HandleFunc("/akprox/auth", func(rw http.ResponseWriter, r *http.Request) {
a.mux.HandleFunc("/outpost.goauthentik.io/auth", func(rw http.ResponseWriter, r *http.Request) {
if _, ok := r.URL.Query()["traefik"]; ok {
a.forwardHandleTraefik(rw, r)
return
}
a.forwardHandleNginx(rw, r)
})
a.mux.HandleFunc("/akprox/auth/traefik", a.forwardHandleTraefik)
a.mux.HandleFunc("/akprox/auth/nginx", a.forwardHandleNginx)
a.mux.HandleFunc("/outpost.goauthentik.io/auth/traefik", a.forwardHandleTraefik)
a.mux.HandleFunc("/outpost.goauthentik.io/auth/nginx", a.forwardHandleNginx)
return nil
}
@ -49,8 +49,8 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque
a.log.Trace("path can be accessed without authentication")
return
}
if strings.HasPrefix(r.Header.Get("X-Forwarded-Uri"), "/akprox") {
a.log.WithField("url", r.URL.String()).Trace("path begins with /akprox, allowing access")
if strings.HasPrefix(r.Header.Get("X-Forwarded-Uri"), "/outpost.goauthentik.io") {
a.log.WithField("url", r.URL.String()).Trace("path begins with /outpost.goauthentik.io, allowing access")
return
}
host := ""
@ -80,7 +80,7 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque
if proto != "" {
proto = proto + ":"
}
rdFinal := fmt.Sprintf("%s//%s%s", proto, host, "/akprox/start")
rdFinal := fmt.Sprintf("%s//%s%s", proto, host, "/outpost.goauthentik.io/start")
a.log.WithField("url", rdFinal).Debug("Redirecting to login")
http.Redirect(rw, r, rdFinal, http.StatusTemporaryRedirect)
}
@ -119,8 +119,8 @@ func (a *Application) forwardHandleNginx(rw http.ResponseWriter, r *http.Request
}
if fwd.String() != r.URL.String() {
if strings.HasPrefix(fwd.Path, "/akprox") {
a.log.WithField("url", r.URL.String()).Trace("path begins with /akprox, allowing access")
if strings.HasPrefix(fwd.Path, "/outpost.goauthentik.io") {
a.log.WithField("url", r.URL.String()).Trace("path begins with /outpost.goauthentik.io, allowing access")
return
}
}

View File

@ -12,7 +12,7 @@ import (
func TestForwardHandleNginx_Single_Blank(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/nginx", nil)
rr := httptest.NewRecorder()
a.forwardHandleNginx(rr, req)
@ -22,7 +22,7 @@ func TestForwardHandleNginx_Single_Blank(t *testing.T) {
func TestForwardHandleNginx_Single_Skip(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/nginx", nil)
req.Header.Set("X-Original-URL", "http://test.goauthentik.io/skip")
rr := httptest.NewRecorder()
@ -33,7 +33,7 @@ func TestForwardHandleNginx_Single_Skip(t *testing.T) {
func TestForwardHandleNginx_Single_Headers(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/nginx", nil)
req.Header.Set("X-Original-URL", "http://test.goauthentik.io/app")
rr := httptest.NewRecorder()
@ -47,7 +47,7 @@ func TestForwardHandleNginx_Single_Headers(t *testing.T) {
func TestForwardHandleNginx_Single_URI(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "https://foo.bar/akprox/auth/nginx", nil)
req, _ := http.NewRequest("GET", "https://foo.bar/outpost.goauthentik.io/auth/nginx", nil)
req.Header.Set("X-Original-URI", "/app")
rr := httptest.NewRecorder()
@ -61,7 +61,7 @@ func TestForwardHandleNginx_Single_URI(t *testing.T) {
func TestForwardHandleNginx_Single_Claims(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/nginx", nil)
req.Header.Set("X-Original-URI", "/")
rr := httptest.NewRecorder()
@ -108,7 +108,7 @@ func TestForwardHandleNginx_Domain_Blank(t *testing.T) {
a := newTestApplication()
a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr()
a.proxyConfig.CookieDomain = api.PtrString("foo")
req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/nginx", nil)
rr := httptest.NewRecorder()
a.forwardHandleNginx(rr, req)
@ -121,7 +121,7 @@ func TestForwardHandleNginx_Domain_Header(t *testing.T) {
a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr()
a.proxyConfig.CookieDomain = api.PtrString("foo")
a.proxyConfig.ExternalHost = "http://auth.test.goauthentik.io"
req, _ := http.NewRequest("GET", "/akprox/auth/nginx", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/nginx", nil)
req.Header.Set("X-Original-URL", "http://test.goauthentik.io/app")
rr := httptest.NewRecorder()

View File

@ -12,7 +12,7 @@ import (
func TestForwardHandleTraefik_Single_Blank(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/traefik", nil)
rr := httptest.NewRecorder()
a.forwardHandleTraefik(rr, req)
@ -22,7 +22,7 @@ func TestForwardHandleTraefik_Single_Blank(t *testing.T) {
func TestForwardHandleTraefik_Single_Skip(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/traefik", nil)
req.Header.Set("X-Forwarded-Proto", "http")
req.Header.Set("X-Forwarded-Host", "test.goauthentik.io")
req.Header.Set("X-Forwarded-Uri", "/skip")
@ -35,7 +35,7 @@ func TestForwardHandleTraefik_Single_Skip(t *testing.T) {
func TestForwardHandleTraefik_Single_Headers(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/traefik", nil)
req.Header.Set("X-Forwarded-Proto", "http")
req.Header.Set("X-Forwarded-Host", "test.goauthentik.io")
req.Header.Set("X-Forwarded-Uri", "/app")
@ -45,7 +45,7 @@ func TestForwardHandleTraefik_Single_Headers(t *testing.T) {
assert.Equal(t, rr.Code, http.StatusTemporaryRedirect)
loc, _ := rr.Result().Location()
assert.Equal(t, loc.String(), "http://test.goauthentik.io/akprox/start")
assert.Equal(t, loc.String(), "http://test.goauthentik.io/outpost.goauthentik.io/start")
s, _ := a.sessions.Get(req, constants.SeesionName)
assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect])
@ -53,7 +53,7 @@ func TestForwardHandleTraefik_Single_Headers(t *testing.T) {
func TestForwardHandleTraefik_Single_Claims(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/traefik", nil)
req.Header.Set("X-Forwarded-Proto", "http")
req.Header.Set("X-Forwarded-Host", "test.goauthentik.io")
req.Header.Set("X-Forwarded-Uri", "/app")
@ -102,7 +102,7 @@ func TestForwardHandleTraefik_Domain_Blank(t *testing.T) {
a := newTestApplication()
a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr()
a.proxyConfig.CookieDomain = api.PtrString("foo")
req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/traefik", nil)
rr := httptest.NewRecorder()
a.forwardHandleTraefik(rr, req)
@ -115,7 +115,7 @@ func TestForwardHandleTraefik_Domain_Header(t *testing.T) {
a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr()
a.proxyConfig.CookieDomain = api.PtrString("foo")
a.proxyConfig.ExternalHost = "http://auth.test.goauthentik.io"
req, _ := http.NewRequest("GET", "/akprox/auth/traefik", nil)
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/traefik", nil)
req.Header.Set("X-Forwarded-Proto", "http")
req.Header.Set("X-Forwarded-Host", "test.goauthentik.io")
req.Header.Set("X-Forwarded-Uri", "/app")
@ -125,7 +125,7 @@ func TestForwardHandleTraefik_Domain_Header(t *testing.T) {
assert.Equal(t, http.StatusTemporaryRedirect, rr.Code)
loc, _ := rr.Result().Location()
assert.Equal(t, "http://auth.test.goauthentik.io/akprox/start", loc.String())
assert.Equal(t, "http://auth.test.goauthentik.io/outpost.goauthentik.io/start", loc.String())
s, _ := a.sessions.Get(req, constants.SeesionName)
assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect])

View File

@ -73,10 +73,10 @@ func (a *Application) configureProxy() error {
func (a *Application) proxyModifyRequest(ou *url.URL) func(req *http.Request) {
return func(r *http.Request) {
r.Header.Set("X-Forwarded-Host", r.Host)
claims, _ := a.getClaims(r)
r.URL.Scheme = ou.Scheme
r.URL.Host = ou.Host
r.Host = ou.Host
if claims != nil && claims.Proxy != nil && claims.Proxy.BackendOverride != "" {
u, err := url.Parse(claims.Proxy.BackendOverride)
if err != nil {
@ -84,7 +84,6 @@ func (a *Application) proxyModifyRequest(ou *url.URL) func(req *http.Request) {
} else {
r.URL.Scheme = u.Scheme
r.URL.Host = u.Host
r.Host = u.Host
}
}
a.log.WithField("upstream_url", r.URL.String()).Trace("final upstream url")

View File

@ -19,9 +19,10 @@ func TestProxy_ModifyRequest(t *testing.T) {
}
a.proxyModifyRequest(u)(req)
assert.Equal(t, "frontend", req.Header.Get("X-Forwarded-Host"))
assert.Equal(t, "/foo", req.URL.Path)
assert.Equal(t, "backend:8012", req.URL.Host)
assert.Equal(t, "backend:8012", req.Host)
assert.Equal(t, "frontend", req.Host)
}
func TestProxy_ModifyRequest_Claims(t *testing.T) {
@ -49,7 +50,7 @@ func TestProxy_ModifyRequest_Claims(t *testing.T) {
assert.Equal(t, "/foo", req.URL.Path)
assert.Equal(t, "other-backend:8123", req.URL.Host)
assert.Equal(t, "other-backend:8123", req.Host)
assert.Equal(t, "frontend", req.Host)
}
func TestProxy_ModifyRequest_Claims_Invalid(t *testing.T) {
@ -77,5 +78,5 @@ func TestProxy_ModifyRequest_Claims_Invalid(t *testing.T) {
assert.Equal(t, "/foo", req.URL.Path)
assert.Equal(t, "backend:8012", req.URL.Host)
assert.Equal(t, "backend:8012", req.Host)
assert.Equal(t, "frontend", req.Host)
}

View File

@ -3,14 +3,46 @@ package application
import (
"encoding/base64"
"net/http"
"net/url"
"strings"
"time"
"github.com/gorilla/securecookie"
"goauthentik.io/api"
"goauthentik.io/internal/outpost/proxyv2/constants"
)
const (
redirectParam = "rd"
)
func (a *Application) checkRedirectParam(r *http.Request) (string, bool) {
rd := r.URL.Query().Get(redirectParam)
if rd == "" {
return "", false
}
u, err := url.Parse(rd)
if err != nil {
a.log.WithError(err).Warning("Failed to parse redirect URL")
return "", false
}
// Check to make sure we only redirect to allowed places
if a.Mode() == api.PROXYMODE_PROXY || a.Mode() == api.PROXYMODE_FORWARD_SINGLE {
if !strings.Contains(u.String(), a.proxyConfig.ExternalHost) {
a.log.WithField("url", u.String()).WithField("ext", a.proxyConfig.ExternalHost).Warning("redirect URI did not contain external host")
return "", false
}
} else {
if !strings.HasSuffix(u.Host, *a.proxyConfig.CookieDomain) {
a.log.WithField("host", u.Host).WithField("dom", *a.proxyConfig.CookieDomain).Warning("redirect URI Host was not included in cookie domain")
return "", false
}
}
return u.String(), true
}
func (a *Application) handleRedirect(rw http.ResponseWriter, r *http.Request) {
newState := base64.RawStdEncoding.EncodeToString(securecookie.GenerateRandomKey(32))
newState := base64.RawURLEncoding.EncodeToString(securecookie.GenerateRandomKey(32))
s, err := a.sessions.Get(r, constants.SeesionName)
if err != nil {
s.Values[constants.SessionOAuthState] = []string{}
@ -20,6 +52,11 @@ func (a *Application) handleRedirect(rw http.ResponseWriter, r *http.Request) {
s.Values[constants.SessionOAuthState] = []string{}
state = []string{}
}
rd, ok := a.checkRedirectParam(r)
if ok {
s.Values[constants.SessionRedirect] = rd
a.log.WithField("rd", rd).Trace("Setting redirect")
}
s.Values[constants.SessionOAuthState] = append(state, newState)
err = s.Save(r, rw)
if err != nil {
@ -29,7 +66,10 @@ func (a *Application) handleRedirect(rw http.ResponseWriter, r *http.Request) {
}
func (a *Application) handleCallback(rw http.ResponseWriter, r *http.Request) {
s, _ := a.sessions.Get(r, constants.SeesionName)
s, err := a.sessions.Get(r, constants.SeesionName)
if err != nil {
a.log.WithError(err).Trace("failed to get session")
}
state, ok := s.Values[constants.SessionOAuthState]
if !ok {
a.log.Warning("No state saved in session")
@ -62,8 +102,8 @@ func (a *Application) handleCallback(rw http.ResponseWriter, r *http.Request) {
redirect := a.proxyConfig.ExternalHost
redirectR, ok := s.Values[constants.SessionRedirect]
if ok {
a.log.WithField("redirect", redirectR).Trace("got final redirect from session")
redirect = redirectR.(string)
}
a.log.WithField("redirect", redirect).Trace("final redirect")
http.Redirect(rw, r, redirect, http.StatusFound)
}

View File

@ -0,0 +1,51 @@
package application
import (
"net/http"
"testing"
"github.com/stretchr/testify/assert"
"goauthentik.io/api"
)
func TestCheckRedirectParam(t *testing.T) {
a := newTestApplication()
req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/start", nil)
rd, ok := a.checkRedirectParam(req)
assert.Equal(t, false, ok)
assert.Equal(t, "", rd)
req, _ = http.NewRequest("GET", "/outpost.goauthentik.io/auth/start?rd=https://google.com", nil)
rd, ok = a.checkRedirectParam(req)
assert.Equal(t, false, ok)
assert.Equal(t, "", rd)
req, _ = http.NewRequest("GET", "/outpost.goauthentik.io/auth/start?rd=https://ext.t.goauthentik.io/test", nil)
rd, ok = a.checkRedirectParam(req)
assert.Equal(t, true, ok)
assert.Equal(t, "https://ext.t.goauthentik.io/test", rd)
}
func TestCheckRedirectParam_Domain(t *testing.T) {
a := newTestApplication()
a.proxyConfig.Mode = api.PROXYMODE_FORWARD_DOMAIN.Ptr()
a.proxyConfig.CookieDomain = api.PtrString("t.goauthentik.io")
req, _ := http.NewRequest("GET", "https://a.t.goauthentik.io/outpost.goauthentik.io/auth/start", nil)
rd, ok := a.checkRedirectParam(req)
assert.Equal(t, false, ok)
assert.Equal(t, "", rd)
req, _ = http.NewRequest("GET", "/outpost.goauthentik.io/auth/start?rd=https://ext.t.goauthentik.io/test", nil)
rd, ok = a.checkRedirectParam(req)
assert.Equal(t, true, ok)
assert.Equal(t, "https://ext.t.goauthentik.io/test", rd)
}

View File

@ -15,6 +15,7 @@ func newTestApplication() *Application {
ClientId: api.PtrString(ak.TestSecret()),
ClientSecret: api.PtrString(ak.TestSecret()),
CookieSecret: api.PtrString(ak.TestSecret()),
ExternalHost: "https://ext.t.goauthentik.io",
CookieDomain: api.PtrString(""),
Mode: api.PROXYMODE_FORWARD_SINGLE.Ptr(),
SkipPathRegex: api.PtrString("/skip.*"),

View File

@ -42,7 +42,7 @@ func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) {
a.log.WithError(err).Warning("failed to save session before redirect")
}
authUrl := urlJoin(a.proxyConfig.ExternalHost, "/akprox/start")
authUrl := urlJoin(a.proxyConfig.ExternalHost, "/outpost.goauthentik.io/start")
http.Redirect(rw, r, authUrl, http.StatusFound)
}

View File

@ -21,7 +21,7 @@ func TestRedirectToStart_Proxy(t *testing.T) {
assert.Equal(t, http.StatusFound, rr.Code)
loc, _ := rr.Result().Location()
assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
assert.Equal(t, "https://test.goauthentik.io/outpost.goauthentik.io/start", loc.String())
s, _ := a.sessions.Get(req, constants.SeesionName)
assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect])
@ -38,7 +38,7 @@ func TestRedirectToStart_Forward(t *testing.T) {
assert.Equal(t, http.StatusFound, rr.Code)
loc, _ := rr.Result().Location()
assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
assert.Equal(t, "https://test.goauthentik.io/outpost.goauthentik.io/start", loc.String())
s, _ := a.sessions.Get(req, constants.SeesionName)
assert.Equal(t, "https://test.goauthentik.io/foo/bar/baz", s.Values[constants.SessionRedirect])
@ -56,7 +56,7 @@ func TestRedirectToStart_Forward_Domain_Invalid(t *testing.T) {
assert.Equal(t, http.StatusFound, rr.Code)
loc, _ := rr.Result().Location()
assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
assert.Equal(t, "https://test.goauthentik.io/outpost.goauthentik.io/start", loc.String())
s, _ := a.sessions.Get(req, constants.SeesionName)
assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect])
@ -74,7 +74,7 @@ func TestRedirectToStart_Forward_Domain(t *testing.T) {
assert.Equal(t, http.StatusFound, rr.Code)
loc, _ := rr.Result().Location()
assert.Equal(t, "https://test.goauthentik.io/akprox/start", loc.String())
assert.Equal(t, "https://test.goauthentik.io/outpost.goauthentik.io/start", loc.String())
s, _ := a.sessions.Get(req, constants.SeesionName)
assert.Equal(t, "https://test.goauthentik.io", s.Values[constants.SessionRedirect])

View File

@ -32,7 +32,7 @@ func (ps *ProxyServer) HandlePing(rw http.ResponseWriter, r *http.Request) {
func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) {
before := time.Now()
web.DisableIndex(http.StripPrefix("/akprox/static/dist", staticWeb.StaticHandler)).ServeHTTP(rw, r)
web.DisableIndex(http.StripPrefix("/outpost.goauthentik.io/static/dist", staticWeb.StaticHandler)).ServeHTTP(rw, r)
after := time.Since(before)
metrics.Requests.With(prometheus.Labels{
"outpost_name": ps.akAPI.Outpost.Name,
@ -90,11 +90,11 @@ func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, str
}
func (ps *ProxyServer) Handle(rw http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/akprox/static") {
if strings.HasPrefix(r.URL.Path, "/outpost.goauthentik.io/static") {
ps.HandleStatic(rw, r)
return
}
if strings.HasPrefix(r.URL.Path, "/akprox/ping") {
if strings.HasPrefix(r.URL.Path, "/outpost.goauthentik.io/ping") {
ps.HandlePing(rw, r)
return
}
@ -109,6 +109,7 @@ func (ps *ProxyServer) Handle(rw http.ResponseWriter, r *http.Request) {
}
}
ps.log.WithField("headers", r.Header).Trace("tracing headers for no hostname match")
ps.log.WithField("host", host).Warning("no app for hostname")
rw.Header().Set("Content-Type", "application/json")

View File

@ -25,7 +25,7 @@ var (
func RunServer() {
m := mux.NewRouter()
l := log.WithField("logger", "authentik.outpost.metrics")
m.HandleFunc("/akprox/ping", func(rw http.ResponseWriter, r *http.Request) {
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(204)
})
m.Path("/metrics").Handler(promhttp.Handler())

View File

@ -64,8 +64,8 @@ func NewProxyServer(ac *ak.APIController, portOffset int) *ProxyServer {
akAPI: ac,
defaultCert: defaultCert,
}
globalMux.PathPrefix("/akprox/static").HandlerFunc(s.HandleStatic)
globalMux.Path("/akprox/ping").HandlerFunc(s.HandlePing)
globalMux.PathPrefix("/outpost.goauthentik.io/static").HandlerFunc(s.HandleStatic)
globalMux.Path("/outpost.goauthentik.io/ping").HandlerFunc(s.HandlePing)
rootMux.PathPrefix("/").HandlerFunc(s.Handle)
return s
}

View File

@ -5,12 +5,13 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{{.Title}}</title>
<link rel="shortcut icon" type="image/png" href="/akprox/static/dist/assets/icons/icon.png">
<link rel="stylesheet" type="text/css" href="/akprox/static/dist/patternfly.min.css">
<link rel="stylesheet" type="text/css" href="/akprox/static/dist/authentik.css">
<link rel="shortcut icon" type="image/png" href="/outpost.goauthentik.io/static/dist/assets/icons/icon.png">
<link rel="stylesheet" type="text/css" href="/outpost.goauthentik.io/static/dist/patternfly.min.css">
<link rel="stylesheet" type="text/css" href="/outpost.goauthentik.io/static/dist/authentik.css">
<link rel="stylesheet" type="text/css" href="/outpost.goauthentik.io/static/dist/custom.css">
<style>
.pf-c-background-image::before {
--ak-flow-background: url("/akprox/static/dist/assets/images/flow_background.jpg");
--ak-flow-background: url("/outpost.goauthentik.io/static/dist/assets/images/flow_background.jpg");
}
</style>
</head>
@ -32,7 +33,7 @@
<div class="ak-login-container">
<header class="pf-c-login__header">
<div class="pf-c-brand ak-brand">
<img src="/akprox/static/dist/assets/icons/icon_left_brand.svg" alt="authentik icon" />
<img src="/outpost.goauthentik.io/static/dist/assets/icons/icon_left_brand.svg" alt="authentik icon" />
</div>
</header>
<main class="pf-c-login__main">

View File

@ -3,7 +3,8 @@ package templates
import (
_ "embed"
"html/template"
"log"
log "github.com/sirupsen/logrus"
)
//go:embed error.html

View File

@ -30,7 +30,7 @@ func (ws *WebServer) configureProxy() {
rp := &httputil.ReverseProxy{Director: director}
rp.ErrorHandler = ws.proxyErrorHandler
rp.ModifyResponse = ws.proxyModifyResponse
ws.m.PathPrefix("/akprox").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
ws.m.PathPrefix("/outpost.goauthentik.io").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if ws.ProxyServer != nil {
before := time.Now()
ws.ProxyServer.Handle(rw, r)

View File

@ -1,5 +1,5 @@
# Stage 1: Build
FROM docker.io/golang:1.17.6-bullseye AS builder
FROM docker.io/golang:1.17.7-bullseye AS builder
WORKDIR /go/src/goauthentik.io
@ -19,7 +19,7 @@ ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
COPY --from=builder /go/ldap /
HEALTHCHECK CMD [ "wget", "--spider", "http://localhost:9300/akprox/ping" ]
HEALTHCHECK CMD [ "wget", "--spider", "http://localhost:9300/outpost.goauthentik.io/ping" ]
EXPOSE 3389 6636 9300

View File

@ -32,30 +32,6 @@ function check_if_root {
chpst -u authentik:$GROUP env HOME=/authentik $1
}
function prefixwith {
local prefix="$1"
shift
"$@" > >(sed "s/^/$prefix: /") 2> >(sed "s/^/$prefix (err): /" >&2)
}
function restore {
PG_HOST=$(python -m authentik.lib.config postgresql.host 2> /dev/null)
PG_NAME=$(python -m authentik.lib.config postgresql.name 2> /dev/null)
PG_USER=$(python -m authentik.lib.config postgresql.user 2> /dev/null)
PG_PORT=$(python -m authentik.lib.config postgresql.port 2> /dev/null)
export PGPASSWORD=$(python -m authentik.lib.config postgresql.password 2> /dev/null)
log "Ensuring no one can connect to the database"
prefixwith "psql" psql -h"${PG_HOST}" -U"${PG_USER}" -c"UPDATE pg_database SET datallowconn = 'false' WHERE datname = '${PG_NAME}';" "postgres"
prefixwith "psql" psql -h"${PG_HOST}" -U"${PG_USER}" -c"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '${PG_NAME}';" "postgres"
log "deleting and re-creating database"
prefixwith "psql" dropdb -h"${PG_HOST}" -U"${PG_USER}" "${PG_NAME}" || trueacku
prefixwith "psql" createdb -h"${PG_HOST}" -U"${PG_USER}" "${PG_NAME}"
log "running initial migrations"
prefixwith "migrate" python -m lifecycle.migrate 2> /dev/null
log "restoring database"
prefixwith "restore" python -m manage dbrestore -i ${@:2}
}
MODE_FILE="/tmp/authentik-mode"
if [[ "$1" == "server" ]]; then
@ -75,12 +51,6 @@ elif [[ "$1" == "worker" ]]; then
elif [[ "$1" == "flower" ]]; then
echo "flower" > $MODE_FILE
celery -A authentik.root.celery flower
elif [[ "$1" == "backup" ]]; then
wait_for_db
python -m manage dbbackup --clean
elif [[ "$1" == "restore" ]]; then
wait_for_db
restore $@
elif [[ "$1" == "bash" ]]; then
/bin/bash
elif [[ "$1" == "test" ]]; then

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -22,13 +22,6 @@ warnings.filterwarnings(
"efault_app_config."
),
)
warnings.filterwarnings(
"ignore",
message=(
"'dbbackup' defines default_app_config = 'dbbackup.apps.DbbackupConfig'. Django now det"
"ects this configuration automatically. You can remove default_app_config."
),
)
defuse_stdlib()

631
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ ENV NODE_ENV=production
RUN cd /static && npm i && npm run build-proxy
# Stage 2: Build
FROM docker.io/golang:1.17.6-bullseye AS builder
FROM docker.io/golang:1.17.7-bullseye AS builder
WORKDIR /go/src/goauthentik.io
@ -32,7 +32,7 @@ COPY --from=web-builder /static/security.txt /web/security.txt
COPY --from=web-builder /static/dist/ /web/dist/
COPY --from=web-builder /static/authentik/ /web/authentik/
HEALTHCHECK CMD [ "wget", "--spider", "http://localhost:9300/akprox/ping" ]
HEALTHCHECK CMD [ "wget", "--spider", "http://localhost:9300/outpost.goauthentik.io/ping" ]
EXPOSE 9000 9300 9443

View File

@ -92,12 +92,11 @@ addopts = "-p no:celery --junitxml=unittest.xml"
[tool.poetry]
name = "authentik"
version = "2022.1.5"
version = "2022.2.1"
description = ""
authors = ["Jens Langhammer <jens.langhammer@beryju.org>"]
[tool.poetry.dependencies]
boto3 = "*"
celery = "*"
channels = "*"
channels-redis = "*"
@ -107,14 +106,12 @@ dacite = "*"
deepmerge = "*"
defusedxml = "*"
django = "*"
django-dbbackup = "=4.0.0b0"
django-filter = "*"
django-guardian = "*"
django-model-utils = "*"
django-otp = "*"
django-prometheus = "*"
django-redis = "*"
django-storages = "*"
djangorestframework = "*"
djangorestframework-guardian = "*"
docker = "*"

View File

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2022.1.5
version: 2022.2.1
description: Making authentication simple.
contact:
email: hello@beryju.org
@ -15045,10 +15045,14 @@ paths:
description: AuthenticatorValidateStage Viewset
parameters:
- in: query
name: configuration_stage
name: configuration_stages
schema:
type: string
format: uuid
type: array
items:
type: string
format: uuid
explode: true
style: form
- in: query
name: name
schema:
@ -19826,11 +19830,12 @@ components:
items:
$ref: '#/components/schemas/DeviceClassesEnum'
description: Device classes which can be used to authenticate
configuration_stage:
type: string
format: uuid
nullable: true
description: Stage used to configure Authenticator when user doesn't have
configuration_stages:
type: array
items:
type: string
format: uuid
description: Stages used to configure Authenticator when user doesn't have
any compatible devices. After this configuration Stage passes, the user
is not prompted again.
required:
@ -19858,11 +19863,12 @@ components:
items:
$ref: '#/components/schemas/DeviceClassesEnum'
description: Device classes which can be used to authenticate
configuration_stage:
type: string
format: uuid
nullable: true
description: Stage used to configure Authenticator when user doesn't have
configuration_stages:
type: array
items:
type: string
format: uuid
description: Stages used to configure Authenticator when user doesn't have
any compatible devices. After this configuration Stage passes, the user
is not prompted again.
required:
@ -19892,7 +19898,12 @@ components:
type: array
items:
$ref: '#/components/schemas/DeviceChallenge'
configuration_stages:
type: array
items:
$ref: '#/components/schemas/SelectableStage'
required:
- configuration_stages
- device_challenges
- pending_user
- pending_user_avatar
@ -19907,6 +19918,9 @@ components:
default: ak-stage-authenticator-validate
selected_challenge:
$ref: '#/components/schemas/DeviceChallengeRequest'
selected_stage:
type: string
minLength: 1
code:
type: string
minLength: 1
@ -20017,7 +20031,6 @@ components:
enum:
- can_save_media
- can_geo_ip
- can_backup
type: string
CaptchaChallenge:
type: object
@ -26678,11 +26691,12 @@ components:
items:
$ref: '#/components/schemas/DeviceClassesEnum'
description: Device classes which can be used to authenticate
configuration_stage:
type: string
format: uuid
nullable: true
description: Stage used to configure Authenticator when user doesn't have
configuration_stages:
type: array
items:
type: string
format: uuid
description: Stages used to configure Authenticator when user doesn't have
any compatible devices. After this configuration Stage passes, the user
is not prompted again.
PatchedCaptchaStageRequest:
@ -30018,6 +30032,24 @@ components:
- direct
- cached
type: string
SelectableStage:
type: object
description: Serializer for stages which can be selected by users
properties:
pk:
type: string
format: uuid
name:
type: string
verbose_name:
type: string
meta_model_name:
type: string
required:
- meta_model_name
- name
- pk
- verbose_name
ServiceConnection:
type: object
description: ServiceConnection Serializer

View File

@ -105,7 +105,7 @@ class TestProviderProxy(SeleniumTestCase):
self.assertIn(f"X-Authentik-Username: {self.user.username}", full_body_text)
self.assertIn("X-Foo: bar", full_body_text)
self.driver.get("http://localhost:9000/akprox/sign_out")
self.driver.get("http://localhost:9000/outpost.goauthentik.io/sign_out")
sleep(2)
full_body_text = self.driver.find_element(By.CSS_SELECTOR, ".pf-c-title.pf-m-3xl").text
self.assertIn("You've logged out of proxy.", full_body_text)

873
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,11 @@
"fr_FR",
"tr",
"es",
"pl"
"pl",
"zh_TW",
"zh-Hans",
"zh-Hant",
"de"
],
"formatOptions": {
"lineNumbers": false
@ -48,14 +52,14 @@
]
},
"dependencies": {
"@babel/core": "^7.16.12",
"@babel/plugin-proposal-decorators": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.16.10",
"@babel/core": "^7.17.4",
"@babel/plugin-proposal-decorators": "^7.17.2",
"@babel/plugin-transform-runtime": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@formatjs/intl-listformat": "^6.5.1",
"@fortawesome/fontawesome-free": "^5.15.4",
"@goauthentik/api": "^2022.1.3-1643236150",
"@formatjs/intl-listformat": "^6.5.2",
"@fortawesome/fontawesome-free": "^6.0.0",
"@goauthentik/api": "^2022.1.5-1644681372",
"@jackfranklin/rollup-plugin-markdown": "^0.3.0",
"@lingui/cli": "^3.13.2",
"@lingui/core": "^3.13.2",
@ -67,36 +71,36 @@
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-replace": "^3.0.1",
"@rollup/plugin-replace": "^3.1.0",
"@rollup/plugin-typescript": "^8.3.0",
"@sentry/browser": "^6.17.3",
"@sentry/tracing": "^6.17.3",
"@sentry/browser": "^6.17.8",
"@sentry/tracing": "^6.17.8",
"@squoosh/cli": "^0.7.2",
"@trivago/prettier-plugin-sort-imports": "^3.1.1",
"@trivago/prettier-plugin-sort-imports": "^3.2.0",
"@types/chart.js": "^2.9.35",
"@types/codemirror": "5.60.5",
"@types/grecaptcha": "^3.0.3",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.12.0",
"@webcomponents/webcomponentsjs": "^2.6.0",
"babel-plugin-macros": "^3.1.0",
"base64-js": "^1.5.1",
"chart.js": "^3.7.0",
"chart.js": "^3.7.1",
"chartjs-adapter-moment": "^1.0.0",
"codemirror": "^5.65.1",
"construct-style-sheets-polyfill": "^3.1.0",
"country-flag-icons": "^1.4.20",
"eslint": "^8.8.0",
"country-flag-icons": "^1.4.21",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.4",
"eslint-plugin-lit": "^1.6.1",
"flowchart.js": "^1.17.0",
"flowchart.js": "^1.17.1",
"fuse.js": "^6.5.3",
"lit": "^2.1.2",
"lit": "^2.1.4",
"moment": "^2.29.1",
"prettier": "^2.5.1",
"rapidoc": "^9.1.4",
"rollup": "^2.66.1",
"rollup": "^2.67.2",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.2",
"rollup-plugin-minify-html-literals": "^1.2.6",

View File

@ -34,6 +34,7 @@ export const resources = [
dest: "dist/",
},
{ src: "src/authentik.css", dest: "dist/" },
{ src: "src/custom.css", dest: "dist/" },
{
src: "node_modules/@patternfly/patternfly/assets/*",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 KiB

After

Width:  |  Height:  |  Size: 580 KiB

View File

@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2022.1.5";
export const VERSION = "2022.2.1";
export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";";

1
web/src/custom.css Normal file
View File

@ -0,0 +1 @@
/* User customisable */

View File

@ -433,8 +433,7 @@ export class FlowExecutor extends LitElement implements StageHost {
)
? html`
<li>
<a
href="https://unsplash.com/@kimonmaritz"
<a href="https://unsplash.com/@trime"
>${t`Background image`}</a
>
</li>

View File

@ -67,7 +67,7 @@ export class AuthenticatorValidateStage
return this._selectedDeviceChallenge;
}
submit(payload: AuthenticatorValidationChallengeResponseRequest): Promise<void> {
submit(payload: AuthenticatorValidationChallengeResponseRequest): Promise<boolean> {
return this.host?.submit(payload) || Promise.resolve();
}
@ -140,7 +140,7 @@ export class AuthenticatorValidateStage
}
renderDevicePicker(): TemplateResult {
return html` <ul>
return html`<ul>
${this.challenge?.deviceChallenges.map((challenges) => {
return html`<li>
<button
@ -157,6 +157,30 @@ export class AuthenticatorValidateStage
</ul>`;
}
renderStagePicker(): TemplateResult {
return html`<ul>
${this.challenge?.configurationStages.map((stage) => {
return html`<li>
<button
class="pf-c-button authenticator-button"
type="button"
@click=${() => {
this.submit({
component: this.challenge.component || "",
selectedStage: stage.pk,
});
}}
>
<div class="right">
<p>${stage.name}</p>
<small>${stage.verboseName}</small>
</div>
</button>
</li>`;
})}
</ul>`;
}
renderDeviceChallenge(): TemplateResult {
if (!this.selectedDeviceChallenge) {
return html``;
@ -242,6 +266,9 @@ export class AuthenticatorValidateStage
${this.selectedDeviceChallenge
? ""
: html`<p>${t`Select an authentication method.`}</p>`}
${this.challenge.configurationStages.length > 0
? this.renderStagePicker()
: html``}
</form>
${this.renderDevicePicker()}
</div>

View File

@ -1,15 +1,19 @@
import { en, es, fr, pl, tr } from "make-plural/plurals";
import { de, en, es, fr, pl, tr, zh } from "make-plural/plurals";
import { Messages, i18n } from "@lingui/core";
import { detect, fromNavigator, fromStorage, fromUrl } from "@lingui/detect-locale";
import { t } from "@lingui/macro";
import { messages as localeDE } from "../locales/de";
import { messages as localeEN } from "../locales/en";
import { messages as localeES } from "../locales/es";
import { messages as localeFR_FR } from "../locales/fr_FR";
import { messages as localePL } from "../locales/pl";
import { messages as localeDEBUG } from "../locales/pseudo-LOCALE";
import { messages as localeTR } from "../locales/tr";
import { messages as localeZH_Hans } from "../locales/zh-Hans";
import { messages as localeZH_Hant } from "../locales/zh-Hant";
import { messages as localeZH_TW } from "../locales/zh_TW";
export const LOCALES: {
code: string;
@ -54,6 +58,30 @@ export const LOCALES: {
label: t`Polish`,
locale: localePL,
},
{
code: "zh_TW",
plurals: zh,
label: t`Taiwanese Mandarin`,
locale: localeZH_TW,
},
{
code: "zh-Hans",
plurals: zh,
label: t`Chinese (simplified)`,
locale: localeZH_Hans,
},
{
code: "zh-Hant",
plurals: zh,
label: t`Chinese (traditional)`,
locale: localeZH_Hant,
},
{
code: "de",
plurals: de,
label: t`German`,
locale: localeDE,
},
];
LOCALES.forEach((locale) => {

6125
web/src/locales/de.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -563,16 +563,16 @@ msgid "Background shown during execution."
msgstr "Background shown during execution."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with errors."
msgstr "Backup finished with errors."
#~ msgid "Backup finished with errors."
#~ msgstr "Backup finished with errors."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with warnings/backup not supported."
msgstr "Backup finished with warnings/backup not supported."
#~ msgid "Backup finished with warnings/backup not supported."
#~ msgstr "Backup finished with warnings/backup not supported."
#: src/pages/admin-overview/AdminOverviewPage.ts
msgid "Backup status"
msgstr "Backup status"
#~ msgid "Backup status"
#~ msgstr "Backup status"
#: src/pages/providers/ldap/LDAPProviderForm.ts
#: src/pages/providers/ldap/LDAPProviderViewPage.ts
@ -844,6 +844,14 @@ msgstr "Checks if the request's user's password has been changed in the last x d
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr "Checks the value from the policy request against several rules, mostly used to ensure password strength."
#: src/interfaces/locale.ts
msgid "Chinese (simplified)"
msgstr "Chinese (simplified)"
#: src/interfaces/locale.ts
msgid "Chinese (traditional)"
msgstr "Chinese (traditional)"
#: src/pages/flows/FlowListPage.ts
msgid "Clear Flow cache"
msgstr "Clear Flow cache"
@ -948,8 +956,12 @@ msgid "Configuration flow"
msgstr "Configuration flow"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stage"
msgstr "Configuration stage"
#~ msgid "Configuration stage"
#~ msgstr "Configuration stage"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stages"
msgstr "Configuration stages"
#:
#~ msgid "Configure WebAuthn"
@ -2205,6 +2217,10 @@ msgstr "Generic"
msgid "Generic OpenID Connect"
msgstr "Generic OpenID Connect"
#: src/interfaces/locale.ts
msgid "German"
msgstr "German"
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
msgid "Get this value from https://console.twilio.com"
@ -4483,8 +4499,8 @@ msgid "Stage type"
msgstr "Stage type"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#~ msgstr "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
@ -4543,6 +4559,10 @@ msgstr "Stages"
msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow."
msgstr "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#: src/pages/outposts/ServiceConnectionListPage.ts
msgid "State"
msgstr "State"
@ -5014,6 +5034,10 @@ msgstr "TOTP Device"
msgid "TOTP authenticator"
msgstr "TOTP authenticator"
#: src/interfaces/locale.ts
msgid "Taiwanese Mandarin"
msgstr "Taiwanese Mandarin"
#: src/pages/flows/StageBindingForm.ts
msgid "Target"
msgstr "Target"
@ -5673,8 +5697,8 @@ msgid "Use the username and password below to authenticate. The password can be
msgstr "Use the username and password below to authenticate. The password can be retrieved later on the Tokens page."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you)."
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you)."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application."
@ -6036,6 +6060,10 @@ msgstr "When enabled, the invitation will be deleted after usage."
msgid "When enabled, user fields are matched regardless of their casing."
msgstr "When enabled, user fields are matched regardless of their casing."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "When multiple stages are selected, the user can choose which one they want to enroll."
msgstr "When multiple stages are selected, the user can choose which one they want to enroll."
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
msgstr "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."

View File

@ -561,16 +561,16 @@ msgid "Background shown during execution."
msgstr "Se muestra el fondo durante la ejecución."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with errors."
msgstr "La copia de seguridad terminó con errores."
#~ msgid "Backup finished with errors."
#~ msgstr "La copia de seguridad terminó con errores."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with warnings/backup not supported."
msgstr "La copia de seguridad finalizó con advertencias o copias de seguridad no compatibles"
#~ msgid "Backup finished with warnings/backup not supported."
#~ msgstr "La copia de seguridad finalizó con advertencias o copias de seguridad no compatibles"
#: src/pages/admin-overview/AdminOverviewPage.ts
msgid "Backup status"
msgstr "Estado de respaldo"
#~ msgid "Backup status"
#~ msgstr "Estado de respaldo"
#: src/pages/providers/ldap/LDAPProviderForm.ts
#: src/pages/providers/ldap/LDAPProviderViewPage.ts
@ -838,6 +838,14 @@ msgstr "Comprueba si la contraseña del usuario de la solicitud se ha cambiado e
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr "Comprueba el valor de la solicitud de política en relación con varias reglas, que se utilizan principalmente para garantizar la seguridad de la contraseña."
#: src/interfaces/locale.ts
msgid "Chinese (simplified)"
msgstr ""
#: src/interfaces/locale.ts
msgid "Chinese (traditional)"
msgstr ""
#: src/pages/flows/FlowListPage.ts
msgid "Clear Flow cache"
msgstr "Borrar caché de flujo"
@ -942,8 +950,12 @@ msgid "Configuration flow"
msgstr "Flujo de configuración"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stage"
msgstr "Etapa de configuración"
#~ msgid "Configuration stage"
#~ msgstr "Etapa de configuración"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stages"
msgstr ""
#~ msgid "Configure WebAuthn"
#~ msgstr "Configurar WebAuthn"
@ -2166,6 +2178,10 @@ msgstr "Genérico"
msgid "Generic OpenID Connect"
msgstr "Conexión OpenID genérica"
#: src/interfaces/locale.ts
msgid "German"
msgstr ""
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
msgid "Get this value from https://console.twilio.com"
@ -4391,8 +4407,8 @@ msgid "Stage type"
msgstr "Tipo de escenario"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr "Etapa utilizada para configurar Authenticator cuando el usuario no tiene ningún dispositivo compatible. Una vez superada esta etapa de configuración, no se volverá a preguntar al usuario."
#~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#~ msgstr "Etapa utilizada para configurar Authenticator cuando el usuario no tiene ningún dispositivo compatible. Una vez superada esta etapa de configuración, no se volverá a preguntar al usuario."
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
@ -4451,6 +4467,10 @@ msgstr "Etapas"
msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow."
msgstr "Las etapas son pasos individuales de un flujo por los que se guía al usuario. Una etapa solo se puede ejecutar desde dentro de un flujo."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr ""
#: src/pages/outposts/ServiceConnectionListPage.ts
msgid "State"
msgstr "Estado"
@ -4905,6 +4925,10 @@ msgstr "Dispositivo TOTP"
msgid "TOTP authenticator"
msgstr "Autenticador TOTP"
#: src/interfaces/locale.ts
msgid "Taiwanese Mandarin"
msgstr ""
#: src/pages/flows/StageBindingForm.ts
msgid "Target"
msgstr "Objetivo"
@ -5556,8 +5580,8 @@ msgid "Use the username and password below to authenticate. The password can be
msgstr "Use el nombre de usuario y la contraseña a continuación para autenticarse. La contraseña se puede recuperar más adelante en la página Tokens."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Use este proveedor con auth_request de nginx o ForwardAuth de traefik. Cada aplicación/dominio necesita su propio proveedor. Además, en cada dominio, /akprox debe enrutarse al puesto avanzado (cuando se usa un puesto avanzado administrado, esto se hace por usted)."
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Use este proveedor con auth_request de nginx o ForwardAuth de traefik. Cada aplicación/dominio necesita su propio proveedor. Además, en cada dominio, /outpost.goauthentik.io debe enrutarse al puesto avanzado (cuando se usa un puesto avanzado administrado, esto se hace por usted)."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application."
@ -5912,6 +5936,10 @@ msgstr "Cuando se habilita, la invitación se eliminará después de su uso."
msgid "When enabled, user fields are matched regardless of their casing."
msgstr "Cuando se habilita, los campos de usuario coinciden independientemente de su carcasa."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "When multiple stages are selected, the user can choose which one they want to enroll."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
msgstr "Cuando se selecciona, se muestra un campo de contraseña en la misma página en lugar de en una página separada. Esto evita ataques de enumeración de nombres de usuario."

View File

@ -567,16 +567,16 @@ msgid "Background shown during execution."
msgstr "Arrière-plan utilisé durant l'exécution."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with errors."
msgstr "Sauvegarde terminée avec des erreurs."
#~ msgid "Backup finished with errors."
#~ msgstr "Sauvegarde terminée avec des erreurs."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with warnings/backup not supported."
msgstr "Sauvegarde terminée avec avertissements/sauvegarde non supportée."
#~ msgid "Backup finished with warnings/backup not supported."
#~ msgstr "Sauvegarde terminée avec avertissements/sauvegarde non supportée."
#: src/pages/admin-overview/AdminOverviewPage.ts
msgid "Backup status"
msgstr "État de la sauvegarde"
#~ msgid "Backup status"
#~ msgstr "État de la sauvegarde"
#: src/pages/providers/ldap/LDAPProviderForm.ts
#: src/pages/providers/ldap/LDAPProviderViewPage.ts
@ -846,6 +846,14 @@ msgstr "Vérifie si le mot de passe de l'usager a été changé dans les X derni
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr "Vérifie la valeur de la requête via plusieurs règles, principalement utilisé pour s'assurer de la robustesse des mots de passe."
#: src/interfaces/locale.ts
msgid "Chinese (simplified)"
msgstr ""
#: src/interfaces/locale.ts
msgid "Chinese (traditional)"
msgstr ""
#: src/pages/flows/FlowListPage.ts
msgid "Clear Flow cache"
msgstr "Vider le cache des flux"
@ -950,8 +958,12 @@ msgid "Configuration flow"
msgstr "Flux de configuration"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stage"
msgstr "Étape de configuration"
#~ msgid "Configuration stage"
#~ msgstr "Étape de configuration"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stages"
msgstr ""
#:
#~ msgid "Configure WebAuthn"
@ -2191,6 +2203,10 @@ msgstr ""
msgid "Generic OpenID Connect"
msgstr ""
#: src/interfaces/locale.ts
msgid "German"
msgstr ""
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
msgid "Get this value from https://console.twilio.com"
@ -4444,8 +4460,8 @@ msgid "Stage type"
msgstr "Type d'étape"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr "Étape utilisée pour configurer l'Authenticator lorsqu'un utilisateur n'a pas d'appareil compatible. Une fois cette étape franchie, l'utilisateur ne sera plus sollicité."
#~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#~ msgstr "Étape utilisée pour configurer l'Authenticator lorsqu'un utilisateur n'a pas d'appareil compatible. Une fois cette étape franchie, l'utilisateur ne sera plus sollicité."
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
@ -4504,6 +4520,10 @@ msgstr "Étapes"
msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow."
msgstr "Les étapes sont des étapes simples d'un flux au travers duquel un utilisateur est guidé. Une étape peut être uniquement exécutée à l'intérieur d'un flux."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr ""
#: src/pages/outposts/ServiceConnectionListPage.ts
msgid "State"
msgstr "État"
@ -4969,6 +4989,10 @@ msgstr ""
msgid "TOTP authenticator"
msgstr ""
#: src/interfaces/locale.ts
msgid "Taiwanese Mandarin"
msgstr ""
#: src/pages/flows/StageBindingForm.ts
msgid "Target"
msgstr "Cible"
@ -5614,8 +5638,8 @@ msgid "Use the username and password below to authenticate. The password can be
msgstr "Utilisez le nom d'utilisateur et le mot de passe ci-dessous pour vous authentifier. Le mot de passe peut être récupéré plus tard sur la page Jetons."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Utilisez ce fournisseur avec auth_request de nginx ou forwardAuth de traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, /akprox doit être routé vers l'avant-poste (si vous utilisez un avant-poste géré, cela est fait pour vous)."
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Utilisez ce fournisseur avec auth_request de nginx ou forwardAuth de traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, /outpost.goauthentik.io doit être routé vers l'avant-poste (si vous utilisez un avant-poste géré, cela est fait pour vous)."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application."
@ -5975,6 +5999,10 @@ msgstr "Si activée, l'invitation sera supprimée après utilisation."
msgid "When enabled, user fields are matched regardless of their casing."
msgstr "Si activé, les champs de l'utilisateur sont mis en correspondance en ignorant leur casse."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "When multiple stages are selected, the user can choose which one they want to enroll."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
msgstr "Si activée, un champ de mot de passe est affiché sur la même page au lieu d'une page séparée. Cela permet d'éviter les attaques par énumération de noms d'utilisateur."

View File

@ -560,17 +560,14 @@ msgstr "Obraz tła"
msgid "Background shown during execution."
msgstr "Tło pokazywane podczas wykonywania."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with errors."
msgstr "Kopia zapasowa zakończona z błędami."
#~ msgid "Backup finished with errors."
#~ msgstr "Kopia zapasowa zakończona z błędami."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with warnings/backup not supported."
msgstr "Tworzenie kopii zapasowej zakończone z ostrzeżeniami/kopia zapasowa nie jest obsługiwana."
#~ msgid "Backup finished with warnings/backup not supported."
#~ msgstr "Tworzenie kopii zapasowej zakończone z ostrzeżeniami/kopia zapasowa nie jest obsługiwana."
#: src/pages/admin-overview/AdminOverviewPage.ts
msgid "Backup status"
msgstr "Stan kopii zapasowej"
#~ msgid "Backup status"
#~ msgstr "Stan kopii zapasowej"
#: src/pages/providers/ldap/LDAPProviderForm.ts
#: src/pages/providers/ldap/LDAPProviderViewPage.ts
@ -838,6 +835,14 @@ msgstr "Sprawdza, czy żądanego użytkownika hasło zostało zmienione w ciągu
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr "Sprawdza wartość z żądania zasad pod kątem kilku reguł, używanych głównie w celu zapewnienia siły hasła."
#: src/interfaces/locale.ts
msgid "Chinese (simplified)"
msgstr "Chiński (uproszczony)"
#: src/interfaces/locale.ts
msgid "Chinese (traditional)"
msgstr "Chiński (tradycyjny)"
#: src/pages/flows/FlowListPage.ts
msgid "Clear Flow cache"
msgstr "Wyczyść pamięć podręczną przepływu"
@ -942,8 +947,12 @@ msgid "Configuration flow"
msgstr "Przepływ konfiguracji"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stage"
msgstr "Etap konfiguracji"
#~ msgid "Configuration stage"
#~ msgstr "Etap konfiguracji"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stages"
msgstr ""
#~ msgid "Configure WebAuthn"
#~ msgstr "Skonfiguruj WebAuthn"
@ -2166,6 +2175,10 @@ msgstr "Ogólny"
msgid "Generic OpenID Connect"
msgstr "Ogólny OpenID Connect"
#: src/interfaces/locale.ts
msgid "German"
msgstr ""
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
msgid "Get this value from https://console.twilio.com"
@ -4391,8 +4404,8 @@ msgid "Stage type"
msgstr "Typ etapu"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr "Etap używany do konfiguracji uwierzytelniacza, gdy użytkownik nie ma żadnych kompatybilnych urządzeń. Po zakończeniu tego etapu konfiguracji użytkownik nie jest ponownie pytany."
#~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#~ msgstr "Etap używany do konfiguracji uwierzytelniacza, gdy użytkownik nie ma żadnych kompatybilnych urządzeń. Po zakończeniu tego etapu konfiguracji użytkownik nie jest ponownie pytany."
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
@ -4451,6 +4464,10 @@ msgstr "Etapy"
msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow."
msgstr "Etapy to pojedyncze kroki przepływu, przez które prowadzony jest użytkownik. Etap można wykonać tylko z przepływu."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr ""
#: src/pages/outposts/ServiceConnectionListPage.ts
msgid "State"
msgstr "Stan"
@ -4905,6 +4922,10 @@ msgstr "Urządzenie TOTP"
msgid "TOTP authenticator"
msgstr "Uwierzytelniacz TOTP"
#: src/interfaces/locale.ts
msgid "Taiwanese Mandarin"
msgstr "Tajwański mandaryński"
#: src/pages/flows/StageBindingForm.ts
msgid "Target"
msgstr "Cel"
@ -5556,8 +5577,8 @@ msgid "Use the username and password below to authenticate. The password can be
msgstr "Użyj poniższej nazwy użytkownika i hasła do uwierzytelnienia. Hasło można później odzyskać na stronie Tokeny."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Użyj tego dostawcy z auth_request nginx lub forwardAuth traefik. Każda aplikacja/domena potrzebuje własnego dostawcy. Dodatkowo w każdej domenie /akprox musi być przekierowany do placówki (w przypadku korzystania z zarządzanej placówki jest to zrobione za Ciebie)."
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Użyj tego dostawcy z auth_request nginx lub forwardAuth traefik. Każda aplikacja/domena potrzebuje własnego dostawcy. Dodatkowo w każdej domenie /outpost.goauthentik.io musi być przekierowany do placówki (w przypadku korzystania z zarządzanej placówki jest to zrobione za Ciebie)."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application."
@ -5912,6 +5933,10 @@ msgstr "Po włączeniu zaproszenie zostanie usunięte po użyciu."
msgid "When enabled, user fields are matched regardless of their casing."
msgstr "Po włączeniu pola użytkownika są dopasowywane niezależnie od wielkości liter."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "When multiple stages are selected, the user can choose which one they want to enroll."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
msgstr "Po wybraniu pole hasła jest wyświetlane na tej samej stronie zamiast na osobnej stronie. Zapobiega to atakom polegającym na wyliczaniu nazw użytkowników."

6648
web/src/locales/pl_PL.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -559,16 +559,16 @@ msgid "Background shown during execution."
msgstr ""
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with errors."
msgstr ""
#~ msgid "Backup finished with errors."
#~ msgstr ""
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with warnings/backup not supported."
msgstr ""
#~ msgid "Backup finished with warnings/backup not supported."
#~ msgstr ""
#: src/pages/admin-overview/AdminOverviewPage.ts
msgid "Backup status"
msgstr ""
#~ msgid "Backup status"
#~ msgstr ""
#: src/pages/providers/ldap/LDAPProviderForm.ts
#: src/pages/providers/ldap/LDAPProviderViewPage.ts
@ -838,6 +838,14 @@ msgstr ""
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr ""
#: src/interfaces/locale.ts
msgid "Chinese (simplified)"
msgstr ""
#: src/interfaces/locale.ts
msgid "Chinese (traditional)"
msgstr ""
#: src/pages/flows/FlowListPage.ts
msgid "Clear Flow cache"
msgstr ""
@ -942,7 +950,11 @@ msgid "Configuration flow"
msgstr ""
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stage"
#~ msgid "Configuration stage"
#~ msgstr ""
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stages"
msgstr ""
#:
@ -2197,6 +2209,10 @@ msgstr ""
msgid "Generic OpenID Connect"
msgstr ""
#: src/interfaces/locale.ts
msgid "German"
msgstr ""
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
msgid "Get this value from https://console.twilio.com"
@ -4473,8 +4489,8 @@ msgid "Stage type"
msgstr ""
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr ""
#~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#~ msgstr ""
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
@ -4533,6 +4549,10 @@ msgstr ""
msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow."
msgstr ""
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr ""
#: src/pages/outposts/ServiceConnectionListPage.ts
msgid "State"
msgstr ""
@ -5004,6 +5024,10 @@ msgstr ""
msgid "TOTP authenticator"
msgstr ""
#: src/interfaces/locale.ts
msgid "Taiwanese Mandarin"
msgstr ""
#: src/pages/flows/StageBindingForm.ts
msgid "Target"
msgstr ""
@ -5653,7 +5677,7 @@ msgid "Use the username and password below to authenticate. The password can be
msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you)."
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts
@ -6016,6 +6040,10 @@ msgstr ""
msgid "When enabled, user fields are matched regardless of their casing."
msgstr ""
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "When multiple stages are selected, the user can choose which one they want to enroll."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
msgstr ""

View File

@ -561,16 +561,16 @@ msgid "Background shown during execution."
msgstr "Yürütme sırasında arka plan gösterilir."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with errors."
msgstr "Yedekleme hatalarla tamamlandı."
#~ msgid "Backup finished with errors."
#~ msgstr "Yedekleme hatalarla tamamlandı."
#: src/pages/admin-overview/cards/BackupStatusCard.ts
msgid "Backup finished with warnings/backup not supported."
msgstr "Yedekleme desteklenmeyen uyarılar/yedekleme ile tamamlandı."
#~ msgid "Backup finished with warnings/backup not supported."
#~ msgstr "Yedekleme desteklenmeyen uyarılar/yedekleme ile tamamlandı."
#: src/pages/admin-overview/AdminOverviewPage.ts
msgid "Backup status"
msgstr "Yedekleme durumu"
#~ msgid "Backup status"
#~ msgstr "Yedekleme durumu"
#: src/pages/providers/ldap/LDAPProviderForm.ts
#: src/pages/providers/ldap/LDAPProviderViewPage.ts
@ -838,6 +838,14 @@ msgstr "İsteğin kullanıcı parolasının son x gün içinde değiştirilip de
msgid "Checks the value from the policy request against several rules, mostly used to ensure password strength."
msgstr "İlke isteğindeki değeri, çoğunlukla parola gücünü sağlamak için kullanılan çeşitli kurallara göre denetler."
#: src/interfaces/locale.ts
msgid "Chinese (simplified)"
msgstr ""
#: src/interfaces/locale.ts
msgid "Chinese (traditional)"
msgstr ""
#: src/pages/flows/FlowListPage.ts
msgid "Clear Flow cache"
msgstr "Akış önbelleğini temizleme"
@ -942,8 +950,12 @@ msgid "Configuration flow"
msgstr "Yapılandırma akışı"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stage"
msgstr "Yapılandırma aşamasında"
#~ msgid "Configuration stage"
#~ msgstr "Yapılandırma aşamasında"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Configuration stages"
msgstr ""
#~ msgid "Configure WebAuthn"
#~ msgstr "WebAuthn'i Yapılandır"
@ -2166,6 +2178,10 @@ msgstr "Jenerik"
msgid "Generic OpenID Connect"
msgstr "Genel OpenID Connect"
#: src/interfaces/locale.ts
msgid "German"
msgstr ""
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
msgid "Get this value from https://console.twilio.com"
@ -4393,8 +4409,8 @@ msgid "Stage type"
msgstr "Aşama türü"
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr "Kullanıcının uyumlu bir aygıtı olmadığında Kimlik Doğrulayıcısı'nı yapılandırmak için kullanılan Aşama. Bu yapılandırma Stage geçtikten sonra kullanıcıya yeniden istenmez."
#~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
#~ msgstr "Kullanıcının uyumlu bir aygıtı olmadığında Kimlik Doğrulayıcısı'nı yapılandırmak için kullanılan Aşama. Bu yapılandırma Stage geçtikten sonra kullanıcıya yeniden istenmez."
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
@ -4453,6 +4469,10 @@ msgstr "Aşamalar"
msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow."
msgstr "Aşamalar, bir Akış'ın kullanıcının yönlendirildiği tek adımlardır. Bir aşama yalnızca bir akış içinden yürütülebilir."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
msgstr ""
#: src/pages/outposts/ServiceConnectionListPage.ts
msgid "State"
msgstr "Eyalet"
@ -4907,6 +4927,10 @@ msgstr "TOTP Cihazı"
msgid "TOTP authenticator"
msgstr "TOTP kimlik doğrulayıcı"
#: src/interfaces/locale.ts
msgid "Taiwanese Mandarin"
msgstr ""
#: src/pages/flows/StageBindingForm.ts
msgid "Target"
msgstr "Hedef"
@ -5558,8 +5582,8 @@ msgid "Use the username and password below to authenticate. The password can be
msgstr "Kimlik doğrulaması için aşağıdaki kullanıcı adı ve parolayı kullanın. Parola daha sonra Belirteçler sayfasından alınabilir."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Bu sağlayıcıyı nginx'in auth_request veya traefik's forwardAuth ile kullanın. Her uygulama/etki alanının kendi sağlayıcısına ihtiyacı vardır. Ayrıca, her etki alanında /akprox üsse yönlendirilmelidir (manged bir üs kullanırken, bu sizin için yapılır)."
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you)."
msgstr "Bu sağlayıcıyı nginx'in auth_request veya traefik's forwardAuth ile kullanın. Her uygulama/etki alanının kendi sağlayıcısına ihtiyacı vardır. Ayrıca, her etki alanında /outpost.goauthentik.io üsse yönlendirilmelidir (manged bir üs kullanırken, bu sizin için yapılır)."
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application."
@ -5914,6 +5938,10 @@ msgstr "Etkinleştirildiğinde, davetiye kullanımdan sonra silinir."
msgid "When enabled, user fields are matched regardless of their casing."
msgstr "Etkinleştirildiğinde, kullanıcı alanları muhafazası ne olursa olsun eşleştirilir."
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
msgid "When multiple stages are selected, the user can choose which one they want to enroll."
msgstr ""
#: src/pages/stages/identification/IdentificationStageForm.ts
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
msgstr "Seçildiğinde, ayrı bir sayfa yerine aynı sayfada bir parola alanı gösterilir. Bu, kullanıcı adı numaralandırma saldırılarını engeller."

6117
web/src/locales/zh-Hans.po Normal file

File diff suppressed because it is too large Load Diff

6117
web/src/locales/zh-Hant.po Normal file

File diff suppressed because it is too large Load Diff

6117
web/src/locales/zh_TW.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,6 @@ import "../../elements/charts/AdminLoginsChart";
import { paramURL } from "../../elements/router/RouterOutlet";
import "./TopApplicationsTable";
import "./cards/AdminStatusCard";
import "./cards/BackupStatusCard";
import "./cards/SystemStatusCard";
import "./cards/VersionStatusCard";
import "./cards/WorkerStatusCard";
@ -166,7 +165,7 @@ export class AdminOverviewPage extends LitElement {
</div>
<!-- row 2 -->
<div
class="pf-l-grid__item pf-m-6-col pf-m-3-col-on-md pf-m-3-col-on-xl card-container"
class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-4-col-on-xl card-container"
>
<ak-admin-status-system
icon="pf-icon pf-icon-server"
@ -175,7 +174,7 @@ export class AdminOverviewPage extends LitElement {
</ak-admin-status-system>
</div>
<div
class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-3-col-on-xl card-container"
class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-4-col-on-xl card-container"
>
<ak-admin-status-version
icon="pf-icon pf-icon-bundle"
@ -185,17 +184,7 @@ export class AdminOverviewPage extends LitElement {
</ak-admin-status-version>
</div>
<div
class="pf-l-grid__item pf-m-6-col pf-m-2-col-on-md pf-m-3-col-on-xl card-container"
>
<ak-admin-status-card-backup
icon="fa fa-database"
header=${t`Backup status`}
headerLink="#/administration/system-tasks"
>
</ak-admin-status-card-backup>
</div>
<div
class="pf-l-grid__item pf-m-6-col pf-m-3-col-on-md pf-m-3-col-on-xl card-container"
class="pf-l-grid__item pf-m-6-col pf-m-4-col-on-md pf-m-4-col-on-xl card-container"
>
<ak-admin-status-card-workers
icon="pf-icon pf-icon-server"

View File

@ -1,56 +0,0 @@
import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { AdminApi, CapabilitiesEnum, StatusEnum } from "@goauthentik/api";
import { DEFAULT_CONFIG, config } from "../../../api/Config";
import { convertToTitle } from "../../../utils";
import { AdminStatus, AdminStatusCard } from "./AdminStatusCard";
@customElement("ak-admin-status-card-backup")
export class BackupStatusCard extends AdminStatusCard<StatusEnum> {
getPrimaryValue(): Promise<StatusEnum> {
return new AdminApi(DEFAULT_CONFIG)
.adminSystemTasksRetrieve({
id: "backup_database",
})
.then((value) => {
return value.status;
})
.catch(() => {
// On error (probably 404), check the config and see if the server
// can even backup
return config().then((c) => {
if (c.capabilities.includes(CapabilitiesEnum.Backup)) {
return StatusEnum.Error;
}
return StatusEnum.Warning;
});
});
}
renderValue(): TemplateResult {
return html`${convertToTitle(this.value?.toString() || "")}`;
}
getStatus(value: StatusEnum): Promise<AdminStatus> {
switch (value) {
case StatusEnum.Successful:
return Promise.resolve<AdminStatus>({
icon: "fa fa-check-circle pf-m-success",
});
case StatusEnum.Error:
return Promise.resolve<AdminStatus>({
icon: "fa fa-times-circle pf-m-danger",
message: html`${t`Backup finished with errors.`}`,
});
default:
return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning",
message: html`${t`Backup finished with warnings/backup not supported.`}`,
});
}
}
}

View File

@ -214,7 +214,7 @@ export class ProxyProviderFormPage extends ModelForm<ProxyProvider, number> {
</ak-form-element-horizontal>`;
case ProxyMode.ForwardSingle:
return html`<p class="pf-u-mb-xl">
${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /akprox must be routed to the outpost (when using a manged outpost, this is done for you).`}
${t`Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a manged outpost, this is done for you).`}
</p>
<ak-form-element-horizontal
label=${t`External host`}

View File

@ -92,16 +92,19 @@ export class ProxyProviderViewPage extends LitElement {
}
renderConfigTemplate(markdown: MarkdownDocument): MarkdownDocument {
const extHost = new URL(this.provider?.externalHost || "http://a");
// See website/docs/providers/proxy/forward_auth.mdx
if (this.provider?.mode === ProxyMode.ForwardSingle) {
markdown.html = markdown.html
.replaceAll("authentik.company", window.location.hostname)
.replaceAll("outpost.company", window.location.hostname)
.replaceAll("app.company", this.provider?.externalHost || "");
.replaceAll("http://outpost.company:9000", window.location.hostname)
.replaceAll("https://app.company", extHost.toString())
.replaceAll("app.company", extHost.hostname);
} else if (this.provider?.mode == ProxyMode.ForwardDomain) {
markdown.html = markdown.html
.replaceAll("authentik.company", window.location.hostname)
.replaceAll("outpost.company", this.provider?.externalHost || "");
.replaceAll("https://app.company", extHost.hostname)
.replaceAll("http://outpost.company:9000", extHost.toString());
}
return markdown;
}

View File

@ -25,14 +25,14 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
stageUuid: pk,
})
.then((stage) => {
this.showConfigurationStage =
this.showConfigurationStages =
stage.notConfiguredAction === NotConfiguredActionEnum.Configure;
return stage;
});
}
@property({ type: Boolean })
showConfigurationStage = true;
showConfigurationStages = true;
getSuccessMessage(): string {
if (this.instance) {
@ -136,9 +136,9 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
target.selectedOptions[0].value ===
NotConfiguredActionEnum.Configure
) {
this.showConfigurationStage = true;
this.showConfigurationStages = true;
} else {
this.showConfigurationStage = false;
this.showConfigurationStages = false;
}
}}
>
@ -165,21 +165,13 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
</option>
</select>
</ak-form-element-horizontal>
${this.showConfigurationStage
${this.showConfigurationStages
? html`
<ak-form-element-horizontal
label=${t`Configuration stage`}
?required=${true}
name="configurationStage"
label=${t`Configuration stages`}
name="configurationStages"
>
<select class="pf-c-form-control">
<option
value=""
?selected=${this.instance?.configurationStage ===
undefined}
>
---------
</option>
<select class="pf-c-form-control" multiple>
${until(
new StagesApi(DEFAULT_CONFIG)
.stagesAllList({
@ -187,9 +179,11 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
})
.then((stages) => {
return stages.results.map((stage) => {
const selected =
this.instance?.configurationStage ===
stage.pk;
const selected = Array.from(
this.instance?.configurationStages || [],
).some((su) => {
return su == stage.pk;
});
return html`<option
value=${ifDefined(stage.pk)}
?selected=${selected}
@ -202,7 +196,10 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
)}
</select>
<p class="pf-c-form__helper-text">
${t`Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.`}
${t`Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.`}
</p>
<p class="pf-c-form__helper-text">
${t`When multiple stages are selected, the user can choose which one they want to enroll.`}
</p>
</ak-form-element-horizontal>
`

View File

@ -153,7 +153,7 @@ export class IdentificationStageForm extends ModelForm<IdentificationStage, stri
?required=${true}
name="sources"
>
<select name="users" class="pf-c-form-control" multiple>
<select class="pf-c-form-control" multiple>
${until(
new SourcesApi(DEFAULT_CONFIG)
.sourcesAllList({})

View File

@ -9,7 +9,7 @@ Applications are used to configure and separate the authorization / access contr
## Authorization
Application access can be configured using (Policy) Bindings. You can use this to grant access to one or multiple users/groups, or dynamically give access using policies.
Application access can be configured using (Policy) Bindings. Click on an application in the applications list, and select the *Policy / Group / User Bindings* tab. There you can bind users/groups/policies to grant them access. When nothing is bound, everyone has access. You can use this to grant access to one or multiple users/groups, or dynamically give access using policies.
By default, all users can access applications when no policies are bound.

View File

@ -23,27 +23,6 @@ All of these variables can be set to values, but you can also use a URI-like for
- `AUTHENTIK_POSTGRESQL__PORT`: Database port, defaults to 5432
- `AUTHENTIK_POSTGRESQL__PASSWORD`: Database password, defaults to the environment variable `POSTGRES_PASSWORD`
### PostgreSQL Backup Settings
:::info
The integrated backup is deprecated in 2022.1 and will be removed in a future version.
:::
- `AUTHENTIK_POSTGRESQL__BACKUP__ENABLED`: Controls if the inbuilt backup-mechanism is enabled, defaults to false (new in 2021.10).
Optionally enable automated database backups to S3 or S3-compatible storages.
- `AUTHENTIK_POSTGRESQL__S3_BACKUP__ACCESS_KEY`: S3 Access Key
- `AUTHENTIK_POSTGRESQL__S3_BACKUP__SECRET_KEY`: S3 Secret Key
- `AUTHENTIK_POSTGRESQL__S3_BACKUP__BUCKET`: S3 Bucket
- `AUTHENTIK_POSTGRESQL__S3_BACKUP__REGION`: S3 Region, defaults to `eu-central-1`
- `AUTHENTIK_POSTGRESQL__S3_BACKUP__LOCATION`: Relative Location of the files to the bucket. Defaults to the root of the bucket.
To use an S3-compatible storage, set the following settings.
- `AUTHENTIK_POSTGRESQL__S3_BACKUP__HOST`: URL to the Service, for example `https://play.min.io`
- `AUTHENTIK_POSTGRESQL__S3_BACKUP__INSECURE_SKIP_VERIFY`: Set to `true` to disable SSL Certificate verification.
## Redis Settings
- `AUTHENTIK_REDIS__HOST`: Hostname of your Redis Server
@ -142,6 +121,16 @@ Disable the inbuilt update-checker. Defaults to `false`.
Placeholder for outpost docker images. Default: `ghcr.io/goauthentik/%(type)s:%(version)s`.
- `AUTHENTIK_OUTPOSTS__DISCOVER`
Configure the automatic discovery of integrations. Defaults to `true`.
By default, the following is discovered:
- Kubernetes in-cluster config
- Kubeconfig
- Existence of a docker socket
### AUTHENTIK_AVATARS
Configure how authentik should show avatars for users. Following values can be set:

View File

@ -21,8 +21,8 @@ If this is a fresh authentik install run the following commands to generate a pa
sudo apt-get install -y pwgen
# Because of a PostgreSQL limitation, only passwords up to 99 chars are supported
# See https://www.postgresql.org/message-id/09512C4F-8CB9-4021-B455-EF4C4F0D55A0@amazon.com
echo "PG_PASS=$(pwgen 40 1)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(pwgen 50 1)" >> .env
echo "PG_PASS=$(pwgen -s 40 1)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(pwgen -s 50 1)" >> .env
# Skip if you don't want to enable error reporting
echo "AUTHENTIK_ERROR_REPORTING__ENABLED=true" >> .env
```

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