mirror of
https://github.com/goauthentik/authentik
synced 2026-05-14 19:06:39 +02:00
Compare commits
96 Commits
version-20
...
website/in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a26cd079ea | ||
|
|
9853224275 | ||
|
|
409f9ec429 | ||
|
|
2c3d11a4c3 | ||
|
|
f9b7d4c6ac | ||
|
|
acbf176d50 | ||
|
|
85d2ac7735 | ||
|
|
a3c50ae92a | ||
|
|
3ef36b9e9e | ||
|
|
691e173cad | ||
|
|
68a6b04749 | ||
|
|
046dbdabe2 | ||
|
|
aae1b32c61 | ||
|
|
87a95eddea | ||
|
|
71025a83ad | ||
|
|
00f0cfe6e4 | ||
|
|
b19f43c8e1 | ||
|
|
5053167a05 | ||
|
|
f4e868210d | ||
|
|
ee954d64f8 | ||
|
|
69facf209f | ||
|
|
561cd8c97b | ||
|
|
d14afe242d | ||
|
|
349a97b1df | ||
|
|
31d8ddc887 | ||
|
|
78f5d85a8b | ||
|
|
c2636d72a4 | ||
|
|
f4d6ebf024 | ||
|
|
75a62b7dca | ||
|
|
9581b90961 | ||
|
|
7dbc01c051 | ||
|
|
e188ddc2ab | ||
|
|
ae073544fe | ||
|
|
a4e0ae9ecd | ||
|
|
086510230d | ||
|
|
8d32228c90 | ||
|
|
1295e2d595 | ||
|
|
008c9fb723 | ||
|
|
9be1b618a5 | ||
|
|
2afe5b5a7b | ||
|
|
af4ccba51e | ||
|
|
d09260f64f | ||
|
|
923c1f465a | ||
|
|
e5208185f9 | ||
|
|
b5deeaa822 | ||
|
|
cceb952429 | ||
|
|
aa5d75c1db | ||
|
|
30495c54f5 | ||
|
|
1a5ac932b5 | ||
|
|
c69b00b580 | ||
|
|
cf5d82a87b | ||
|
|
fd4d61ae9f | ||
|
|
bb8a0373b5 | ||
|
|
c4ba35cfdd | ||
|
|
699e0c06f5 | ||
|
|
b16b5a8e5b | ||
|
|
2efbb9a4c7 | ||
|
|
f8cfd319fd | ||
|
|
b9f429eec8 | ||
|
|
edad4f109e | ||
|
|
b51d498ea2 | ||
|
|
df5c2cc662 | ||
|
|
7e1e7d5e8c | ||
|
|
f2c399af26 | ||
|
|
5b7ba191dc | ||
|
|
0fa1a6c017 | ||
|
|
ec75fb6089 | ||
|
|
82925994b8 | ||
|
|
6967f6f6d9 | ||
|
|
c4a938a6dc | ||
|
|
dec8a03560 | ||
|
|
a8e69b391e | ||
|
|
7315d126d5 | ||
|
|
817bca9c7d | ||
|
|
17083e2e99 | ||
|
|
b8a4ccebb3 | ||
|
|
38fdb4c4e8 | ||
|
|
74b1399ddb | ||
|
|
af51ed4d23 | ||
|
|
251e031a27 | ||
|
|
b65bc06a3d | ||
|
|
97ea93bdcd | ||
|
|
9f2c2988a3 | ||
|
|
c8efb7b82f | ||
|
|
2c452306cf | ||
|
|
c810beca71 | ||
|
|
08316634fc | ||
|
|
88bef0ec5f | ||
|
|
886c494402 | ||
|
|
02f0a087dc | ||
|
|
e03d6347a2 | ||
|
|
34364f4acc | ||
|
|
ea61e1cf3b | ||
|
|
06d72b8386 | ||
|
|
c6771b2277 | ||
|
|
ac3fc88bc9 |
6
.github/actions/setup/action.yml
vendored
6
.github/actions/setup/action.yml
vendored
@@ -52,19 +52,19 @@ runs:
|
||||
run: uv sync --all-extras --dev --locked
|
||||
- name: Setup rust (stable)
|
||||
if: ${{ contains(inputs.dependencies, 'rust') && !contains(inputs.dependencies, 'rust-nightly') }}
|
||||
uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1
|
||||
uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1
|
||||
with:
|
||||
rustflags: ""
|
||||
- name: Setup rust (nightly)
|
||||
if: ${{ contains(inputs.dependencies, 'rust-nightly') }}
|
||||
uses: actions-rust-lang/setup-rust-toolchain@2b1f5e9b395427c92ee4e3331786ca3c37afe2d7 # v1
|
||||
uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
components: rustfmt
|
||||
rustflags: ""
|
||||
- name: Setup rust dependencies
|
||||
if: ${{ contains(inputs.dependencies, 'rust') }}
|
||||
uses: taiki-e/install-action@711e1c3275189d76dcc4d34ddea63bf96ac49090 # v2
|
||||
uses: taiki-e/install-action@ec28e287910af896fd98e04056d31fa68607e7ad # v2
|
||||
with:
|
||||
tool: cargo-deny cargo-machete cargo-llvm-cov nextest
|
||||
- name: Setup node (web)
|
||||
|
||||
6
.github/workflows/qa-codeql.yml
vendored
6
.github/workflows/qa-codeql.yml
vendored
@@ -28,10 +28,10 @@ jobs:
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
uses: github/codeql-action/init@v4.35.4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
uses: github/codeql-action/autobuild@v4.35.4
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
uses: github/codeql-action/analyze@v4.35.4
|
||||
|
||||
4
.github/workflows/release-branch-off.yml
vendored
4
.github/workflows/release-branch-off.yml
vendored
@@ -5,7 +5,7 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
next_version:
|
||||
description: Next major version (for example, if releasing 2042.2, this is 2042.4)
|
||||
description: Next version (for example, if you're currently releasing 2026.5, then enter 2026.8)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
@@ -74,6 +74,8 @@ jobs:
|
||||
run: make migrate
|
||||
- name: Bump version
|
||||
run: "make bump version=${{ inputs.next_version }}.0-rc1"
|
||||
- name: Re-generate API Clients
|
||||
run: make gen
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v7
|
||||
with:
|
||||
|
||||
2
.github/workflows/release-publish.yml
vendored
2
.github/workflows/release-publish.yml
vendored
@@ -191,7 +191,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: aws-actions/configure-aws-credentials@ec61189d14ec14c8efccab744f656cffd0e33f37 # v6.1.0
|
||||
- uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1
|
||||
with:
|
||||
role-to-assume: "arn:aws:iam::016170277896:role/github_goauthentik_authentik"
|
||||
aws-region: ${{ env.AWS_REGION }}
|
||||
|
||||
20
.npmrc
Normal file
20
.npmrc
Normal file
@@ -0,0 +1,20 @@
|
||||
# Block lifecycle scripts (preinstall/install/postinstall/prepare) from dependencies.
|
||||
# This neutralizes the dominant npm supply-chain attack vector.
|
||||
#
|
||||
# Packages that legitimately need a build step (e.g. esbuild, chromedriver, tree-sitter)
|
||||
# must be rebuilt explicitly:
|
||||
#
|
||||
# npm rebuild --foreground-scripts esbuild chromedriver tree-sitter tree-sitter-json
|
||||
ignore-scripts=true
|
||||
|
||||
# Fail fast if the active Node/npm doesn't match the "engines" field.
|
||||
engine-strict=true
|
||||
|
||||
# Pin exact versions so `npm install <pkg>` writes "1.2.3" not "^1.2.3".
|
||||
save-exact=true
|
||||
|
||||
# Surface CVE warnings during install; doesn't block.
|
||||
audit=true
|
||||
|
||||
# Suppress funding banners.
|
||||
fund=false
|
||||
@@ -34,6 +34,7 @@ packages/django-channels-postgres @goauthentik/backend
|
||||
packages/django-postgres-cache @goauthentik/backend
|
||||
packages/django-dramatiq-postgres @goauthentik/backend
|
||||
# Web packages
|
||||
.npmrc @goauthentik/frontend
|
||||
tsconfig.json @goauthentik/frontend
|
||||
package.json @goauthentik/frontend
|
||||
package-lock.json @goauthentik/frontend
|
||||
|
||||
32
Cargo.lock
generated
32
Cargo.lock
generated
@@ -171,7 +171,7 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "authentik"
|
||||
version = "2026.5.0-rc2"
|
||||
version = "2026.8.0-rc1"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"argh",
|
||||
@@ -196,7 +196,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "authentik-axum"
|
||||
version = "2026.5.0-rc2"
|
||||
version = "2026.8.0-rc1"
|
||||
dependencies = [
|
||||
"authentik-common",
|
||||
"axum",
|
||||
@@ -216,7 +216,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "authentik-client"
|
||||
version = "2026.5.0-rc2"
|
||||
version = "2026.8.0-rc1"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"reqwest",
|
||||
@@ -232,7 +232,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "authentik-common"
|
||||
version = "2026.5.0-rc2"
|
||||
version = "2026.8.0-rc1"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"authentik-client",
|
||||
@@ -1744,16 +1744,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iri-string"
|
||||
version = "0.7.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
@@ -3203,9 +3193,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
|
||||
[[package]]
|
||||
name = "sentry"
|
||||
version = "0.48.0"
|
||||
version = "0.48.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8ac94aab850a23d7507307cc505332ed2bafd36c65930dfc5c43610f9e9b477"
|
||||
checksum = "b93b3e19f45495ddd41d8222a152c48c84f6ba45abe9c69e2527e9cdea29bb5b"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"httpdate",
|
||||
@@ -3400,9 +3390,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.18.0"
|
||||
version = "3.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd5414fad8e6907dbdd5bc441a50ae8d6e26151a03b1de04d89a5576de61d01f"
|
||||
checksum = "f05839ce67618e14a09b286535c0d9c94e85ef25469b0e13cb4f844e5593eb19"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
@@ -4082,21 +4072,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.8"
|
||||
version = "0.6.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
|
||||
checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"iri-string",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@@ -8,7 +8,7 @@ members = [
|
||||
resolver = "3"
|
||||
|
||||
[workspace.package]
|
||||
version = "2026.5.0-rc2"
|
||||
version = "2026.8.0-rc1"
|
||||
authors = ["authentik Team <hello@goauthentik.io>"]
|
||||
description = "Making authentication simple."
|
||||
edition = "2024"
|
||||
@@ -67,7 +67,7 @@ reqwest-middleware = { version = "= 0.5.1", features = [
|
||||
"rustls",
|
||||
] }
|
||||
rustls = { version = "= 0.23.40", features = ["fips"] }
|
||||
sentry = { version = "= 0.48.0", default-features = false, features = [
|
||||
sentry = { version = "= 0.48.1", default-features = false, features = [
|
||||
"backtrace",
|
||||
"contexts",
|
||||
"debug-images",
|
||||
@@ -80,7 +80,7 @@ sentry = { version = "= 0.48.0", default-features = false, features = [
|
||||
serde = { version = "= 1.0.228", features = ["derive"] }
|
||||
serde_json = "= 1.0.149"
|
||||
serde_repr = "= 0.1.20"
|
||||
serde_with = { version = "= 3.18.0", default-features = false, features = [
|
||||
serde_with = { version = "= 3.19.0", default-features = false, features = [
|
||||
"base64",
|
||||
] }
|
||||
sqlx = { version = "= 0.8.6", default-features = false, features = [
|
||||
@@ -102,7 +102,7 @@ tokio-retry2 = "= 0.9.1"
|
||||
tokio-rustls = "= 0.26.4"
|
||||
tokio-util = { version = "= 0.7.18", features = ["full"] }
|
||||
tower = "= 0.5.3"
|
||||
tower-http = { version = "= 0.6.8", features = ["timeout"] }
|
||||
tower-http = { version = "= 0.6.10", features = ["timeout"] }
|
||||
tracing = "= 0.1.44"
|
||||
tracing-error = "= 0.2.1"
|
||||
tracing-subscriber = { version = "= 0.3.23", features = [
|
||||
@@ -115,9 +115,9 @@ url = "= 2.5.8"
|
||||
uuid = { version = "= 1.23.1", features = ["serde", "v4"] }
|
||||
which = "= 8.0.2"
|
||||
|
||||
ak-axum = { package = "authentik-axum", version = "2026.5.0-rc2", path = "./packages/ak-axum" }
|
||||
ak-client = { package = "authentik-client", version = "2026.5.0-rc2", path = "./packages/client-rust" }
|
||||
ak-common = { package = "authentik-common", version = "2026.5.0-rc2", path = "./packages/ak-common", default-features = false }
|
||||
ak-axum = { package = "authentik-axum", version = "2026.8.0-rc1", path = "./packages/ak-axum" }
|
||||
ak-client = { package = "authentik-client", version = "2026.8.0-rc1", path = "./packages/client-rust" }
|
||||
ak-common = { package = "authentik-common", version = "2026.8.0-rc1", path = "./packages/ak-common", default-features = false }
|
||||
|
||||
[workspace.lints.rust]
|
||||
ambiguous_negative_literals = "warn"
|
||||
|
||||
18
Makefile
18
Makefile
@@ -125,7 +125,7 @@ core-i18n-extract:
|
||||
--ignore website \
|
||||
-l en
|
||||
|
||||
install: node-install docs-install core-install ## Install all requires dependencies for `node`, `docs` and `core`
|
||||
install: node-install web-install core-install ## Install all requires dependencies for `node`, `web` and `core`
|
||||
|
||||
dev-drop-db:
|
||||
$(eval pg_user := $(shell $(UV) run python -m authentik.lib.config postgresql.user 2>/dev/null))
|
||||
@@ -228,14 +228,26 @@ gen-dev-config: ## Generate a local development config file
|
||||
## Node.js
|
||||
#########################
|
||||
|
||||
# Packages whose install/postinstall scripts are required for correct
|
||||
# operation (binary downloads, native bindings). The root .npmrc sets
|
||||
# `ignore-scripts=true` to block dependency lifecycle scripts by default;
|
||||
# this list is rebuilt explicitly with scripts re-enabled. Audit any
|
||||
# additions: each entry runs arbitrary code at install time.
|
||||
TRUSTED_INSTALL_SCRIPTS := esbuild chromedriver tree-sitter tree-sitter-json
|
||||
|
||||
node-install: ## Install the necessary libraries to build Node.js packages
|
||||
npm ci
|
||||
npm ci --prefix web
|
||||
|
||||
#########################
|
||||
## Web
|
||||
#########################
|
||||
|
||||
web-install: ## Install the necessary libraries to build the Authentik UI
|
||||
npm ci --prefix web
|
||||
|
||||
web-postinstall: ## Trigger postinstall scripts for packages with native bindings or binary downloads, which are blocked by default for security reasons.
|
||||
npm rebuild --prefix web --ignore-scripts=false --foreground-scripts $(TRUSTED_INSTALL_SCRIPTS)
|
||||
|
||||
web-build: node-install ## Build the Authentik UI
|
||||
npm run --prefix web build
|
||||
|
||||
@@ -268,7 +280,7 @@ web-i18n-extract:
|
||||
|
||||
docs: docs-lint-fix docs-build ## Automatically fix formatting issues in the Authentik docs source code, lint the code, and compile it
|
||||
|
||||
docs-install:
|
||||
docs-install: node-install
|
||||
npm ci --prefix website
|
||||
|
||||
docs-lint-fix: lint-spellcheck
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from functools import lru_cache
|
||||
from os import environ
|
||||
|
||||
VERSION = "2026.5.0-rc2"
|
||||
VERSION = "2026.8.0-rc1"
|
||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||
|
||||
|
||||
|
||||
@@ -1,72 +1,14 @@
|
||||
from datetime import datetime
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
from authentik.providers.scim.models import SCIMAuthenticationMode, SCIMProvider
|
||||
from authentik.sources.oauth.models import UserOAuthSourceConnection
|
||||
from authentik.providers.scim.models import SCIMAuthenticationMode
|
||||
|
||||
|
||||
class SCIMProviderSerializerMixin:
|
||||
|
||||
def _get_token(self, instance: SCIMProvider) -> UserOAuthSourceConnection | None:
|
||||
user = instance.auth_oauth_user
|
||||
conn = UserOAuthSourceConnection.objects.filter(
|
||||
user=user, source=instance.auth_oauth
|
||||
).first()
|
||||
return conn
|
||||
|
||||
def get_auth_oauth_token_last_updated(self, instance: SCIMProvider) -> datetime | None:
|
||||
conn = self._get_token(instance)
|
||||
return conn.last_updated if conn else None
|
||||
|
||||
def get_auth_oauth_token_expires(self, instance: SCIMProvider) -> datetime | None:
|
||||
conn = self._get_token(instance)
|
||||
return conn.expires if conn else None
|
||||
|
||||
def get_auth_oauth_url_callback(self, instance: SCIMProvider) -> str | None:
|
||||
if (
|
||||
instance.auth_mode
|
||||
in [
|
||||
SCIMAuthenticationMode.TOKEN,
|
||||
SCIMAuthenticationMode.OAUTH_SILENT,
|
||||
]
|
||||
or not instance.backchannel_application
|
||||
):
|
||||
return None
|
||||
relative_url = reverse(
|
||||
"authentik_enterprise_providers_scim:callback",
|
||||
kwargs={"application_slug": instance.backchannel_application.slug},
|
||||
)
|
||||
if "request" not in self.context:
|
||||
return relative_url
|
||||
return self.context["request"].build_absolute_uri(relative_url)
|
||||
|
||||
def get_auth_oauth_url_start(self, instance: SCIMProvider) -> str | None:
|
||||
if (
|
||||
instance.auth_mode
|
||||
in [
|
||||
SCIMAuthenticationMode.TOKEN,
|
||||
SCIMAuthenticationMode.OAUTH_SILENT,
|
||||
]
|
||||
or not instance.backchannel_application
|
||||
):
|
||||
return None
|
||||
relative_url = reverse(
|
||||
"authentik_enterprise_providers_scim:start",
|
||||
kwargs={"application_slug": instance.backchannel_application.slug},
|
||||
)
|
||||
if "request" not in self.context:
|
||||
return relative_url
|
||||
return self.context["request"].build_absolute_uri(relative_url)
|
||||
|
||||
def validate_auth_mode(self, auth_mode: SCIMAuthenticationMode) -> SCIMAuthenticationMode:
|
||||
if auth_mode in [
|
||||
SCIMAuthenticationMode.OAUTH_SILENT,
|
||||
SCIMAuthenticationMode.OAUTH_INTERACTIVE,
|
||||
]:
|
||||
if auth_mode == SCIMAuthenticationMode.OAUTH:
|
||||
if not LicenseKey.cached_summary().status.is_valid:
|
||||
raise ValidationError(_("Enterprise is required to use the OAuth mode."))
|
||||
return auth_mode
|
||||
|
||||
@@ -7,4 +7,3 @@ class AuthentikEnterpriseProviderSCIMConfig(EnterpriseConfig):
|
||||
label = "authentik_enterprise_providers_scim"
|
||||
verbose_name = "authentik Enterprise.Providers.SCIM"
|
||||
default = True
|
||||
mountpoint = "application/scim/"
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
from datetime import timedelta
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.utils.timezone import now
|
||||
from requests import Request, RequestException
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.common.oauth.constants import GRANT_TYPE_PASSWORD, GRANT_TYPE_REFRESH_TOKEN
|
||||
from authentik.providers.scim.clients.exceptions import SCIMRequestException
|
||||
from authentik.providers.scim.models import SCIMAuthenticationMode
|
||||
from authentik.sources.oauth.clients.base import BaseOAuthClient
|
||||
from authentik.sources.oauth.clients.oauth2 import OAuth2Client
|
||||
from authentik.sources.oauth.models import OAuthSource, UserOAuthSourceConnection
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -20,26 +18,23 @@ class SCIMOAuthException(SCIMRequestException):
|
||||
|
||||
|
||||
class SCIMOAuthAuth:
|
||||
|
||||
def __init__(self, provider: SCIMProvider):
|
||||
self.provider = provider
|
||||
self.user = provider.auth_oauth_user
|
||||
self.logger = get_logger().bind()
|
||||
self.connection = self.get_connection()
|
||||
|
||||
def retrieve_token(self, conn: UserOAuthSourceConnection | None) -> dict[str, Any]:
|
||||
def retrieve_token(self):
|
||||
if not self.provider.auth_oauth:
|
||||
return None
|
||||
source: OAuthSource = self.provider.auth_oauth
|
||||
client: BaseOAuthClient = source.source_type.callback_view(request=None).get_client(source)
|
||||
client = OAuth2Client(source, None)
|
||||
access_token_url = source.source_type.access_token_url or ""
|
||||
if source.source_type.urls_customizable and source.access_token_url:
|
||||
access_token_url = source.access_token_url
|
||||
data = client.get_access_token_args(None, None)
|
||||
if self.provider.auth_mode == SCIMAuthenticationMode.OAUTH_SILENT:
|
||||
data["grant_type"] = GRANT_TYPE_PASSWORD
|
||||
elif self.provider.auth_mode == SCIMAuthenticationMode.OAUTH_INTERACTIVE:
|
||||
data["grant_type"] = GRANT_TYPE_REFRESH_TOKEN
|
||||
if not conn:
|
||||
raise SCIMOAuthException(None, "Could not refresh SCIM OAuth token")
|
||||
data["refresh_token"] = conn.refresh_token
|
||||
data["grant_type"] = "password"
|
||||
data.update(self.provider.auth_oauth_params)
|
||||
try:
|
||||
response = client.do_request(
|
||||
@@ -59,14 +54,12 @@ class SCIMOAuthAuth:
|
||||
raise SCIMOAuthException(exc.response, message="Failed to get OAuth token") from exc
|
||||
|
||||
def get_connection(self):
|
||||
if not self.provider.auth_oauth:
|
||||
return None
|
||||
conn = UserOAuthSourceConnection.objects.filter(
|
||||
source=self.provider.auth_oauth, user=self.user
|
||||
token = UserOAuthSourceConnection.objects.filter(
|
||||
source=self.provider.auth_oauth, user=self.user, expires__gt=now()
|
||||
).first()
|
||||
if conn and conn.access_token and conn.expires > now():
|
||||
return conn
|
||||
token = self.retrieve_token(conn)
|
||||
if token and token.access_token:
|
||||
return token
|
||||
token = self.retrieve_token()
|
||||
access_token = token["access_token"]
|
||||
expires_in = int(token.get("expires_in", 0))
|
||||
token, _ = UserOAuthSourceConnection.objects.update_or_create(
|
||||
@@ -74,10 +67,7 @@ class SCIMOAuthAuth:
|
||||
user=self.user,
|
||||
defaults={
|
||||
"access_token": access_token,
|
||||
"refresh_token": token.get("refresh_token"),
|
||||
"expires": now() + timedelta(seconds=expires_in),
|
||||
# When using `update_or_create`, `last_updated` is not updated
|
||||
"last_updated": now(),
|
||||
},
|
||||
)
|
||||
return token
|
||||
|
||||
@@ -14,10 +14,7 @@ def scim_provider_post_save(sender: type[Model], instance: SCIMProvider, created
|
||||
"""Create service account before provider is saved"""
|
||||
identifier = f"ak-providers-scim-{instance.pk}"
|
||||
with audit_ignore():
|
||||
if instance.auth_mode in [
|
||||
SCIMAuthenticationMode.OAUTH_SILENT,
|
||||
SCIMAuthenticationMode.OAUTH_INTERACTIVE,
|
||||
]:
|
||||
if instance.auth_mode == SCIMAuthenticationMode.OAUTH:
|
||||
user, user_created = User.objects.update_or_create(
|
||||
username=identifier,
|
||||
defaults={
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from base64 import b64encode
|
||||
from datetime import timedelta
|
||||
from urllib.parse import parse_qs, urlencode, urlparse
|
||||
from unittest.mock import MagicMock, PropertyMock, patch
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
@@ -11,14 +11,17 @@ from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.blueprints.tests import apply_blueprint
|
||||
from authentik.core.models import Application, Group, User
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
from authentik.enterprise.models import License
|
||||
from authentik.enterprise.tests.test_license import expiry_valid
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.providers.scim.models import SCIMAuthenticationMode, SCIMMapping, SCIMProvider
|
||||
from authentik.sources.oauth.models import OAuthSource, UserOAuthSourceConnection
|
||||
from authentik.tenants.models import Tenant
|
||||
from tests.live import create_test_admin_user
|
||||
|
||||
|
||||
class TestSCIMOAuthToken(APITestCase):
|
||||
class SCIMOAuthTests(APITestCase):
|
||||
"""SCIM User tests"""
|
||||
|
||||
@apply_blueprint("system/providers-scim.yaml")
|
||||
@@ -39,7 +42,7 @@ class TestSCIMOAuthToken(APITestCase):
|
||||
self.provider = SCIMProvider.objects.create(
|
||||
name=generate_id(),
|
||||
url="https://localhost",
|
||||
auth_mode=SCIMAuthenticationMode.OAUTH_SILENT,
|
||||
auth_mode=SCIMAuthenticationMode.OAUTH,
|
||||
auth_oauth=self.source,
|
||||
auth_oauth_params={
|
||||
"foo": "bar",
|
||||
@@ -57,9 +60,8 @@ class TestSCIMOAuthToken(APITestCase):
|
||||
self.provider.property_mappings_group.add(
|
||||
SCIMMapping.objects.get(managed="goauthentik.io/providers/scim/group")
|
||||
)
|
||||
self.admin = create_test_admin_user()
|
||||
|
||||
def test_retrieve_token_silent(self):
|
||||
def test_retrieve_token(self):
|
||||
"""Test token retrieval"""
|
||||
with Mocker() as mocker:
|
||||
token = generate_id()
|
||||
@@ -84,44 +86,6 @@ class TestSCIMOAuthToken(APITestCase):
|
||||
)
|
||||
self.assertEqual(mocker.request_history[0].body, "grant_type=password&foo=bar")
|
||||
|
||||
def test_retrieve_token_interactive(self):
|
||||
"""Test token retrieval"""
|
||||
self.provider.auth_mode = SCIMAuthenticationMode.OAUTH_INTERACTIVE
|
||||
self.provider.save()
|
||||
refresh_token = generate_id()
|
||||
access_token = generate_id()
|
||||
UserOAuthSourceConnection.objects.create(
|
||||
user=self.provider.auth_oauth_user,
|
||||
source=self.source,
|
||||
refresh_token=refresh_token,
|
||||
access_token=access_token,
|
||||
)
|
||||
with Mocker() as mocker:
|
||||
token = generate_id()
|
||||
mocker.post("http://localhost/token", json={"access_token": token, "expires_in": 3600})
|
||||
self.provider.scim_auth()
|
||||
conn = UserOAuthSourceConnection.objects.filter(
|
||||
source=self.source,
|
||||
user=self.provider.auth_oauth_user,
|
||||
).first()
|
||||
self.assertIsNotNone(conn)
|
||||
self.assertTrue(conn.is_valid)
|
||||
auth = (
|
||||
b64encode(
|
||||
b":".join((self.source.consumer_key.encode(), self.source.consumer_secret.encode()))
|
||||
)
|
||||
.strip()
|
||||
.decode()
|
||||
)
|
||||
self.assertEqual(
|
||||
mocker.request_history[0].headers["Authorization"],
|
||||
f"Basic {auth}",
|
||||
)
|
||||
self.assertEqual(
|
||||
mocker.request_history[0].body,
|
||||
f"grant_type=refresh_token&refresh_token={refresh_token}&foo=bar",
|
||||
)
|
||||
|
||||
def test_existing_token(self):
|
||||
"""Test existing token"""
|
||||
UserOAuthSourceConnection.objects.create(
|
||||
@@ -134,54 +98,96 @@ class TestSCIMOAuthToken(APITestCase):
|
||||
self.provider.scim_auth()
|
||||
self.assertEqual(len(mocker.request_history), 0)
|
||||
|
||||
def test_interactive_start(self):
|
||||
self.client.force_login(self.admin)
|
||||
res = self.client.get(
|
||||
reverse(
|
||||
"authentik_enterprise_providers_scim:start",
|
||||
kwargs={
|
||||
"application_slug": self.app.slug,
|
||||
@Mocker()
|
||||
def test_user_create(self, mock: Mocker):
|
||||
"""Test user creation"""
|
||||
scim_id = generate_id()
|
||||
token = generate_id()
|
||||
mock.post("http://localhost/token", json={"access_token": token, "expires_in": 3600})
|
||||
mock.get(
|
||||
"https://localhost/ServiceProviderConfig",
|
||||
json={},
|
||||
)
|
||||
mock.post(
|
||||
"https://localhost/Users",
|
||||
json={
|
||||
"id": scim_id,
|
||||
},
|
||||
)
|
||||
uid = generate_id()
|
||||
user = User.objects.create(
|
||||
username=uid,
|
||||
name=f"{uid} {uid}",
|
||||
email=f"{uid}@goauthentik.io",
|
||||
)
|
||||
self.assertEqual(mock.call_count, 3)
|
||||
self.assertEqual(mock.request_history[1].method, "GET")
|
||||
self.assertEqual(mock.request_history[2].method, "POST")
|
||||
self.assertJSONEqual(
|
||||
mock.request_history[2].body,
|
||||
{
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
"active": True,
|
||||
"emails": [
|
||||
{
|
||||
"primary": True,
|
||||
"type": "other",
|
||||
"value": f"{uid}@goauthentik.io",
|
||||
}
|
||||
],
|
||||
"externalId": user.uid,
|
||||
"name": {
|
||||
"familyName": uid,
|
||||
"formatted": f"{uid} {uid}",
|
||||
"givenName": uid,
|
||||
},
|
||||
)
|
||||
"displayName": f"{uid} {uid}",
|
||||
"userName": uid,
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
query = parse_qs(urlparse(res.url).query)
|
||||
self.assertEqual(query["client_id"], [self.source.consumer_key])
|
||||
self.assertEqual(
|
||||
query["redirect_uri"],
|
||||
[f"http://testserver/application/scim/{self.app.slug}/oauth2/callback/"],
|
||||
)
|
||||
self.assertEqual(query["response_type"], ["code"])
|
||||
|
||||
def test_interactive_callback(self):
|
||||
self.client.force_login(self.admin)
|
||||
res = self.client.get(
|
||||
reverse(
|
||||
"authentik_enterprise_providers_scim:start",
|
||||
kwargs={
|
||||
"application_slug": self.app.slug,
|
||||
},
|
||||
@patch(
|
||||
"authentik.enterprise.license.LicenseKey.validate",
|
||||
MagicMock(
|
||||
return_value=LicenseKey(
|
||||
aud="",
|
||||
exp=expiry_valid,
|
||||
name=generate_id(),
|
||||
internal_users=100,
|
||||
external_users=100,
|
||||
)
|
||||
),
|
||||
)
|
||||
def test_api_create(self):
|
||||
License.objects.create(key=generate_id())
|
||||
self.client.force_login(create_test_admin_user())
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:scimprovider-list"),
|
||||
{
|
||||
"name": generate_id(),
|
||||
"url": "http://localhost",
|
||||
"auth_mode": "oauth",
|
||||
"auth_oauth": str(self.source.pk),
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
query = parse_qs(urlparse(res.url).query)
|
||||
self.assertEqual(res.status_code, 201)
|
||||
|
||||
with Mocker() as mock:
|
||||
token = generate_id()
|
||||
mock.post("http://localhost/token", json={"access_token": token, "expires_in": 3600})
|
||||
|
||||
res = self.client.get(
|
||||
reverse(
|
||||
"authentik_enterprise_providers_scim:callback",
|
||||
kwargs={
|
||||
"application_slug": self.app.slug,
|
||||
},
|
||||
)
|
||||
+ "?"
|
||||
+ urlencode({"state": query["state"][0], "code": generate_id()})
|
||||
)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
|
||||
conn = UserOAuthSourceConnection.objects.filter(source=self.source).first()
|
||||
self.assertIsNotNone(conn)
|
||||
self.assertTrue(conn.is_valid)
|
||||
@patch(
|
||||
"authentik.enterprise.models.LicenseUsageStatus.is_valid",
|
||||
PropertyMock(return_value=False),
|
||||
)
|
||||
def test_api_create_no_license(self):
|
||||
self.client.force_login(create_test_admin_user())
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:scimprovider-list"),
|
||||
{
|
||||
"name": generate_id(),
|
||||
"url": "http://localhost",
|
||||
"auth_mode": "oauth",
|
||||
"auth_oauth": str(self.source.pk),
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 400)
|
||||
self.assertJSONEqual(
|
||||
res.content, {"auth_mode": ["Enterprise is required to use the OAuth mode."]}
|
||||
)
|
||||
@@ -1,73 +0,0 @@
|
||||
"""SCIM OAuth tests"""
|
||||
|
||||
from unittest.mock import MagicMock, PropertyMock, patch
|
||||
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.enterprise.license import LicenseKey
|
||||
from authentik.enterprise.models import License
|
||||
from authentik.enterprise.tests.test_license import expiry_valid
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.sources.oauth.models import OAuthSource
|
||||
|
||||
|
||||
class TestSCIMOAuthAPI(APITestCase):
|
||||
"""SCIM User tests"""
|
||||
|
||||
def setUp(self):
|
||||
self.source = OAuthSource.objects.create(
|
||||
name=generate_id(),
|
||||
slug=generate_id(),
|
||||
access_token_url="http://localhost/token", # nosec
|
||||
consumer_key=generate_id(),
|
||||
consumer_secret=generate_id(),
|
||||
provider_type="openidconnect",
|
||||
)
|
||||
|
||||
@patch(
|
||||
"authentik.enterprise.license.LicenseKey.validate",
|
||||
MagicMock(
|
||||
return_value=LicenseKey(
|
||||
aud="",
|
||||
exp=expiry_valid,
|
||||
name=generate_id(),
|
||||
internal_users=100,
|
||||
external_users=100,
|
||||
)
|
||||
),
|
||||
)
|
||||
def test_api_create(self):
|
||||
License.objects.create(key=generate_id())
|
||||
self.client.force_login(create_test_admin_user())
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:scimprovider-list"),
|
||||
{
|
||||
"name": generate_id(),
|
||||
"url": "http://localhost",
|
||||
"auth_mode": "oauth",
|
||||
"auth_oauth": str(self.source.pk),
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 201)
|
||||
|
||||
@patch(
|
||||
"authentik.enterprise.models.LicenseUsageStatus.is_valid",
|
||||
PropertyMock(return_value=False),
|
||||
)
|
||||
def test_api_create_no_license(self):
|
||||
self.client.force_login(create_test_admin_user())
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:scimprovider-list"),
|
||||
{
|
||||
"name": generate_id(),
|
||||
"url": "http://localhost",
|
||||
"auth_mode": "oauth",
|
||||
"auth_oauth": str(self.source.pk),
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 400)
|
||||
self.assertJSONEqual(
|
||||
res.content, {"auth_mode": ["Enterprise is required to use the OAuth mode."]}
|
||||
)
|
||||
@@ -1,100 +0,0 @@
|
||||
"""SCIM OAuth tests"""
|
||||
|
||||
from requests_mock import Mocker
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.blueprints.tests import apply_blueprint
|
||||
from authentik.core.models import Application, Group, User
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.providers.scim.models import SCIMAuthenticationMode, SCIMMapping, SCIMProvider
|
||||
from authentik.sources.oauth.models import OAuthSource
|
||||
from authentik.tenants.models import Tenant
|
||||
|
||||
|
||||
class TestSCIMOAuthAuth(APITestCase):
|
||||
"""SCIM User tests"""
|
||||
|
||||
@apply_blueprint("system/providers-scim.yaml")
|
||||
def setUp(self) -> None:
|
||||
# Delete all users and groups as the mocked HTTP responses only return one ID
|
||||
# which will cause errors with multiple users
|
||||
Tenant.objects.update(avatars="none")
|
||||
User.objects.all().exclude_anonymous().delete()
|
||||
Group.objects.all().delete()
|
||||
self.source = OAuthSource.objects.create(
|
||||
name=generate_id(),
|
||||
slug=generate_id(),
|
||||
access_token_url="http://localhost/token", # nosec
|
||||
consumer_key=generate_id(),
|
||||
consumer_secret=generate_id(),
|
||||
provider_type="openidconnect",
|
||||
)
|
||||
self.provider = SCIMProvider.objects.create(
|
||||
name=generate_id(),
|
||||
url="https://localhost",
|
||||
auth_mode=SCIMAuthenticationMode.OAUTH_SILENT,
|
||||
auth_oauth=self.source,
|
||||
auth_oauth_params={
|
||||
"foo": "bar",
|
||||
},
|
||||
exclude_users_service_account=True,
|
||||
)
|
||||
self.app: Application = Application.objects.create(
|
||||
name=generate_id(),
|
||||
slug=generate_id(),
|
||||
)
|
||||
self.app.backchannel_providers.add(self.provider)
|
||||
self.provider.property_mappings.add(
|
||||
SCIMMapping.objects.get(managed="goauthentik.io/providers/scim/user")
|
||||
)
|
||||
self.provider.property_mappings_group.add(
|
||||
SCIMMapping.objects.get(managed="goauthentik.io/providers/scim/group")
|
||||
)
|
||||
|
||||
@Mocker()
|
||||
def test_user_create(self, mock: Mocker):
|
||||
"""Test user creation"""
|
||||
scim_id = generate_id()
|
||||
token = generate_id()
|
||||
mock.post("http://localhost/token", json={"access_token": token, "expires_in": 3600})
|
||||
mock.get(
|
||||
"https://localhost/ServiceProviderConfig",
|
||||
json={},
|
||||
)
|
||||
mock.post(
|
||||
"https://localhost/Users",
|
||||
json={
|
||||
"id": scim_id,
|
||||
},
|
||||
)
|
||||
uid = generate_id()
|
||||
user = User.objects.create(
|
||||
username=uid,
|
||||
name=f"{uid} {uid}",
|
||||
email=f"{uid}@goauthentik.io",
|
||||
)
|
||||
self.assertEqual(mock.call_count, 3)
|
||||
self.assertEqual(mock.request_history[1].method, "GET")
|
||||
self.assertEqual(mock.request_history[2].method, "POST")
|
||||
self.assertJSONEqual(
|
||||
mock.request_history[2].body,
|
||||
{
|
||||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
"active": True,
|
||||
"emails": [
|
||||
{
|
||||
"primary": True,
|
||||
"type": "other",
|
||||
"value": f"{uid}@goauthentik.io",
|
||||
}
|
||||
],
|
||||
"externalId": user.uid,
|
||||
"name": {
|
||||
"familyName": uid,
|
||||
"formatted": f"{uid} {uid}",
|
||||
"givenName": uid,
|
||||
},
|
||||
"displayName": f"{uid} {uid}",
|
||||
"userName": uid,
|
||||
},
|
||||
)
|
||||
@@ -1,10 +0,0 @@
|
||||
from django.urls import path
|
||||
|
||||
from authentik.enterprise.providers.scim.views import SCIMOAuthStart, SCIMRedirectCallback
|
||||
|
||||
urlpatterns = [
|
||||
path("<slug:application_slug>/oauth2/start/", SCIMOAuthStart.as_view(), name="start"),
|
||||
path(
|
||||
"<slug:application_slug>/oauth2/callback/", SCIMRedirectCallback.as_view(), name="callback"
|
||||
),
|
||||
]
|
||||
@@ -1,70 +0,0 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
|
||||
from authentik.core.models import Application
|
||||
from authentik.providers.scim.models import SCIMProvider
|
||||
from authentik.sources.oauth.clients.base import BaseOAuthClient
|
||||
from authentik.sources.oauth.models import OAuthSource, UserOAuthSourceConnection
|
||||
from authentik.sources.oauth.types.registry import RequestKind, registry
|
||||
from authentik.sources.oauth.views.callback import OAuthCallback
|
||||
from authentik.sources.oauth.views.redirect import OAuthRedirect
|
||||
|
||||
|
||||
class SCIMOAuthViewMixin:
|
||||
|
||||
provider: SCIMProvider
|
||||
|
||||
def get_client(self, source: OAuthSource, **kwargs) -> BaseOAuthClient:
|
||||
source: OAuthSource = self.provider.auth_oauth
|
||||
source_cls = registry.find(source.provider_type, kind=RequestKind.CALLBACK)
|
||||
if not source_cls.client_class:
|
||||
return super().get_client(source, **kwargs)
|
||||
return source_cls.client_class(source, self.request, **kwargs)
|
||||
|
||||
def _get_scim_provider(self, app_slug: str):
|
||||
app = Application.objects.filter(slug=app_slug).first()
|
||||
if not app:
|
||||
return None
|
||||
provider = SCIMProvider.objects.filter(backchannel_application=app)
|
||||
return provider.first()
|
||||
|
||||
def dispatch(self, request: HttpRequest, application_slug: str):
|
||||
if not request.user.is_authenticated:
|
||||
raise PermissionDenied()
|
||||
provider = self._get_scim_provider(application_slug)
|
||||
if not provider or not provider.auth_oauth:
|
||||
raise PermissionDenied()
|
||||
if not request.user.has_perm(
|
||||
"authentik_providers_scim.change_scimprovider",
|
||||
provider,
|
||||
):
|
||||
raise PermissionDenied()
|
||||
self.provider = provider
|
||||
return super().dispatch(request, source_slug=provider.auth_oauth.slug)
|
||||
|
||||
|
||||
class SCIMOAuthStart(SCIMOAuthViewMixin, OAuthRedirect):
|
||||
|
||||
def get_callback_url(self, source: OAuthSource):
|
||||
return reverse("authentik_enterprise_providers_scim:callback", kwargs=self.kwargs)
|
||||
|
||||
|
||||
class SCIMRedirectCallback(SCIMOAuthViewMixin, OAuthCallback):
|
||||
|
||||
def redirect_flow_manager(self, client: BaseOAuthClient):
|
||||
expires_in = int(self.token.get("expires_in", 0))
|
||||
UserOAuthSourceConnection.objects.update_or_create(
|
||||
source=self.provider.auth_oauth,
|
||||
user=self.provider.auth_oauth_user,
|
||||
defaults={
|
||||
"access_token": self.token.get("access_token"),
|
||||
"refresh_token": self.token.get("refresh_token"),
|
||||
"expires": now() + timedelta(seconds=expires_in),
|
||||
},
|
||||
)
|
||||
return redirect("authentik_core:if-admin")
|
||||
@@ -1,6 +1,5 @@
|
||||
"""SCIM Provider API Views"""
|
||||
|
||||
from rest_framework.fields import SerializerMethodField
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.core.api.providers import ProviderSerializer
|
||||
@@ -17,11 +16,6 @@ class SCIMProviderSerializer(
|
||||
):
|
||||
"""SCIMProvider Serializer"""
|
||||
|
||||
auth_oauth_token_last_updated = SerializerMethodField()
|
||||
auth_oauth_token_expires = SerializerMethodField()
|
||||
auth_oauth_url_callback = SerializerMethodField()
|
||||
auth_oauth_url_start = SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = SCIMProvider
|
||||
fields = [
|
||||
@@ -41,10 +35,6 @@ class SCIMProviderSerializer(
|
||||
"auth_mode",
|
||||
"auth_oauth",
|
||||
"auth_oauth_params",
|
||||
"auth_oauth_token_last_updated",
|
||||
"auth_oauth_token_expires",
|
||||
"auth_oauth_url_callback",
|
||||
"auth_oauth_url_start",
|
||||
"compatibility_mode",
|
||||
"service_provider_config_cache_timeout",
|
||||
"exclude_users_service_account",
|
||||
|
||||
@@ -102,16 +102,4 @@ class Migration(migrations.Migration):
|
||||
verbose_name="SCIM Compatibility Mode",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="scimprovider",
|
||||
name="auth_mode",
|
||||
field=models.TextField(
|
||||
choices=[
|
||||
("token", "Token"),
|
||||
("oauth", "OAuth (Silent)"),
|
||||
("oauth_interactive", "OAuth (interactive)"),
|
||||
],
|
||||
default="token",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -72,8 +72,7 @@ class SCIMAuthenticationMode(models.TextChoices):
|
||||
"""SCIM authentication modes"""
|
||||
|
||||
TOKEN = "token", _("Token")
|
||||
OAUTH_SILENT = "oauth", _("OAuth (Silent)")
|
||||
OAUTH_INTERACTIVE = "oauth_interactive", _("OAuth (interactive)")
|
||||
OAUTH = "oauth", _("OAuth")
|
||||
|
||||
|
||||
class SCIMCompatibilityMode(models.TextChoices):
|
||||
@@ -145,10 +144,7 @@ class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
||||
)
|
||||
|
||||
def scim_auth(self) -> AuthBase:
|
||||
if self.auth_mode in [
|
||||
SCIMAuthenticationMode.OAUTH_SILENT,
|
||||
SCIMAuthenticationMode.OAUTH_INTERACTIVE,
|
||||
]:
|
||||
if self.auth_mode == SCIMAuthenticationMode.OAUTH:
|
||||
try:
|
||||
from authentik.enterprise.providers.scim.auth_oauth2 import SCIMOAuthAuth
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Source type manager"""
|
||||
|
||||
from collections.abc import Callable
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
@@ -113,7 +114,7 @@ class SourceTypeRegistry:
|
||||
)
|
||||
return found_type
|
||||
|
||||
def find(self, type_name: str, kind: RequestKind) -> type[OAuthCallback | OAuthRedirect]:
|
||||
def find(self, type_name: str, kind: RequestKind) -> Callable:
|
||||
"""Find fitting Source Type"""
|
||||
found_type = self.find_type(type_name)
|
||||
if kind == RequestKind.CALLBACK:
|
||||
|
||||
@@ -15,7 +15,6 @@ from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.sources.flow_manager import SourceFlowManager
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.sources.oauth.clients.base import BaseOAuthClient
|
||||
from authentik.sources.oauth.models import (
|
||||
GroupOAuthSourceConnection,
|
||||
OAuthSource,
|
||||
@@ -30,7 +29,7 @@ class OAuthCallback(OAuthClientMixin, View):
|
||||
"Base OAuth callback view."
|
||||
|
||||
source: OAuthSource
|
||||
token: dict[str, Any] | None = None
|
||||
token: dict | None = None
|
||||
|
||||
def dispatch(self, request: HttpRequest, *_, **kwargs) -> HttpResponse:
|
||||
"""View Get handler"""
|
||||
@@ -50,31 +49,20 @@ class OAuthCallback(OAuthClientMixin, View):
|
||||
if "error" in self.token:
|
||||
return self.handle_login_failure(self.token["error"])
|
||||
# Fetch profile info
|
||||
try:
|
||||
res = self.redirect_flow_manager(client)
|
||||
except ValueError as exc:
|
||||
# if we're authenticated and not in a source stage and this new flag is enabled,
|
||||
# just continue
|
||||
if self.request.user.is_authenticated:
|
||||
pass
|
||||
return self.handle_login_failure(exc.args[0])
|
||||
return res
|
||||
|
||||
def redirect_flow_manager(self, client: BaseOAuthClient) -> HttpResponse:
|
||||
try:
|
||||
raw_info = client.get_profile_info(self.token)
|
||||
if raw_info is None:
|
||||
raise ValueError("Could not retrieve profile.")
|
||||
return self.handle_login_failure("Could not retrieve profile.")
|
||||
except JSONDecodeError as exc:
|
||||
Event.new(
|
||||
EventAction.CONFIGURATION_ERROR,
|
||||
message="Failed to JSON-decode profile.",
|
||||
raw_profile=exc.doc,
|
||||
).from_http(self.request)
|
||||
raise ValueError("Could not retrieve profile.") from None
|
||||
return self.handle_login_failure("Could not retrieve profile.")
|
||||
identifier = self.get_user_id(info=raw_info)
|
||||
if identifier is None:
|
||||
raise ValueError("Could not determine id.")
|
||||
return self.handle_login_failure("Could not determine id.")
|
||||
sfm = OAuthSourceFlowManager(
|
||||
source=self.source,
|
||||
request=self.request,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"$schema": "http://json-schema.org/draft-07/schema",
|
||||
"$id": "https://goauthentik.io/blueprints/schema.json",
|
||||
"type": "object",
|
||||
"title": "authentik 2026.5.0-rc2 Blueprint schema",
|
||||
"title": "authentik 2026.8.0-rc1 Blueprint schema",
|
||||
"required": [
|
||||
"version",
|
||||
"entries"
|
||||
@@ -11203,8 +11203,7 @@
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"token",
|
||||
"oauth",
|
||||
"oauth_interactive"
|
||||
"oauth"
|
||||
],
|
||||
"title": "Auth mode"
|
||||
},
|
||||
|
||||
14
go.mod
14
go.mod
@@ -7,10 +7,10 @@ require (
|
||||
beryju.io/radius-eap v0.1.0
|
||||
github.com/avast/retry-go/v4 v4.7.0
|
||||
github.com/coreos/go-oidc/v3 v3.18.0
|
||||
github.com/getsentry/sentry-go v0.46.1
|
||||
github.com/getsentry/sentry-go v0.46.2
|
||||
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
|
||||
github.com/go-ldap/ldap/v3 v3.4.13
|
||||
github.com/go-openapi/runtime v0.29.4
|
||||
github.com/go-openapi/runtime v0.29.5
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/handlers v1.5.2
|
||||
@@ -57,7 +57,7 @@ require (
|
||||
github.com/go-openapi/jsonreference v0.21.5 // indirect
|
||||
github.com/go-openapi/loads v0.23.3 // indirect
|
||||
github.com/go-openapi/spec v0.22.4 // indirect
|
||||
github.com/go-openapi/strfmt v0.26.1 // indirect
|
||||
github.com/go-openapi/strfmt v0.26.2 // indirect
|
||||
github.com/go-openapi/swag/conv v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/jsonname v0.25.5 // indirect
|
||||
@@ -90,10 +90,10 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
google.golang.org/protobuf v1.36.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
36
go.sum
36
go.sum
@@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/getsentry/sentry-go v0.46.1 h1:mZyQFaQYkPxAdDG4HR8gDg6j4CnKYVWt4TF92N7i3XY=
|
||||
github.com/getsentry/sentry-go v0.46.1/go.mod h1:evVbw2qotNUdYG8KxXbAdjOQWWvWIwKxpjdZZIvcIPw=
|
||||
github.com/getsentry/sentry-go v0.46.2 h1:1jhYwrKGa3sIpo/y5iDNXS5wDoT7I1KNzMHrnK6ojns=
|
||||
github.com/getsentry/sentry-go v0.46.2/go.mod h1:evVbw2qotNUdYG8KxXbAdjOQWWvWIwKxpjdZZIvcIPw=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
@@ -51,12 +51,12 @@ github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe
|
||||
github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw=
|
||||
github.com/go-openapi/loads v0.23.3 h1:g5Xap1JfwKkUnZdn+S0L3SzBDpcTIYzZ5Qaag0YDkKQ=
|
||||
github.com/go-openapi/loads v0.23.3/go.mod h1:NOH07zLajXo8y55hom0omlHWDVVvCwBM/S+csCK8LqA=
|
||||
github.com/go-openapi/runtime v0.29.4 h1:k2lDxrGoSAJRdhFG2tONKMpkizY/4X1cciSdtzk4Jjo=
|
||||
github.com/go-openapi/runtime v0.29.4/go.mod h1:K0k/2raY6oqXJnZAgWJB2i/12QKrhUKpZcH4PfV9P18=
|
||||
github.com/go-openapi/runtime v0.29.5 h1:uc5+/TtqLIfDBTUxnF3uppoGMt+9DzonwUWsviINlrY=
|
||||
github.com/go-openapi/runtime v0.29.5/go.mod h1:D9IUbWccdYv+km8QwmAm90FZvDcQk47vP2Y7y5as/D8=
|
||||
github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ=
|
||||
github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ=
|
||||
github.com/go-openapi/strfmt v0.26.1 h1:7zGCHji7zSYDC2tCXIusoxYQz/48jAf2q+sF6wXTG+c=
|
||||
github.com/go-openapi/strfmt v0.26.1/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y=
|
||||
github.com/go-openapi/strfmt v0.26.2 h1:ysjheCh4i1rmFEo2LanhELDNucNzfWTZhUDKgWWPaFM=
|
||||
github.com/go-openapi/strfmt v0.26.2/go.mod h1:fXh1e449cyUn2NYuz+wb3wARBUdMl7qPEZwX00nqivY=
|
||||
github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I=
|
||||
github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE=
|
||||
github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU=
|
||||
@@ -77,10 +77,10 @@ github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFu
|
||||
github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.2 h1:5zRca5jw7lzVREKCZVNBpysDNBjj74rBh0N2BGQbSR0=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.2/go.mod h1:XVevPw5hUXuV+5AkI1u1PeAm27EQVrhXTTCPAF85LmE=
|
||||
github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4=
|
||||
github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.5.0 h1:3hZD1fwydvCx/cc1R2uYNQirHqf2s6lqpKV3FcNTURA=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.5.0/go.mod h1:TvDZKBH7ZbMaF3EqH2AwTvNQCmzyZq8K1agRjf1B+Nk=
|
||||
github.com/go-openapi/testify/v2 v2.5.0 h1:UOCr63aAsMIDydZbZGqo5Ev01D4eydItRbekDuZMJLw=
|
||||
github.com/go-openapi/testify/v2 v2.5.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||
github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0=
|
||||
github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
@@ -216,8 +216,8 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab h1:628ME69lBm9C6JY2wXhAph/yjN3jezx1z7BIDLUwxjo=
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
@@ -227,8 +227,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -245,8 +245,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -258,8 +258,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
|
||||
@@ -1 +1 @@
|
||||
2026.5.0-rc2
|
||||
2026.8.0-rc1
|
||||
@@ -18,7 +18,7 @@ Parameters:
|
||||
Description: authentik Docker image
|
||||
AuthentikVersion:
|
||||
Type: String
|
||||
Default: 2026.5.0-rc2
|
||||
Default: 2026.8.0-rc1
|
||||
Description: authentik Docker image tag
|
||||
AuthentikServerCPU:
|
||||
Type: Number
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage: Build webui
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-trixie-slim@sha256:735dd688da64d22ebd9dd374b3e7e5a874635668fd2a6ec20ca1f99264294086 AS node-builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-trixie-slim@sha256:4f2b45e32dc7d2caf66b6dbd59fac50e32f8077769efe0ef4d4c3f114672537d AS node-builder
|
||||
|
||||
ARG GIT_BUILD_HASH
|
||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||
|
||||
@@ -31,7 +31,7 @@ services:
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.5.0-rc2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.8.0-rc1}
|
||||
ports:
|
||||
- ${COMPOSE_PORT_HTTP:-9000}:9000
|
||||
- ${COMPOSE_PORT_HTTPS:-9443}:9443
|
||||
@@ -53,7 +53,7 @@ services:
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:?secret key required}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.5.0-rc2}
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.8.0-rc1}
|
||||
restart: unless-stopped
|
||||
shm_size: 512mb
|
||||
user: root
|
||||
|
||||
Binary file not shown.
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-06 00:27+0000\n"
|
||||
"POT-Creation-Date: 2026-05-13 05:39+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -226,6 +226,10 @@ msgstr ""
|
||||
msgid "The slug '{slug}' is reserved and cannot be used for applications."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/api/groups.py
|
||||
msgid "User does not have permission to add members to this group."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/api/providers.py
|
||||
msgid ""
|
||||
"When not set all providers are returned. When set to true, only backchannel "
|
||||
@@ -256,6 +260,14 @@ msgstr ""
|
||||
msgid "Setting a user to internal service account is not allowed."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/api/users.py
|
||||
msgid "User does not have permission to add members to a superuser group."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/api/users.py
|
||||
msgid "User does not have permission to assign roles."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/api/users.py
|
||||
msgid "Can't modify internal service account users"
|
||||
msgstr ""
|
||||
|
||||
@@ -34,6 +34,7 @@ Komodo
|
||||
Kubeconfig
|
||||
Mautic
|
||||
Mobilizon
|
||||
myabsorb
|
||||
Observium
|
||||
Ofair
|
||||
Ollama
|
||||
|
||||
Binary file not shown.
Binary file not shown.
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2026.5.0-rc2",
|
||||
"version": "2026.8.0-rc1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2026.5.0-rc2",
|
||||
"version": "2026.8.0-rc1",
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@goauthentik/eslint-config": "./packages/eslint-config",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2026.5.0-rc2",
|
||||
"version": "2026.8.0-rc1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"lint": "run-s lint:spellcheck lint:lockfile",
|
||||
|
||||
2
packages/client-go/api_core.go
generated
2
packages/client-go/api_core.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/api_crypto.go
generated
2
packages/client-go/api_crypto.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/api_events.go
generated
2
packages/client-go/api_events.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/api_flows.go
generated
2
packages/client-go/api_flows.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/api_outposts.go
generated
2
packages/client-go/api_outposts.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/api_root.go
generated
2
packages/client-go/api_root.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
4
packages/client-go/client.go
generated
4
packages/client-go/client.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
@@ -41,7 +41,7 @@ var (
|
||||
queryDescape = strings.NewReplacer("%5B", "[", "%5D", "]")
|
||||
)
|
||||
|
||||
// APIClient manages communication with the authentik API v2026.5.0-rc2
|
||||
// APIClient manages communication with the authentik API v2026.8.0-rc1
|
||||
// In most cases there should be only one, shared, APIClient.
|
||||
type APIClient struct {
|
||||
cfg *Configuration
|
||||
|
||||
2
packages/client-go/configuration.go
generated
2
packages/client-go/configuration.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_autosubmit_challenge.go
generated
2
packages/client-go/model_autosubmit_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_brand.go
generated
2
packages/client-go/model_brand.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_capabilities_enum.go
generated
2
packages/client-go/model_capabilities_enum.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_captcha_challenge.go
generated
2
packages/client-go/model_captcha_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_certificate_data.go
generated
2
packages/client-go/model_certificate_data.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_certificate_key_pair.go
generated
2
packages/client-go/model_certificate_key_pair.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_challenge_types.go
generated
2
packages/client-go/model_challenge_types.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_config.go
generated
2
packages/client-go/model_config.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_consent_challenge.go
generated
2
packages/client-go/model_consent_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_consent_permission.go
generated
2
packages/client-go/model_consent_permission.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_contextual_flow_info.go
generated
2
packages/client-go/model_contextual_flow_info.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_device_challenge.go
generated
2
packages/client-go/model_device_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_device_classes_enum.go
generated
2
packages/client-go/model_device_classes_enum.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_dummy_challenge.go
generated
2
packages/client-go/model_dummy_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_email_challenge.go
generated
2
packages/client-go/model_email_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_error_detail.go
generated
2
packages/client-go/model_error_detail.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_event.go
generated
2
packages/client-go/model_event.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_event_actions.go
generated
2
packages/client-go/model_event_actions.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_event_request.go
generated
2
packages/client-go/model_event_request.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_flow_error_challenge.go
generated
2
packages/client-go/model_flow_error_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_frame_challenge.go
generated
2
packages/client-go/model_frame_challenge.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
2
packages/client-go/model_generic_error.go
generated
2
packages/client-go/model_generic_error.go
generated
@@ -3,7 +3,7 @@ authentik
|
||||
|
||||
Making authentication simple.
|
||||
|
||||
API version: 2026.5.0-rc2
|
||||
API version: 2026.8.0-rc1
|
||||
Contact: hello@goauthentik.io
|
||||
*/
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user