mirror of
https://github.com/goauthentik/authentik.git
synced 2026-06-17 19:09:11 +03:00
Merge branch 'main' into dev
* main: root: bump pyo3 (#23036) websites/integrations: specify redirect uri of type authorization or post logout (#22981) website/integrations: Update nextcloud to support post logout redirect uri (#22989) stages/captcha: add Cap and JSON verification support (#22373) web: bump @goauthentik/tsconfig from 1.0.9 to 2.0.0 in /web/packages/core in the goauthentik group across 1 directory (#22996) website/integrations: add kavita (#23000) website/integrations: add post logout to audiobookshelf (#22999) website/docs: additional scim provider docs (#22135) translate: Updates for project authentik and language fr_FR (#22986) translate: Updates for project authentik and language hu_HU (#22987) translate: Updates for project authentik and language no_NO (#22988) lifecycle/aws: bump aws-cdk from 2.1125.0 to 2.1126.0 in /lifecycle/aws (#22990) core: bump astral-sh/uv from 0.11.19 to 0.11.20 in /lifecycle/container (#22991) core: bump goauthentik/fips-python from `ede0a00` to `94d8805` in /lifecycle/container (#22992) core: bump uvicorn[standard] from 0.48.0 to 0.49.0 (#22993) core: bump which from 8.0.2 to 8.0.3 (#22994) ci: bump taiki-e/install-action from 2.81.7 to 2.81.8 in /.github/actions/setup (#22995) web/elements: extract mermaid runtime, modernize `<ak-diagram>` (#22980) core, web: update translations (#22983) website/integrations: dokuwiki: add post logout and logout urls (#22984)
This commit is contained in:
@@ -64,7 +64,7 @@ runs:
|
||||
rustflags: ""
|
||||
- name: Setup rust dependencies
|
||||
if: ${{ contains(inputs.dependencies, 'rust') }}
|
||||
uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e # v2
|
||||
uses: taiki-e/install-action@0631aa6515c7d545823c67cfae7ef4fc7f490154 # v2
|
||||
with:
|
||||
tool: cargo-deny cargo-machete cargo-llvm-cov nextest
|
||||
- name: Setup node (root, web)
|
||||
|
||||
Generated
+12
-13
@@ -2642,9 +2642,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3"
|
||||
version = "0.28.3"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91fd8e38a3b50ed1167fb981cd6fd60147e091784c427b8f7183a7ee32c31c12"
|
||||
checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
@@ -2656,18 +2656,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-build-config"
|
||||
version = "0.28.3"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e368e7ddfdeb98c9bca7f8383be1648fd84ab466bf2bc015e94008db6d35611e"
|
||||
checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078"
|
||||
dependencies = [
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-ffi"
|
||||
version = "0.28.3"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f29e10af80b1f7ccaf7f69eace800a03ecd13e883acfacc1e5d0988605f651e"
|
||||
checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pyo3-build-config",
|
||||
@@ -2675,9 +2675,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros"
|
||||
version = "0.28.3"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df6e520eff47c45997d2fc7dd8214b25dd1310918bbb2642156ef66a67f29813"
|
||||
checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"pyo3-macros-backend",
|
||||
@@ -2687,13 +2687,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pyo3-macros-backend"
|
||||
version = "0.28.3"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4cdc218d835738f81c2338f822078af45b4afdf8b2e33cbb5916f108b813acb"
|
||||
checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"pyo3-build-config",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
@@ -4578,9 +4577,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "8.0.2"
|
||||
version = "8.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81995fafaaaf6ae47a7d0cc83c67caf92aeb7e5331650ae6ff856f7c0c60c459"
|
||||
checksum = "c789537cf2f7f55be8e6192f92e464174ee55f91af622777f7f1ceb0dbccd03e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
+3
-3
@@ -48,8 +48,8 @@ metrics-exporter-prometheus = { version = "= 0.18.3", default-features = false }
|
||||
nix = { version = "= 0.31.3", features = ["hostname", "signal"] }
|
||||
notify = "= 8.2.0"
|
||||
pin-project-lite = "= 0.2.17"
|
||||
pyo3 = "= 0.28.3"
|
||||
pyo3-build-config = "= 0.28.3"
|
||||
pyo3 = "= 0.29.0"
|
||||
pyo3-build-config = "= 0.29.0"
|
||||
regex = "= 1.12.3"
|
||||
reqwest = { version = "= 0.13.4", features = [
|
||||
"form",
|
||||
@@ -113,7 +113,7 @@ tracing-subscriber = { version = "= 0.3.23", features = [
|
||||
] }
|
||||
url = "= 2.5.8"
|
||||
uuid = { version = "= 1.23.2", features = ["serde", "v4"] }
|
||||
which = "= 8.0.2"
|
||||
which = "= 8.0.3"
|
||||
|
||||
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" }
|
||||
|
||||
@@ -17,6 +17,7 @@ class CaptchaStageSerializer(StageSerializer):
|
||||
"private_key",
|
||||
"js_url",
|
||||
"api_url",
|
||||
"request_content_type",
|
||||
"interactive",
|
||||
"score_min_threshold",
|
||||
"score_max_threshold",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.2.14 on 2026-05-14 23:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_stages_captcha", "0004_captchastage_interactive"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="captchastage",
|
||||
name="request_content_type",
|
||||
field=models.TextField(
|
||||
choices=[
|
||||
("application/x-www-form-urlencoded", "Form encoded"),
|
||||
("application/json", "JSON"),
|
||||
],
|
||||
default="application/x-www-form-urlencoded",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -8,6 +8,13 @@ from rest_framework.serializers import BaseSerializer
|
||||
from authentik.flows.models import Stage
|
||||
|
||||
|
||||
class CaptchaRequestContentType(models.TextChoices):
|
||||
"""Supported request content types for CAPTCHA verification."""
|
||||
|
||||
FORM = "application/x-www-form-urlencoded", _("Form encoded")
|
||||
JSON = "application/json", _("JSON")
|
||||
|
||||
|
||||
class CaptchaStage(Stage):
|
||||
"""Verify the user is human using Google's reCaptcha/other compatible CAPTCHA solutions."""
|
||||
|
||||
@@ -30,6 +37,10 @@ class CaptchaStage(Stage):
|
||||
|
||||
js_url = models.TextField(default="https://www.recaptcha.net/recaptcha/api.js")
|
||||
api_url = models.TextField(default="https://www.recaptcha.net/recaptcha/api/siteverify")
|
||||
request_content_type = models.TextField(
|
||||
choices=CaptchaRequestContentType.choices,
|
||||
default=CaptchaRequestContentType.FORM,
|
||||
)
|
||||
|
||||
@property
|
||||
def serializer(self) -> type[BaseSerializer]:
|
||||
|
||||
@@ -15,7 +15,7 @@ from authentik.flows.challenge import (
|
||||
from authentik.flows.stage import ChallengeStageView
|
||||
from authentik.lib.utils.http import get_http_session
|
||||
from authentik.root.middleware import ClientIPMiddleware
|
||||
from authentik.stages.captcha.models import CaptchaStage
|
||||
from authentik.stages.captcha.models import CaptchaRequestContentType, CaptchaStage
|
||||
|
||||
LOGGER = get_logger()
|
||||
PLAN_CONTEXT_CAPTCHA = "captcha"
|
||||
@@ -35,17 +35,23 @@ class CaptchaChallenge(WithUserInfoChallenge):
|
||||
|
||||
def verify_captcha_token(stage: CaptchaStage, token: str, remote_ip: str, key: str | None = None):
|
||||
"""Validate captcha token"""
|
||||
payload = {
|
||||
"secret": key or stage.private_key,
|
||||
"response": token,
|
||||
"remoteip": remote_ip,
|
||||
}
|
||||
body_kwargs = (
|
||||
{"json": payload}
|
||||
if stage.request_content_type == CaptchaRequestContentType.JSON
|
||||
else {"data": payload}
|
||||
)
|
||||
try:
|
||||
response = get_http_session().post(
|
||||
stage.api_url,
|
||||
headers={
|
||||
"Content-type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
data={
|
||||
"secret": key or stage.private_key,
|
||||
"response": token,
|
||||
"remoteip": remote_ip,
|
||||
"Content-Type": stage.request_content_type,
|
||||
},
|
||||
**body_kwargs,
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
@@ -10,7 +10,7 @@ from authentik.flows.planner import FlowPlan
|
||||
from authentik.flows.tests import FlowTestCase
|
||||
from authentik.flows.views.executor import SESSION_KEY_PLAN
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.stages.captcha.models import CaptchaStage
|
||||
from authentik.stages.captcha.models import CaptchaRequestContentType, CaptchaStage
|
||||
from authentik.stages.captcha.stage import (
|
||||
PLAN_CONTEXT_CAPTCHA_PRIVATE_KEY,
|
||||
PLAN_CONTEXT_CAPTCHA_SITE_KEY,
|
||||
@@ -56,6 +56,39 @@ class TestCaptchaStage(FlowTestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
|
||||
self.assertEqual(
|
||||
mock.request_history[0].headers["Content-Type"],
|
||||
CaptchaRequestContentType.FORM,
|
||||
)
|
||||
self.assertIn("response=PASSED", mock.request_history[0].text)
|
||||
|
||||
@Mocker()
|
||||
def test_valid_json_content_type(self, mock: Mocker):
|
||||
"""Test valid captcha with JSON verification request"""
|
||||
self.stage.request_content_type = CaptchaRequestContentType.JSON
|
||||
self.stage.save()
|
||||
mock.post(
|
||||
"https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
json={
|
||||
"success": True,
|
||||
"score": 0.5,
|
||||
},
|
||||
)
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
{"token": "PASSED"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
|
||||
self.assertEqual(
|
||||
mock.request_history[0].headers["Content-Type"],
|
||||
CaptchaRequestContentType.JSON,
|
||||
)
|
||||
self.assertEqual(mock.request_history[0].json()["response"], "PASSED")
|
||||
|
||||
@Mocker()
|
||||
def test_valid_override(self, mock: Mocker):
|
||||
|
||||
@@ -15105,6 +15105,14 @@
|
||||
"minLength": 1,
|
||||
"title": "Api url"
|
||||
},
|
||||
"request_content_type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"application/x-www-form-urlencoded",
|
||||
"application/json"
|
||||
],
|
||||
"title": "Request content type"
|
||||
},
|
||||
"interactive": {
|
||||
"type": "boolean",
|
||||
"title": "Interactive"
|
||||
|
||||
Generated
+4
-4
@@ -9,7 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"aws-cdk": "^2.1125.0",
|
||||
"aws-cdk": "^2.1126.0",
|
||||
"cross-env": "^10.1.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -25,9 +25,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/aws-cdk": {
|
||||
"version": "2.1125.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1125.0.tgz",
|
||||
"integrity": "sha512-QAvsE2XQMcyNOjMMqAS7eDADR9t6vcFcMQvhOmtLfDqgfJXSyTkHvzM5zgwZCdJ4FNqWr5Y/zXvL1Cv5ECKXwQ==",
|
||||
"version": "2.1126.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1126.0.tgz",
|
||||
"integrity": "sha512-uNoocb3vCPiAT3j9+SwL6pn/VVggHWBsgC2XpxyhNvYQYt6cE9BM/149GWwtdcwnLrPjnwW1+CV/5nSSh5dV+w==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"aws-cfn": "cross-env CI=false cdk synth --version-reporting=false > template.yaml"
|
||||
},
|
||||
"devDependencies": {
|
||||
"aws-cdk": "^2.1125.0",
|
||||
"aws-cdk": "^2.1126.0",
|
||||
"cross-env": "^10.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -116,9 +116,9 @@ RUN --mount=type=bind,target=rust-toolchain.toml,src=rust-toolchain.toml \
|
||||
RUN cat /root/.rustup/settings.toml
|
||||
|
||||
# Stage: Download uv
|
||||
FROM ghcr.io/astral-sh/uv:0.11.19@sha256:b46b03ddfcfbf8f547af7e9eaefdf8a39c8cebcba7c98858d3162bd28cf536f6 AS uv
|
||||
FROM ghcr.io/astral-sh/uv:0.11.20@sha256:eaa5f1a3305307aaf9e67fe2bbba1d85ebbb2d8a63bce23af21797bfafbe0f8b AS uv
|
||||
# Stage: Base python image
|
||||
FROM ghcr.io/goauthentik/fips-python:3.14.5-slim-trixie-fips@sha256:ede0a006a873bfd3e66fd0e56827bc8e46ea75341e1a6a35dae6edd6ad6be691 AS python-base
|
||||
FROM ghcr.io/goauthentik/fips-python:3.14.5-slim-trixie-fips@sha256:94d880542ff5e74bd50b874680fd68a04fe6bb34b7f25e8a081b62b7e1ae6dc3 AS python-base
|
||||
|
||||
ENV VENV_PATH="/ak-root/.venv" \
|
||||
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-22 00:36+0000\n"
|
||||
"POT-Creation-Date: 2026-06-11 00:42+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"
|
||||
@@ -3399,14 +3399,6 @@ msgstr ""
|
||||
msgid "Google OAuth Sources"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Source"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Sources"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Entra ID OAuth Source"
|
||||
msgstr ""
|
||||
|
||||
@@ -15,7 +15,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-22 00:36+0000\n"
|
||||
"POT-Creation-Date: 2026-06-11 00:42+0000\n"
|
||||
"PO-Revision-Date: 2025-12-01 19:09+0000\n"
|
||||
"Last-Translator: Sp P, 2026\n"
|
||||
"Language-Team: French (France) (https://app.transifex.com/authentik/teams/119923/fr_FR/)\n"
|
||||
@@ -3790,14 +3790,6 @@ msgstr "Source d'OAuth Google"
|
||||
msgid "Google OAuth Sources"
|
||||
msgstr "Source d'OAuth Google"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Source"
|
||||
msgstr "Source d'OAuth Azure AD"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Sources"
|
||||
msgstr "Source d'OAuth Azure AD"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Entra ID OAuth Source"
|
||||
msgstr "Source d'OAuth Entra ID"
|
||||
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-22 00:36+0000\n"
|
||||
"POT-Creation-Date: 2026-06-11 00:42+0000\n"
|
||||
"PO-Revision-Date: 2025-12-01 19:09+0000\n"
|
||||
"Last-Translator: Gyula Kiss <kiss@indi.hu>, 2026\n"
|
||||
"Language-Team: Hungarian (Hungary) (https://app.transifex.com/authentik/teams/119923/hu_HU/)\n"
|
||||
@@ -3780,14 +3780,6 @@ msgstr "Google OAuth forrás"
|
||||
msgid "Google OAuth Sources"
|
||||
msgstr "Google OAuth források"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Source"
|
||||
msgstr "Azure AD OAuth forrás"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Sources"
|
||||
msgstr "Azure AD OAuth források"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Entra ID OAuth Source"
|
||||
msgstr "Entra ID OAuth forrás"
|
||||
|
||||
@@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-22 00:36+0000\n"
|
||||
"POT-Creation-Date: 2026-06-11 00:42+0000\n"
|
||||
"PO-Revision-Date: 2025-12-01 19:09+0000\n"
|
||||
"Last-Translator: Raphael Cancelliere, 2026\n"
|
||||
"Language-Team: Norwegian (Norway) (https://app.transifex.com/authentik/teams/119923/no_NO/)\n"
|
||||
@@ -3692,14 +3692,6 @@ msgstr "Google OAuth-kilde"
|
||||
msgid "Google OAuth Sources"
|
||||
msgstr "Google OAuth-kilder"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Source"
|
||||
msgstr "Azure AD OAuth-kilde"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Azure AD OAuth Sources"
|
||||
msgstr "Azure AD OAuth-kilder"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Entra ID OAuth Source"
|
||||
msgstr "Entra ID OAuth-kilde"
|
||||
|
||||
+16
@@ -14,6 +14,11 @@
|
||||
|
||||
import type { FlowSet } from "./FlowSet";
|
||||
import { FlowSetFromJSON } from "./FlowSet";
|
||||
import type { RequestContentTypeEnum } from "./RequestContentTypeEnum";
|
||||
import {
|
||||
RequestContentTypeEnumFromJSON,
|
||||
RequestContentTypeEnumToJSON,
|
||||
} from "./RequestContentTypeEnum";
|
||||
|
||||
/**
|
||||
* CaptchaStage Serializer
|
||||
@@ -81,6 +86,12 @@ export interface CaptchaStage {
|
||||
* @memberof CaptchaStage
|
||||
*/
|
||||
apiUrl?: string;
|
||||
/**
|
||||
*
|
||||
* @type {RequestContentTypeEnum}
|
||||
* @memberof CaptchaStage
|
||||
*/
|
||||
requestContentType?: RequestContentTypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
@@ -141,6 +152,10 @@ export function CaptchaStageFromJSONTyped(json: any, ignoreDiscriminator: boolea
|
||||
publicKey: json["public_key"],
|
||||
jsUrl: json["js_url"] == null ? undefined : json["js_url"],
|
||||
apiUrl: json["api_url"] == null ? undefined : json["api_url"],
|
||||
requestContentType:
|
||||
json["request_content_type"] == null
|
||||
? undefined
|
||||
: RequestContentTypeEnumFromJSON(json["request_content_type"]),
|
||||
interactive: json["interactive"] == null ? undefined : json["interactive"],
|
||||
scoreMinThreshold:
|
||||
json["score_min_threshold"] == null ? undefined : json["score_min_threshold"],
|
||||
@@ -171,6 +186,7 @@ export function CaptchaStageToJSONTyped(
|
||||
public_key: value["publicKey"],
|
||||
js_url: value["jsUrl"],
|
||||
api_url: value["apiUrl"],
|
||||
request_content_type: RequestContentTypeEnumToJSON(value["requestContentType"]),
|
||||
interactive: value["interactive"],
|
||||
score_min_threshold: value["scoreMinThreshold"],
|
||||
score_max_threshold: value["scoreMaxThreshold"],
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import type { RequestContentTypeEnum } from "./RequestContentTypeEnum";
|
||||
import {
|
||||
RequestContentTypeEnumFromJSON,
|
||||
RequestContentTypeEnumToJSON,
|
||||
} from "./RequestContentTypeEnum";
|
||||
|
||||
/**
|
||||
* CaptchaStage Serializer
|
||||
* @export
|
||||
@@ -48,6 +54,12 @@ export interface CaptchaStageRequest {
|
||||
* @memberof CaptchaStageRequest
|
||||
*/
|
||||
apiUrl?: string;
|
||||
/**
|
||||
*
|
||||
* @type {RequestContentTypeEnum}
|
||||
* @memberof CaptchaStageRequest
|
||||
*/
|
||||
requestContentType?: RequestContentTypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
@@ -101,6 +113,10 @@ export function CaptchaStageRequestFromJSONTyped(
|
||||
privateKey: json["private_key"],
|
||||
jsUrl: json["js_url"] == null ? undefined : json["js_url"],
|
||||
apiUrl: json["api_url"] == null ? undefined : json["api_url"],
|
||||
requestContentType:
|
||||
json["request_content_type"] == null
|
||||
? undefined
|
||||
: RequestContentTypeEnumFromJSON(json["request_content_type"]),
|
||||
interactive: json["interactive"] == null ? undefined : json["interactive"],
|
||||
scoreMinThreshold:
|
||||
json["score_min_threshold"] == null ? undefined : json["score_min_threshold"],
|
||||
@@ -129,6 +145,7 @@ export function CaptchaStageRequestToJSONTyped(
|
||||
private_key: value["privateKey"],
|
||||
js_url: value["jsUrl"],
|
||||
api_url: value["apiUrl"],
|
||||
request_content_type: RequestContentTypeEnumToJSON(value["requestContentType"]),
|
||||
interactive: value["interactive"],
|
||||
score_min_threshold: value["scoreMinThreshold"],
|
||||
score_max_threshold: value["scoreMaxThreshold"],
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import type { RequestContentTypeEnum } from "./RequestContentTypeEnum";
|
||||
import {
|
||||
RequestContentTypeEnumFromJSON,
|
||||
RequestContentTypeEnumToJSON,
|
||||
} from "./RequestContentTypeEnum";
|
||||
|
||||
/**
|
||||
* CaptchaStage Serializer
|
||||
* @export
|
||||
@@ -48,6 +54,12 @@ export interface PatchedCaptchaStageRequest {
|
||||
* @memberof PatchedCaptchaStageRequest
|
||||
*/
|
||||
apiUrl?: string;
|
||||
/**
|
||||
*
|
||||
* @type {RequestContentTypeEnum}
|
||||
* @memberof PatchedCaptchaStageRequest
|
||||
*/
|
||||
requestContentType?: RequestContentTypeEnum;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
@@ -100,6 +112,10 @@ export function PatchedCaptchaStageRequestFromJSONTyped(
|
||||
privateKey: json["private_key"] == null ? undefined : json["private_key"],
|
||||
jsUrl: json["js_url"] == null ? undefined : json["js_url"],
|
||||
apiUrl: json["api_url"] == null ? undefined : json["api_url"],
|
||||
requestContentType:
|
||||
json["request_content_type"] == null
|
||||
? undefined
|
||||
: RequestContentTypeEnumFromJSON(json["request_content_type"]),
|
||||
interactive: json["interactive"] == null ? undefined : json["interactive"],
|
||||
scoreMinThreshold:
|
||||
json["score_min_threshold"] == null ? undefined : json["score_min_threshold"],
|
||||
@@ -128,6 +144,7 @@ export function PatchedCaptchaStageRequestToJSONTyped(
|
||||
private_key: value["privateKey"],
|
||||
js_url: value["jsUrl"],
|
||||
api_url: value["apiUrl"],
|
||||
request_content_type: RequestContentTypeEnumToJSON(value["requestContentType"]),
|
||||
interactive: value["interactive"],
|
||||
score_min_threshold: value["scoreMinThreshold"],
|
||||
score_max_threshold: value["scoreMaxThreshold"],
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.8.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
export const RequestContentTypeEnum = {
|
||||
ApplicationXWwwFormUrlencoded: "application/x-www-form-urlencoded",
|
||||
ApplicationJson: "application/json",
|
||||
UnknownDefaultOpenApi: "11184809",
|
||||
} as const;
|
||||
export type RequestContentTypeEnum =
|
||||
(typeof RequestContentTypeEnum)[keyof typeof RequestContentTypeEnum];
|
||||
|
||||
export function instanceOfRequestContentTypeEnum(value: any): boolean {
|
||||
for (const key in RequestContentTypeEnum) {
|
||||
if (Object.prototype.hasOwnProperty.call(RequestContentTypeEnum, key)) {
|
||||
if (RequestContentTypeEnum[key as keyof typeof RequestContentTypeEnum] === value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function RequestContentTypeEnumFromJSON(json: any): RequestContentTypeEnum {
|
||||
return RequestContentTypeEnumFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function RequestContentTypeEnumFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): RequestContentTypeEnum {
|
||||
return json as RequestContentTypeEnum;
|
||||
}
|
||||
|
||||
export function RequestContentTypeEnumToJSON(value?: RequestContentTypeEnum | null): any {
|
||||
return value as any;
|
||||
}
|
||||
|
||||
export function RequestContentTypeEnumToJSONTyped(
|
||||
value: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): RequestContentTypeEnum {
|
||||
return value as RequestContentTypeEnum;
|
||||
}
|
||||
Generated
+1
@@ -713,6 +713,7 @@ export * from "./RelatedRule";
|
||||
export * from "./Reputation";
|
||||
export * from "./ReputationPolicy";
|
||||
export * from "./ReputationPolicyRequest";
|
||||
export * from "./RequestContentTypeEnum";
|
||||
export * from "./Review";
|
||||
export * from "./ReviewRequest";
|
||||
export * from "./ReviewerGroup";
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ dependencies = [
|
||||
"ua-parser==1.0.2",
|
||||
"unidecode==1.4.0",
|
||||
"urllib3<3",
|
||||
"uvicorn[standard]==0.48.0",
|
||||
"uvicorn[standard]==0.49.0",
|
||||
"watchdog==6.0.0",
|
||||
"webauthn==2.7.1",
|
||||
"wsproto==1.3.2",
|
||||
|
||||
+11
@@ -36333,6 +36333,8 @@ components:
|
||||
type: string
|
||||
api_url:
|
||||
type: string
|
||||
request_content_type:
|
||||
$ref: '#/components/schemas/RequestContentTypeEnum'
|
||||
interactive:
|
||||
type: boolean
|
||||
score_min_threshold:
|
||||
@@ -36378,6 +36380,8 @@ components:
|
||||
api_url:
|
||||
type: string
|
||||
minLength: 1
|
||||
request_content_type:
|
||||
$ref: '#/components/schemas/RequestContentTypeEnum'
|
||||
interactive:
|
||||
type: boolean
|
||||
score_min_threshold:
|
||||
@@ -48260,6 +48264,8 @@ components:
|
||||
api_url:
|
||||
type: string
|
||||
minLength: 1
|
||||
request_content_type:
|
||||
$ref: '#/components/schemas/RequestContentTypeEnum'
|
||||
interactive:
|
||||
type: boolean
|
||||
score_min_threshold:
|
||||
@@ -53805,6 +53811,11 @@ components:
|
||||
minimum: -2147483648
|
||||
required:
|
||||
- name
|
||||
RequestContentTypeEnum:
|
||||
enum:
|
||||
- application/x-www-form-urlencoded
|
||||
- application/json
|
||||
type: string
|
||||
Review:
|
||||
type: object
|
||||
description: |-
|
||||
|
||||
@@ -422,7 +422,7 @@ requires-dist = [
|
||||
{ name = "ua-parser", specifier = "==1.0.2" },
|
||||
{ name = "unidecode", specifier = "==1.4.0" },
|
||||
{ name = "urllib3", specifier = "<3" },
|
||||
{ name = "uvicorn", extras = ["standard"], specifier = "==0.48.0" },
|
||||
{ name = "uvicorn", extras = ["standard"], specifier = "==0.49.0" },
|
||||
{ name = "watchdog", specifier = "==6.0.0" },
|
||||
{ name = "webauthn", specifier = "==2.7.1" },
|
||||
{ name = "wsproto", specifier = "==1.3.2" },
|
||||
@@ -1812,17 +1812,24 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "httptools"
|
||||
version = "0.7.1"
|
||||
version = "0.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b5/46/120a669232c7bdedb9d52d4aeae7e6c7dfe151e99dc70802e2fc7a5e1993/httptools-0.7.1.tar.gz", hash = "sha256:abd72556974f8e7c74a259655924a717a2365b236c882c3f6f8a45fe94703ac9", size = 258961, upload-time = "2025-10-10T03:55:08.559Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/43/e5/d471fcb0e14523fe1c3f4ba58ca52480e7bd70ad7109a3846bc75892f7fb/httptools-0.8.0.tar.gz", hash = "sha256:6b2a32f18d97e16e90827d7a819ffa8dbd8cc245fc4e1fa9d1095b54ef4bd999", size = 271342, upload-time = "2026-05-25T22:17:48.841Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/34/50/9d095fcbb6de2d523e027a2f304d4551855c2f46e0b82befd718b8b20056/httptools-0.7.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c08fe65728b8d70b6923ce31e3956f859d5e1e8548e6f22ec520a962c6757270", size = 203619, upload-time = "2025-10-10T03:54:54.321Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/f0/89720dc5139ae54b03f861b5e2c55a37dba9a5da7d51e1e824a1f343627f/httptools-0.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7aea2e3c3953521c3c51106ee11487a910d45586e351202474d45472db7d72d3", size = 108714, upload-time = "2025-10-10T03:54:55.163Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/cb/eea88506f191fb552c11787c23f9a405f4c7b0c5799bf73f2249cd4f5228/httptools-0.7.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0e68b8582f4ea9166be62926077a3334064d422cf08ab87d8b74664f8e9058e1", size = 472909, upload-time = "2025-10-10T03:54:56.056Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/4a/a548bdfae6369c0d078bab5769f7b66f17f1bfaa6fa28f81d6be6959066b/httptools-0.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df091cf961a3be783d6aebae963cc9b71e00d57fa6f149025075217bc6a55a7b", size = 470831, upload-time = "2025-10-10T03:54:57.219Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/31/14df99e1c43bd132eec921c2e7e11cda7852f65619bc0fc5bdc2d0cb126c/httptools-0.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f084813239e1eb403ddacd06a30de3d3e09a9b76e7894dcda2b22f8a726e9c60", size = 452631, upload-time = "2025-10-10T03:54:58.219Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/d2/b7e131f7be8d854d48cb6d048113c30f9a46dca0c9a8b08fcb3fcd588cdc/httptools-0.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7347714368fb2b335e9063bc2b96f2f87a9ceffcd9758ac295f8bbcd3ffbc0ca", size = 452910, upload-time = "2025-10-10T03:54:59.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/cf/878f3b91e4e6e011eff6d1fa9ca39f7eb17d19c9d7971b04873734112f30/httptools-0.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:cfabda2a5bb85aa2a904ce06d974a3f30fb36cc63d7feaddec05d2050acede96", size = 88205, upload-time = "2025-10-10T03:55:00.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/12/fa3fbf5f9517b273edea2dc982aa82a8c634091e67c590792b729017bc6f/httptools-0.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:de242a49b5d18e0a8776e654e9f6bf6d89f3875a5c35b425a0e7ce940feb3fd6", size = 206183, upload-time = "2026-05-25T22:17:24.004Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/fc/5e7c4cb443370f2090a3aba0453a07384d29ff66b7435bb90e77e1037599/httptools-0.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:159e9ab5f701ccd42e555a12f1ad8ff69702910fc1c996cf2bb66e5fcb7a231b", size = 112079, upload-time = "2026-05-25T22:17:25.216Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/53/771bd891eb0f236f32145d6a1775777ec85745f3cc983a1f23d1a3b8ddfe/httptools-0.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c4a9f1707e4823d54dfec6c33fa3697d302aed536ed352a7ebb5a061ddb869d0", size = 481596, upload-time = "2026-05-25T22:17:26.186Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/42/94e15bc68ce3d423243c45d7f1b0c7561f13844f97dc52ae23182fb65628/httptools-0.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d76ad7b951387e3632c8716a9bb03ac5b45c5f16119aa409db0459520887944e", size = 480865, upload-time = "2026-05-25T22:17:27.542Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/7c/fe2980fc03723272e30f135b62360b075f513dfe7cc73aef36c7f04012bd/httptools-0.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a3b7387147361c3fd47a0bde763c5c91b5b4cd4dc9989b8ece84ff436c99843b", size = 463189, upload-time = "2026-05-25T22:17:28.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/1b/47fc5fff68acd1bfa20b4734059c9a06cadb88119dcd5258b5b0d21d91c8/httptools-0.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f256d6ce930c52ca1cb2a960b7da03548c454e7d28b06059ad41bfe789036ce0", size = 466610, upload-time = "2026-05-25T22:17:29.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/bd/07b13c93ffd9bec9546e0d43f8e19378dd696dbd278511406bc07371ef1f/httptools-0.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:19d1ee275bb59ba2643ba9a3a1e51cc0c788caf2b8df506368e03f56fdd08527", size = 92705, upload-time = "2026-05-25T22:17:31.133Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/c4/121648f68ce066d7bd762d6b6d97e620847642d38d54f3d90ff11d947629/httptools-0.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:de1ed58a974e75d56560acc7e7fed01a454994429456f65209789992e41f2568", size = 215023, upload-time = "2026-05-25T22:17:32.401Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/b0/312a062ae741ae3e8baa8c8bf20be81b2e67337b259ab4349bebc7b6142e/httptools-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e93c227b595c6926c1acee96891dd9da4be338cfbe82e5cd3bb9d8dd7dc4ac0b", size = 117405, upload-time = "2026-05-25T22:17:33.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/37/fccd705f795386bb05bf413012fecff2a33e5aa8c2f069096de3e9fd8702/httptools-0.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2a021c3a8e65cc125390d72f59b968afca3bdcaff25bd67965e0a055a14946ca", size = 558497, upload-time = "2026-05-25T22:17:34.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/39/f172e8003576de35f5ba77ff417cf0e34429d35dc014deef15afa337a72c/httptools-0.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48774d39cbb70e2b1f71f88852a3087ae1d3a1eb80482bb48c13067ab080c14f", size = 571585, upload-time = "2026-05-25T22:17:35.813Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/b9/f5564760af99f3dbbf3f9104dc00e5da27e96cf433c6bdcf77617f70bf3f/httptools-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:88eead8ec8680a9f146c655bc88445a325bd7921cfd8194c7337e9467282427d", size = 543297, upload-time = "2026-05-25T22:17:37.08Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/67/8d9f2c313618e161b82f3873188e7196126da1d6e29688df40eb3997c77a/httptools-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2c032fa028f46871ec7e1fc59fc15e8023eab3e6bbe6ece786a1611719a5d081", size = 539535, upload-time = "2026-05-25T22:17:38.032Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/63/b906c01e53f50d432c0defe43ce52764a111dc1bdd028bafbeb54dcfd008/httptools-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:384c17174464c8e873398b7af24f0b1f44d992c820328413951a625323155d77", size = 108209, upload-time = "2026-05-25T22:17:39.473Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3853,15 +3860,15 @@ socks = [
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.48.0"
|
||||
version = "0.49.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e6/bf/f6544ba992ddb9a6077343a576f9844f7f8f06ab819aefd00206e9255f18/uvicorn-0.48.0.tar.gz", hash = "sha256:a5504207195d08c2511bf9125ede5ac4a4b71725d519e758d01dcf0bc2d31c37", size = 91074, upload-time = "2026-05-24T12:08:41.925Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c4/1f/fa18009dea8469069cca78a4e877a008ab78f08b064bfc9ab891579077ff/uvicorn-0.49.0.tar.gz", hash = "sha256:ebf4271aa580d9de97f93192d4595176df6e91f9aae919ca73e4fc07df1e66a3", size = 91284, upload-time = "2026-06-03T22:01:30.448Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/01/be/72532be3da7acc5fdfbccdb95215cd04f995a0886532a5b423f929cda4cc/uvicorn-0.48.0-py3-none-any.whl", hash = "sha256:48097851328b87ec36117d3d575234519eb58c2b22d79666e9bbc6c49a761dad", size = 71410, upload-time = "2026-05-24T12:08:40.258Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/fa/e1388bbcf24ef3274f45c0c1c7b501fd14971037c1b6ee23610553307497/uvicorn-0.49.0-py3-none-any.whl", hash = "sha256:ba3d14c3ee7e41c6c654c46c9eb489d33213cdd30aa1696eab1374337c13f68f", size = 71376, upload-time = "2026-06-03T22:01:29.037Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
|
||||
Generated
+31
-1
@@ -37,6 +37,7 @@
|
||||
"@lit/reactive-element": "^2.1.2",
|
||||
"@lit/task": "^1.0.3",
|
||||
"@mdx-js/mdx": "^3.1.1",
|
||||
"@mermaid-js/layout-elk": "^0.2.1",
|
||||
"@mrmarble/djangoql-completion": "^0.8.3",
|
||||
"@open-wc/lit-helpers": "^0.7.0",
|
||||
"@openlayers-elements/core": "^0.4.0",
|
||||
@@ -2037,6 +2038,19 @@
|
||||
"react": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@mermaid-js/layout-elk": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@mermaid-js/layout-elk/-/layout-elk-0.2.1.tgz",
|
||||
"integrity": "sha512-MX9jwhMyd5zDcFsYcl3duDUkKhjVRUCGEQrdCeNV5hCIR6+3FuDDbRbFmvVbAu15K1+juzsYGG+K8MDvCY1Amg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"d3": "^7.9.0",
|
||||
"elkjs": "^0.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mermaid": "^11.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@mermaid-js/parser": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.1.tgz",
|
||||
@@ -9387,6 +9401,12 @@
|
||||
"integrity": "sha512-PwfIw7WQSt3xX7yOf5OE/unLzsK9CaN2f/FvV3WjPR1Knoc1T9vePRVV4W1EM301JzzysK51K7FNKcusCr0zYA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/elkjs": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz",
|
||||
"integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==",
|
||||
"license": "EPL-2.0"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
@@ -20916,7 +20936,7 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.9",
|
||||
"@goauthentik/tsconfig": "^2.0.0",
|
||||
"@types/node": "^25.7.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"semver": "^7.7.4",
|
||||
@@ -20927,6 +20947,16 @@
|
||||
"npm": ">=11.14.1"
|
||||
}
|
||||
},
|
||||
"packages/core/node_modules/@goauthentik/tsconfig": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-2.0.0.tgz",
|
||||
"integrity": "sha512-HiU/U9cO4Aaik3VjUHu/3PjD0m2nhIJXlENW1kbfVRFBaqAw//9UuHIel2E3vgwyua93fht36cBb8itZVsG1Vg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.14.1"
|
||||
}
|
||||
},
|
||||
"packages/core/node_modules/semver": {
|
||||
"version": "7.7.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
|
||||
|
||||
+13
-12
@@ -112,6 +112,7 @@
|
||||
"@lit/reactive-element": "^2.1.2",
|
||||
"@lit/task": "^1.0.3",
|
||||
"@mdx-js/mdx": "^3.1.1",
|
||||
"@mermaid-js/layout-elk": "^0.2.1",
|
||||
"@mrmarble/djangoql-completion": "^0.8.3",
|
||||
"@open-wc/lit-helpers": "^0.7.0",
|
||||
"@openlayers-elements/core": "^0.4.0",
|
||||
@@ -212,14 +213,10 @@
|
||||
],
|
||||
"wireit": {
|
||||
"build": {
|
||||
"#comment": [
|
||||
"`npm run build` and `npm run watch` are the most common ",
|
||||
"commands you should be using when working on the front end",
|
||||
"The files and output spec here expect you to use `npm run build --watch` ",
|
||||
"instead of `npm run watch`. The former is more comprehensive, but ",
|
||||
"the latter is faster."
|
||||
],
|
||||
"command": "${NODE_RUNNER} scripts/build-web.mjs",
|
||||
"dependencies": [
|
||||
"build-locales"
|
||||
],
|
||||
"files": [
|
||||
"src/**/*.{css,jpg,png,ts,js,json}",
|
||||
"!src/**/*.stories.ts",
|
||||
@@ -239,8 +236,12 @@
|
||||
"./dist/poly-*.js.map",
|
||||
"./dist/styles/**"
|
||||
],
|
||||
"dependencies": [
|
||||
"build-locales"
|
||||
"#comment": [
|
||||
"`npm run build` and `npm run watch` are the most common ",
|
||||
"commands you should be using when working on the front end",
|
||||
"The files and output spec here expect you to use `npm run build --watch` ",
|
||||
"instead of `npm run watch`. The former is more comprehensive, but ",
|
||||
"the latter is faster."
|
||||
],
|
||||
"env": {
|
||||
"NODE_RUNNER": {
|
||||
@@ -255,9 +256,6 @@
|
||||
"build-locales"
|
||||
]
|
||||
},
|
||||
"locales:repair": {
|
||||
"command": "prettier --write ./src/locale-codes.ts"
|
||||
},
|
||||
"lint:components": {
|
||||
"command": "lit-analyzer src"
|
||||
},
|
||||
@@ -270,6 +268,9 @@
|
||||
"lit-analyse": {
|
||||
"command": "lit-analyzer src"
|
||||
},
|
||||
"locales:repair": {
|
||||
"command": "prettier --write ./src/locale-codes.ts"
|
||||
},
|
||||
"precommit": {
|
||||
"command": "prettier --write .",
|
||||
"dependencies": [
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.9",
|
||||
"@goauthentik/tsconfig": "^2.0.0",
|
||||
"@types/node": "^25.7.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"semver": "^7.7.4",
|
||||
|
||||
@@ -2,28 +2,29 @@ import "#elements/EmptyState";
|
||||
|
||||
import { aki } from "#common/api/client";
|
||||
|
||||
import { Diagram } from "#elements/Diagram";
|
||||
import { Diagram } from "#elements/Diagram/ak-diagram";
|
||||
|
||||
import { FlowsApi } from "@goauthentik/api";
|
||||
|
||||
import { observes } from "@patternfly/pfe-core/decorators/observes.js";
|
||||
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
@customElement("ak-flow-diagram")
|
||||
export class FlowDiagram extends Diagram {
|
||||
@property()
|
||||
flowSlug?: string;
|
||||
@property({ type: String, useDefault: true })
|
||||
public flowSlug: string | null = null;
|
||||
|
||||
refreshHandler = (): void => {
|
||||
this.diagram = undefined;
|
||||
@observes("flowSlug")
|
||||
protected refresh(): void {
|
||||
aki(FlowsApi)
|
||||
.flowsInstancesDiagramRetrieve({
|
||||
slug: this.flowSlug || "",
|
||||
})
|
||||
.then((data) => {
|
||||
this.diagram = data.diagram;
|
||||
this.requestUpdate();
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Diagram } from "#elements/Diagram";
|
||||
import { Diagram } from "#elements/Diagram/ak-diagram";
|
||||
|
||||
import { UserMatchingModeToLabel } from "#admin/sources/oauth/utils";
|
||||
|
||||
@@ -9,22 +9,28 @@ import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
@customElement("ak-source-oauth-diagram")
|
||||
export class OAuthSourceDiagram extends Diagram {
|
||||
@property({ attribute: false })
|
||||
source?: OAuthSource;
|
||||
@property({ attribute: false, useDefault: true })
|
||||
public source: OAuthSource | null = null;
|
||||
|
||||
refreshHandler = (): void => {
|
||||
protected override syncDiagramContent = (): void => {
|
||||
if (!this.source) return;
|
||||
const graph = ["graph LR"];
|
||||
graph.push(`source[${msg(str`OAuth Source ${this.source.name}`)}]`);
|
||||
graph.push(
|
||||
`source --> flow_manager["${UserMatchingModeToLabel(this.source.userMatchingMode || UserMatchingModeEnum.Identifier)}"]`,
|
||||
);
|
||||
|
||||
const graph = [
|
||||
"graph LR",
|
||||
`source[${msg(str`OAuth Source ${this.source.name}`)}]`,
|
||||
`source --> flow_manager["${UserMatchingModeToLabel(
|
||||
this.source.userMatchingMode || UserMatchingModeEnum.Identifier,
|
||||
)}"]`,
|
||||
];
|
||||
|
||||
if (this.source.enrollmentFlow) {
|
||||
graph.push("flow_manager --> flow_enroll[Enrollment flow]");
|
||||
}
|
||||
|
||||
if (this.source.authenticationFlow) {
|
||||
graph.push("flow_manager --> flow_auth[Authentication flow]");
|
||||
}
|
||||
|
||||
this.diagram = graph.join("\n");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,9 +14,11 @@ import { SlottedTemplateResult } from "#elements/types";
|
||||
import { BaseStageForm } from "#admin/stages/BaseStageForm";
|
||||
import {
|
||||
CAPTCHA_PROVIDERS,
|
||||
CAPTCHA_REQUEST_CONTENT_TYPES,
|
||||
CaptchaProviderKey,
|
||||
CaptchaProviderKeys,
|
||||
CaptchaProviderPreset,
|
||||
deriveCapSiteVerifyURL,
|
||||
detectProviderFromInstance,
|
||||
pluckFormValues,
|
||||
} from "#admin/stages/captcha/shared";
|
||||
@@ -35,6 +37,10 @@ import { customElement, state } from "lit/decorators.js";
|
||||
import { guard } from "lit/directives/guard.js";
|
||||
import { ifDefined } from "lit/directives/if-defined.js";
|
||||
|
||||
type CaptchaStageFormRequest = (CaptchaStageRequest | PatchedCaptchaStageRequest) & {
|
||||
capEndpoint?: string;
|
||||
};
|
||||
|
||||
@customElement("ak-stage-captcha-form")
|
||||
export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
|
||||
public static override readonly styles = [...super.styles, Styles];
|
||||
@@ -83,6 +89,26 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
|
||||
public async send(
|
||||
data: CaptchaStageRequest | PatchedCaptchaStageRequest,
|
||||
): Promise<CaptchaStage> {
|
||||
const formData = data as CaptchaStageFormRequest;
|
||||
|
||||
if (this.selectedProvider === "cap" && (formData.capEndpoint || formData.publicKey)) {
|
||||
const capEndpoint = formData.capEndpoint || formData.publicKey || "";
|
||||
|
||||
formData.publicKey = capEndpoint;
|
||||
delete formData.capEndpoint;
|
||||
|
||||
const presetURL = CAPTCHA_PROVIDERS.cap.apiUrl;
|
||||
// The Cap verification URL includes the site key, so derive it from the
|
||||
// widget endpoint unless the advanced field was explicitly customized.
|
||||
if (!data.apiUrl || data.apiUrl === presetURL) {
|
||||
const siteVerifyURL = deriveCapSiteVerifyURL(capEndpoint);
|
||||
|
||||
if (siteVerifyURL) {
|
||||
data.apiUrl = siteVerifyURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.instance) {
|
||||
return this.#api.stagesCaptchaPartialUpdate({
|
||||
stageUuid: this.instance.pk || "",
|
||||
@@ -117,43 +143,77 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
|
||||
</p>
|
||||
|
||||
${guard([this.#currentPreset], () => {
|
||||
const { formatAPISource, keyURL } = this.#currentPreset;
|
||||
const { formatAPISource, formatDescription, keyURL } = this.#currentPreset;
|
||||
|
||||
if (!formatAPISource || !keyURL) {
|
||||
return null;
|
||||
}
|
||||
const description = formatDescription
|
||||
? html`<p class="pf-c-form__helper-text">${formatDescription()}</p>`
|
||||
: null;
|
||||
const providerLink =
|
||||
formatAPISource && keyURL
|
||||
? html`<ak-alert level=${Level.Info} icon="fa-key">
|
||||
${this.selectedProvider === "cap"
|
||||
? msg(
|
||||
html`Use the
|
||||
${html`<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href=${keyURL}
|
||||
>${formatAPISource()}</a
|
||||
>`}
|
||||
to self-host Cap and configure the endpoint.`,
|
||||
{
|
||||
id: "captcha.provider-link.cap",
|
||||
desc: "Supplementary help text with link to Cap documentation.",
|
||||
},
|
||||
)
|
||||
: msg(
|
||||
html`API keys can be obtained from the
|
||||
${html`<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href=${keyURL}
|
||||
>${formatAPISource()}</a
|
||||
>.`}`,
|
||||
{
|
||||
id: "captcha.provider-link",
|
||||
desc: "Supplementary help text with link to provider dashboard.",
|
||||
},
|
||||
)}
|
||||
</ak-alert>`
|
||||
: null;
|
||||
|
||||
return html`<ak-alert level=${Level.Info} icon="fa-key">
|
||||
${msg(
|
||||
html`API keys can be obtained from the
|
||||
${html`<a target="_blank" rel="noopener noreferrer" href=${keyURL}
|
||||
>${formatAPISource()}</a
|
||||
>.`}`,
|
||||
{
|
||||
id: "captcha.provider-link",
|
||||
desc: "Supplementary help text with link to provider dashboard.",
|
||||
},
|
||||
)}
|
||||
</ak-alert>`;
|
||||
return html`${description} ${providerLink}`;
|
||||
})}
|
||||
</ak-form-element-horizontal>`;
|
||||
}
|
||||
|
||||
protected renderKeyFields(): SlottedTemplateResult {
|
||||
const isCapProvider = this.selectedProvider === "cap";
|
||||
const publicKeyLabel = isCapProvider ? msg("Cap Endpoint") : msg("Public Key");
|
||||
const publicKeyPlaceholder = isCapProvider
|
||||
? msg("https://cap.example.com/site-key/")
|
||||
: msg("Paste your CAPTCHA public key...");
|
||||
const publicKeyHelp = isCapProvider
|
||||
? msg("The public site-key endpoint of your Cap server.", {
|
||||
id: "captcha.cap-endpoint.description",
|
||||
desc: "Description for Cap endpoint field.",
|
||||
})
|
||||
: msg("The public key is used by authentik to render the CAPTCHA widget.", {
|
||||
id: "captcha.public-key.description",
|
||||
desc: "Description for CAPTCHA public key field.",
|
||||
});
|
||||
|
||||
return html`
|
||||
<ak-text-input
|
||||
label=${msg("Public Key")}
|
||||
label=${publicKeyLabel}
|
||||
required
|
||||
name="publicKey"
|
||||
type="text"
|
||||
name=${isCapProvider ? "capEndpoint" : "publicKey"}
|
||||
type=${isCapProvider ? "url" : "text"}
|
||||
value="${ifDefined(this.instance?.publicKey || "")}"
|
||||
autocomplete="off"
|
||||
input-hint="code"
|
||||
placeholder=${msg("Paste your CAPTCHA public key...")}
|
||||
help=${msg("The public key is used by authentik to render the CAPTCHA widget.", {
|
||||
id: "captcha.public-key.description",
|
||||
desc: "Description for CAPTCHA public key field.",
|
||||
})}
|
||||
placeholder=${publicKeyPlaceholder}
|
||||
help=${publicKeyHelp}
|
||||
>
|
||||
</ak-text-input>
|
||||
|
||||
@@ -236,9 +296,13 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
|
||||
type="url"
|
||||
value="${ifDefined(formValues.jsUrl)}"
|
||||
required
|
||||
help=${msg(
|
||||
"URL to fetch the CAPTCHA JavaScript library from. Automatically set based on provider selection but can be customized.",
|
||||
)}
|
||||
help=${this.selectedProvider === "cap"
|
||||
? msg(
|
||||
"For Cap, prefer the self-hosted widget asset, for example https://cap.example.com/assets/widget.js. If using a CDN, pin a reviewed release.",
|
||||
)
|
||||
: msg(
|
||||
"URL to fetch the CAPTCHA JavaScript library from. Automatically set based on provider selection but can be customized.",
|
||||
)}
|
||||
></ak-text-input>
|
||||
<ak-text-input
|
||||
label=${msg("API Verification URL")}
|
||||
@@ -246,10 +310,35 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
|
||||
type="url"
|
||||
value="${ifDefined(formValues.apiUrl)}"
|
||||
required
|
||||
help=${msg(
|
||||
"URL used to validate CAPTCHA response on the backend. Automatically set based on provider selection but can be customized.",
|
||||
)}
|
||||
help=${this.selectedProvider === "cap"
|
||||
? msg(
|
||||
"Cap's server-side verification endpoint, for example https://cap.example.com/site-key/siteverify.",
|
||||
)
|
||||
: msg(
|
||||
"URL used to validate CAPTCHA response on the backend. Automatically set based on provider selection but can be customized.",
|
||||
)}
|
||||
></ak-text-input>
|
||||
<ak-form-element-horizontal
|
||||
label=${msg("Request Content Type")}
|
||||
name="requestContentType"
|
||||
>
|
||||
<select class="pf-c-form-control" name="requestContentType">
|
||||
${CAPTCHA_REQUEST_CONTENT_TYPES.map(
|
||||
(type) =>
|
||||
html`<option
|
||||
value=${type.value}
|
||||
?selected=${type.value === formValues.requestContentType}
|
||||
>
|
||||
${type.formatDisplayName()}
|
||||
</option>`,
|
||||
)}
|
||||
</select>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"Content-Type used for server-side verification. Cap requires JSON; most other providers use form-encoded requests.",
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>`;
|
||||
}
|
||||
|
||||
@@ -2,12 +2,35 @@ import { CaptchaStage, CaptchaStageRequest } from "@goauthentik/api";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
|
||||
export type CaptchaRequestContentType = "application/x-www-form-urlencoded" | "application/json";
|
||||
|
||||
export const CAPTCHA_REQUEST_CONTENT_TYPES = [
|
||||
{
|
||||
value: "application/x-www-form-urlencoded",
|
||||
formatDisplayName: () =>
|
||||
msg("Form encoded", {
|
||||
id: "captcha.request-content-type.form",
|
||||
}),
|
||||
},
|
||||
{
|
||||
value: "application/json",
|
||||
formatDisplayName: () =>
|
||||
msg("JSON", {
|
||||
id: "captcha.request-content-type.json",
|
||||
}),
|
||||
},
|
||||
] as const satisfies {
|
||||
value: CaptchaRequestContentType;
|
||||
formatDisplayName: () => string;
|
||||
}[];
|
||||
|
||||
export const CaptchaProviderKeys = [
|
||||
"recaptcha_v2",
|
||||
"recaptcha_v3",
|
||||
"recaptcha_enterprise",
|
||||
"hcaptcha",
|
||||
"turnstile",
|
||||
"cap",
|
||||
"custom",
|
||||
] as const satisfies string[];
|
||||
|
||||
@@ -15,8 +38,10 @@ export type CaptchaProviderKey = (typeof CaptchaProviderKeys)[number];
|
||||
|
||||
export interface CaptchaProviderPreset {
|
||||
formatDisplayName: () => string;
|
||||
formatDescription?: () => string;
|
||||
jsUrl: string;
|
||||
apiUrl: string;
|
||||
requestContentType: CaptchaRequestContentType;
|
||||
interactive: boolean;
|
||||
supportsScore: boolean;
|
||||
score?: { min: number; max: number };
|
||||
@@ -37,6 +62,7 @@ export const CAPTCHA_PROVIDERS = {
|
||||
}),
|
||||
jsUrl: "https://www.recaptcha.net/recaptcha/api.js",
|
||||
apiUrl: "https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
requestContentType: "application/x-www-form-urlencoded",
|
||||
interactive: true,
|
||||
supportsScore: false,
|
||||
formatAPISource: () =>
|
||||
@@ -52,6 +78,7 @@ export const CAPTCHA_PROVIDERS = {
|
||||
}),
|
||||
jsUrl: "https://www.recaptcha.net/recaptcha/api.js",
|
||||
apiUrl: "https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
requestContentType: "application/x-www-form-urlencoded",
|
||||
interactive: false,
|
||||
supportsScore: true,
|
||||
score: { min: 0.5, max: 1.0 },
|
||||
@@ -68,6 +95,7 @@ export const CAPTCHA_PROVIDERS = {
|
||||
}),
|
||||
jsUrl: "https://www.recaptcha.net/recaptcha/enterprise.js",
|
||||
apiUrl: "https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
requestContentType: "application/x-www-form-urlencoded",
|
||||
interactive: false,
|
||||
supportsScore: true,
|
||||
score: { min: 0.5, max: 1.0 },
|
||||
@@ -84,6 +112,7 @@ export const CAPTCHA_PROVIDERS = {
|
||||
}),
|
||||
jsUrl: "https://js.hcaptcha.com/1/api.js",
|
||||
apiUrl: "https://api.hcaptcha.com/siteverify",
|
||||
requestContentType: "application/x-www-form-urlencoded",
|
||||
interactive: true,
|
||||
supportsScore: true,
|
||||
score: { min: 0.0, max: 0.5 },
|
||||
@@ -100,6 +129,7 @@ export const CAPTCHA_PROVIDERS = {
|
||||
}),
|
||||
jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js",
|
||||
apiUrl: "https://challenges.cloudflare.com/turnstile/v0/siteverify",
|
||||
requestContentType: "application/x-www-form-urlencoded",
|
||||
interactive: true,
|
||||
supportsScore: false,
|
||||
formatAPISource: () =>
|
||||
@@ -108,6 +138,26 @@ export const CAPTCHA_PROVIDERS = {
|
||||
}),
|
||||
keyURL: "https://dash.cloudflare.com",
|
||||
},
|
||||
cap: {
|
||||
formatDisplayName: () =>
|
||||
msg("Cap", {
|
||||
id: "captcha.providers.cap",
|
||||
}),
|
||||
formatDescription: () =>
|
||||
msg("Cap is a self-hostable CAPTCHA server that uses proof-of-work challenges.", {
|
||||
id: "captcha.providers.cap.description",
|
||||
}),
|
||||
jsUrl: "https://cap.example.com/assets/widget.js",
|
||||
apiUrl: "https://cap.example.com/site-key/siteverify",
|
||||
requestContentType: "application/json",
|
||||
interactive: true,
|
||||
supportsScore: false,
|
||||
formatAPISource: () =>
|
||||
msg("Cap documentation", {
|
||||
id: "captcha.providers.cap.setup-guide",
|
||||
}),
|
||||
keyURL: "https://trycap.dev/guide/",
|
||||
},
|
||||
custom: {
|
||||
formatDisplayName: () =>
|
||||
msg("Custom", {
|
||||
@@ -115,23 +165,56 @@ export const CAPTCHA_PROVIDERS = {
|
||||
}),
|
||||
jsUrl: "https://www.recaptcha.net/recaptcha/api.js",
|
||||
apiUrl: "https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
requestContentType: "application/x-www-form-urlencoded",
|
||||
interactive: false,
|
||||
supportsScore: true,
|
||||
score: { min: 0.5, max: 1.0 },
|
||||
},
|
||||
} as const satisfies Record<CaptchaProviderKey, CaptchaProviderPreset>;
|
||||
|
||||
export function deriveCapSiteVerifyURL(endpoint: string): string | null {
|
||||
const trimmedEndpoint = endpoint.trim();
|
||||
|
||||
if (!URL.canParse(trimmedEndpoint)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const endpointURL = new URL(trimmedEndpoint);
|
||||
const normalizedEndpoint = endpointURL.href.endsWith("/")
|
||||
? endpointURL.href
|
||||
: `${endpointURL.href}/`;
|
||||
|
||||
return new URL("siteverify", normalizedEndpoint).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect which provider preset matches the given {@linkcode CaptchaStage} instance.
|
||||
* This allows the form to show the correct provider in the dropdown when editing
|
||||
* an existing CAPTCHA stage. Falls back to "custom" if no match is found.
|
||||
*/
|
||||
function isCapWidgetURL(jsUrl?: string | null): boolean {
|
||||
if (!jsUrl || !URL.canParse(jsUrl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { pathname } = new URL(jsUrl);
|
||||
return pathname.includes("cap-widget") || pathname.endsWith("/assets/widget.js");
|
||||
}
|
||||
|
||||
export function detectProviderFromInstance(stage?: CaptchaStage | null): CaptchaProviderKey {
|
||||
if (!stage) return "custom";
|
||||
|
||||
for (const key of CaptchaProviderKeys) {
|
||||
const preset = CAPTCHA_PROVIDERS[key];
|
||||
|
||||
if (
|
||||
key === "cap" &&
|
||||
isCapWidgetURL(stage.jsUrl) &&
|
||||
stage.requestContentType === preset.requestContentType
|
||||
) {
|
||||
return key;
|
||||
}
|
||||
|
||||
if (stage.jsUrl === preset.jsUrl && stage.apiUrl === preset.apiUrl) {
|
||||
return key;
|
||||
}
|
||||
@@ -153,6 +236,7 @@ export function pluckFormValues(
|
||||
return {
|
||||
jsUrl: instance.jsUrl,
|
||||
apiUrl: instance.apiUrl,
|
||||
requestContentType: instance.requestContentType,
|
||||
interactive: instance.interactive,
|
||||
scoreMinThreshold: instance.scoreMinThreshold,
|
||||
scoreMaxThreshold: instance.scoreMaxThreshold,
|
||||
@@ -163,6 +247,7 @@ export function pluckFormValues(
|
||||
return {
|
||||
jsUrl: preset.jsUrl,
|
||||
apiUrl: preset.apiUrl,
|
||||
requestContentType: preset.requestContentType,
|
||||
interactive: preset.interactive,
|
||||
scoreMinThreshold: preset.score?.min ?? 0.5,
|
||||
scoreMaxThreshold: preset.score?.max ?? 1.0,
|
||||
|
||||
@@ -261,26 +261,29 @@ declare global {
|
||||
* @param hint The color scheme hint to use.
|
||||
* @param doc The document to apply the theme to.
|
||||
*/
|
||||
export const applyDocumentTheme = ((currentUITheme = resolveUITheme(), doc = document): void => {
|
||||
export const applyDocumentTheme = ((
|
||||
currentUITheme = resolveUITheme(),
|
||||
ownerDocument = document,
|
||||
): void => {
|
||||
console.debug(`authentik/theme (document): want to switch to ${currentUITheme} theme`);
|
||||
|
||||
const { themeChoice } = doc.documentElement.dataset;
|
||||
const { themeChoice } = ownerDocument.documentElement.dataset;
|
||||
|
||||
if (themeChoice && themeChoice !== "auto") {
|
||||
console.debug(
|
||||
`authentik/theme (document): skipping theme application due to explicit choice (${themeChoice})`,
|
||||
);
|
||||
|
||||
doc.dispatchEvent(new ThemeChangeEvent(themeChoice));
|
||||
ownerDocument.dispatchEvent(new ThemeChangeEvent(themeChoice));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
doc.documentElement.dataset.theme = currentUITheme;
|
||||
ownerDocument.documentElement.dataset.theme = currentUITheme;
|
||||
|
||||
console.debug(`authentik/theme (document): switching to ${currentUITheme} theme`);
|
||||
|
||||
doc.dispatchEvent(new ThemeChangeEvent(currentUITheme));
|
||||
ownerDocument.dispatchEvent(new ThemeChangeEvent(currentUITheme));
|
||||
}) satisfies UIThemeListener;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
import "#elements/EmptyState";
|
||||
|
||||
import { EVENT_REFRESH } from "#common/constants";
|
||||
import { DOM_PURIFY_STRICT } from "#common/purify";
|
||||
import { ThemeChangeEvent } from "#common/theme";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
|
||||
import { UiThemeEnum } from "@goauthentik/api";
|
||||
|
||||
import mermaid, { MermaidConfig } from "mermaid";
|
||||
|
||||
import { css, CSSResult, html, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
import { until } from "lit/directives/until.js";
|
||||
|
||||
@customElement("ak-diagram")
|
||||
export class Diagram extends AKElement {
|
||||
@property({ attribute: false })
|
||||
diagram?: string;
|
||||
|
||||
refreshHandler = (): void => {
|
||||
if (!this.textContent) return;
|
||||
this.diagram = this.textContent;
|
||||
};
|
||||
|
||||
handlerBound = false;
|
||||
|
||||
static styles: CSSResult[] = [
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
config: MermaidConfig;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.config = {
|
||||
// The type definition for this says number
|
||||
// but the example use strings
|
||||
// and numbers don't work
|
||||
logLevel: "fatal",
|
||||
startOnLoad: false,
|
||||
flowchart: {
|
||||
curve: "linear",
|
||||
},
|
||||
htmlLabels: false,
|
||||
securityLevel: "strict",
|
||||
dompurifyConfig: DOM_PURIFY_STRICT,
|
||||
};
|
||||
mermaid.initialize(this.config);
|
||||
}
|
||||
|
||||
firstUpdated(): void {
|
||||
if (this.handlerBound) return;
|
||||
window.addEventListener(EVENT_REFRESH, this.refreshHandler);
|
||||
this.addEventListener(ThemeChangeEvent.eventName, ((ev: CustomEvent<UiThemeEnum>) => {
|
||||
if (ev.detail === UiThemeEnum.Dark) {
|
||||
this.config.theme = "dark";
|
||||
} else {
|
||||
this.config.theme = "default";
|
||||
}
|
||||
mermaid.initialize(this.config);
|
||||
}) as EventListener);
|
||||
this.handlerBound = true;
|
||||
this.refreshHandler();
|
||||
}
|
||||
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
window.removeEventListener(EVENT_REFRESH, this.refreshHandler);
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
this.querySelectorAll("*").forEach((el) => {
|
||||
try {
|
||||
el.remove();
|
||||
} catch {
|
||||
console.debug(`authentik/diagram: failed to remove element ${el}`);
|
||||
}
|
||||
});
|
||||
if (!this.diagram) {
|
||||
return html`<ak-empty-state loading></ak-empty-state>`;
|
||||
}
|
||||
return html`${until(
|
||||
mermaid.render("graph", this.diagram).then((r) => {
|
||||
r.bindFunctions?.(this.shadowRoot as unknown as Element);
|
||||
return unsafeHTML(r.svg);
|
||||
}),
|
||||
)}`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-diagram": Diagram;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
:host {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import "#elements/EmptyState";
|
||||
|
||||
import { AKRefreshEvent } from "#common/events";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { listen } from "#elements/decorators/listen";
|
||||
import Styles from "#elements/Diagram/ak-diagram.css";
|
||||
import { EmptyState } from "#elements/EmptyState";
|
||||
import MermaidStyles from "#elements/mermaid/mermaid.css";
|
||||
import { loadMermaid } from "#elements/mermaid/utils";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
|
||||
import { CSSResult, PropertyValues } from "lit";
|
||||
import { guard } from "lit-html/directives/guard.js";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
import { until } from "lit/directives/until.js";
|
||||
|
||||
@customElement("ak-diagram")
|
||||
export class Diagram extends AKElement {
|
||||
static styles: CSSResult[] = [MermaidStyles, Styles];
|
||||
|
||||
#diagram = "";
|
||||
@property({ attribute: false, useDefault: true })
|
||||
public get diagram(): string {
|
||||
return this.#diagram || this.textContent.trim() || "";
|
||||
}
|
||||
|
||||
public set diagram(value: string) {
|
||||
const previous = this.#diagram;
|
||||
this.#diagram = value.trim();
|
||||
|
||||
this.requestUpdate("diagram", previous);
|
||||
}
|
||||
|
||||
@listen(AKRefreshEvent, {
|
||||
target: window,
|
||||
})
|
||||
protected syncDiagramContent = (): void => {
|
||||
if (!this.textContent) return;
|
||||
this.diagram = this.textContent;
|
||||
};
|
||||
|
||||
loadingPlaceholder: EmptyState;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.loadingPlaceholder = new EmptyState();
|
||||
this.loadingPlaceholder.loading = true;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues<this>): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
this.syncDiagramContent();
|
||||
}
|
||||
|
||||
protected renderMermaid(): Promise<SlottedTemplateResult> {
|
||||
return loadMermaid(this.activeTheme).then((mermaid) => {
|
||||
if (!this.diagram) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mermaid.render(`mermaid-svg-${this.localName}`, this.diagram).then((result) => {
|
||||
result.bindFunctions?.(this.renderRoot as HTMLElement);
|
||||
|
||||
return unsafeHTML(result.svg);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected override render(): SlottedTemplateResult {
|
||||
const { diagram, loadingPlaceholder, activeTheme } = this;
|
||||
|
||||
return guard([diagram, activeTheme], () => {
|
||||
if (!diagram) {
|
||||
return loadingPlaceholder;
|
||||
}
|
||||
|
||||
return until(this.renderMermaid(), loadingPlaceholder);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-diagram": Diagram;
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,12 @@ import { remarkHeadings } from "#elements/ak-mdx/remark/remark-headings";
|
||||
import { remarkLists } from "#elements/ak-mdx/remark/remark-lists";
|
||||
import Styles from "#elements/ak-mdx/styles.css";
|
||||
import { AKElement } from "#elements/Base";
|
||||
import MermaidStyles from "#elements/mermaid/mermaid.css";
|
||||
import { loadMermaid } from "#elements/mermaid/utils";
|
||||
|
||||
import { DistDirectoryName, StaticDirectoryName } from "#paths";
|
||||
import OneDark from "#styles/atom/one-dark.css";
|
||||
|
||||
import { UiThemeEnum } from "@goauthentik/api";
|
||||
|
||||
import { compile as compileMDX, run as runMDX } from "@mdx-js/mdx";
|
||||
import apacheGrammar from "highlight.js/lib/languages/apache";
|
||||
import diffGrammar from "highlight.js/lib/languages/diff";
|
||||
@@ -77,6 +77,7 @@ export class AKMDX extends AKElement {
|
||||
PFTable,
|
||||
PFContent,
|
||||
OneDark,
|
||||
MermaidStyles,
|
||||
Styles,
|
||||
];
|
||||
|
||||
@@ -113,6 +114,8 @@ export class AKMDX extends AKElement {
|
||||
mdxModule.content,
|
||||
);
|
||||
|
||||
const { activeTheme } = this;
|
||||
|
||||
const mdx = await compileMDX(normalized, {
|
||||
outputFormat: "function-body",
|
||||
remarkPlugins: [
|
||||
@@ -132,7 +135,8 @@ export class AKMDX extends AKElement {
|
||||
rehypeMermaid,
|
||||
{
|
||||
prefix: "mermaid-svg-",
|
||||
colorScheme: this.activeTheme === UiThemeEnum.Dark ? "dark" : "light",
|
||||
colorScheme: activeTheme,
|
||||
mermaidConfig: await loadMermaid(activeTheme),
|
||||
} satisfies RehypeMermaidOptions,
|
||||
],
|
||||
],
|
||||
|
||||
@@ -59,21 +59,6 @@ pre:has(.hljs) {
|
||||
padding: var(--pf-global--spacer--md);
|
||||
}
|
||||
|
||||
svg[id^="mermaid-svg-"] {
|
||||
.rect {
|
||||
fill: var(
|
||||
--ak-mermaid-box-background-color,
|
||||
var(--pf-global--BackgroundColor--light-300)
|
||||
) !important;
|
||||
}
|
||||
|
||||
.messageText {
|
||||
stroke-width: 4;
|
||||
fill: var(--ak-mermaid-message-text) !important;
|
||||
paint-order: stroke;
|
||||
}
|
||||
}
|
||||
|
||||
ak-alert + :is(h2, p) {
|
||||
padding-top: var(--pf-global--spacer--md);
|
||||
}
|
||||
@@ -81,19 +66,7 @@ ak-alert + :is(h2, p) {
|
||||
/* #region Dark Theme */
|
||||
|
||||
:host([theme="dark"]) {
|
||||
--ak-mermaid-message-text: var(--ak-dark-foreground);
|
||||
--ak-mermaid-box-background-color: var(--ak-dark-background-lighter);
|
||||
--ak-table-stripe-background: var(--pf-global--BackgroundColor--dark-200);
|
||||
|
||||
svg[id^="mermaid-svg-"] {
|
||||
line[class^="messageLine"] {
|
||||
/*
|
||||
Mermaid's support for dynamic palette changes leaves a lot to be desired.
|
||||
This is a workaround to keep content readable while not breaking the rest of the theme.
|
||||
*/
|
||||
filter: invert(1) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* svg[id^="mermaid-svg-"] { */
|
||||
/* &.flowchart {
|
||||
.edgeLabel .label {
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
color: var(--ak-foreground, #fff);
|
||||
}
|
||||
} */
|
||||
|
||||
.flowchart {
|
||||
foreignObject:has(.edgeLabel) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.edgeLabel,
|
||||
.edgeLabel .labelBkg {
|
||||
background-color: transparent;
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.edgeLabel > span,
|
||||
.labelBkg > span.edgeLabel {
|
||||
margin-inline: auto;
|
||||
max-width: max-content;
|
||||
padding: 3px 12px;
|
||||
border-radius: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.edgeLabel {
|
||||
background-color: var(--pf-global--palette--gold-200) !important;
|
||||
border: 1px solid var(--pf-global--palette--gold-500) !important;
|
||||
}
|
||||
}
|
||||
|
||||
svg[id^="mermaid-svg-"] {
|
||||
& > .rect {
|
||||
fill: color-mix(var(--pf-global--palette--gold-100), transparent 95%);
|
||||
stroke: var(--pf-global--palette--gold-100);
|
||||
stroke-width: 1;
|
||||
}
|
||||
|
||||
.messageText {
|
||||
fill: var(--pf-global--Color--100) !important;
|
||||
}
|
||||
|
||||
.messageLine0 {
|
||||
stroke: var(--pf-global--palette--purple-300) !important;
|
||||
}
|
||||
|
||||
[id$="-arrowhead"] path {
|
||||
fill: var(--pf-global--palette--purple-300) !important;
|
||||
stroke: var(--pf-global--palette--purple-300) !important;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
import type { MermaidConfig } from "mermaid";
|
||||
|
||||
/**
|
||||
* Resolves PatternFly CSS custom properties into concrete hex colors and maps
|
||||
* them onto Mermaid's `themeVariables` keyset.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Colors are parsed through a 1x1 canvas so that any valid CSS color form
|
||||
* (named, rgb/rgba, hsl, or a `var()` chain) collapses to a hex string Mermaid
|
||||
* can consume. Fully transparent values resolve to `"transparent"`.
|
||||
*
|
||||
* PatternFly 4 handles light/dark theming at the token level, so a single token
|
||||
* set resolves correctly under either theme — no per-theme branching needed.
|
||||
*/
|
||||
export class MermaidThemeAdapter {
|
||||
canvas = new OffscreenCanvas(1, 1);
|
||||
ctx = this.canvas.getContext("2d");
|
||||
|
||||
constructor(protected computedStyle: CSSStyleDeclaration) {}
|
||||
|
||||
/**
|
||||
* Resolve a CSS custom property to a hex color string.
|
||||
*
|
||||
* @param cssProperty The CSS custom property name to read.
|
||||
* @param fallback Color used when the property is unset or empty.
|
||||
*
|
||||
* @returns A hex color code string, or `"transparent"` for fully transparent values.
|
||||
*/
|
||||
public readHexColorVariable = (cssProperty: string, fallback = "#ff0000"): string => {
|
||||
if (!this.ctx) {
|
||||
throw new Error("Could not create canvas context for color parsing");
|
||||
}
|
||||
|
||||
this.ctx.clearRect(0, 0, 1, 1);
|
||||
this.ctx.fillStyle = this.computedStyle.getPropertyValue(cssProperty).trim() || fallback;
|
||||
this.ctx.fillRect(0, 0, 1, 1);
|
||||
|
||||
const [r, g, b, a] = this.ctx.getImageData(0, 0, 1, 1).data;
|
||||
|
||||
if (a === 0) {
|
||||
return "transparent";
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-bitwise
|
||||
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a surface color, substituting an opaque fallback when the token
|
||||
* resolves to `transparent`. Node fills must never be see-through.
|
||||
*/
|
||||
protected readSurface = (cssProperty: string, fallback: string): string => {
|
||||
const value = this.readHexColorVariable(cssProperty, fallback);
|
||||
|
||||
return value === "transparent" ? fallback : value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Map PatternFly tokens onto Mermaid's `themeVariables`.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Requires `theme: "base"` in the Mermaid config — other built-in themes
|
||||
* ignore most of these overrides.
|
||||
*/
|
||||
public toThemeVariables(darkMode?: boolean): MermaidConfig["themeVariables"] {
|
||||
const { readHexColorVariable: read, readSurface } = this;
|
||||
|
||||
const surface = readSurface("--pf-global--palette--purple-50", "#ffffff");
|
||||
const surfaceAlt = readSurface("--pf-global--palette--blue-50", surface);
|
||||
const surfaceDark = readSurface("--pf-global--palette--black-200", surfaceAlt);
|
||||
|
||||
const textBase = read("--pf-global--palette--purple-700");
|
||||
const textSecondary = read(
|
||||
darkMode ? "--pf-global--palette--gold-100" : "--pf-global--palette--gold-400",
|
||||
);
|
||||
const border = read(
|
||||
darkMode ? "--pf-global--palette--purple-300" : "--pf-global--palette--purple-700",
|
||||
);
|
||||
|
||||
const primaryBorder = read("--pf-global--palette--purple-400");
|
||||
const primaryAccent = read("--pf-global--palette--purple-100");
|
||||
const primaryAccentText = read("--pf-global--palette--purple-700");
|
||||
|
||||
const success = read("--pf-global--success-color--100");
|
||||
const danger = read("--pf-global--danger-color--100");
|
||||
const warning = read("--pf-global--warning-color--100");
|
||||
const info = read("--pf-global--info-color--100");
|
||||
|
||||
return {
|
||||
// Base / canvas
|
||||
background: surface,
|
||||
mainBkg: surface,
|
||||
fontFamily: "var(--ak-font-family-sans-serif)",
|
||||
|
||||
// Primary node
|
||||
primaryColor: surface,
|
||||
primaryBorderColor: primaryBorder,
|
||||
primaryTextColor: textBase,
|
||||
|
||||
// Secondary node
|
||||
secondaryColor: surfaceAlt,
|
||||
secondaryBorderColor: border,
|
||||
secondaryTextColor: textBase,
|
||||
|
||||
// Tertiary node
|
||||
tertiaryColor: surfaceDark,
|
||||
tertiaryBorderColor: border,
|
||||
tertiaryTextColor: textBase,
|
||||
|
||||
// Edges / lines / labels
|
||||
lineColor: textSecondary,
|
||||
edgeLabelBackground: surface,
|
||||
titleColor: textBase,
|
||||
|
||||
// Generic node fallbacks
|
||||
nodeBorder: border,
|
||||
nodeTextColor: textBase,
|
||||
|
||||
// Clusters / subgraphs
|
||||
clusterBkg: surfaceDark,
|
||||
clusterBorder: border,
|
||||
|
||||
// Notes
|
||||
noteBkgColor: warning,
|
||||
noteTextColor: textBase,
|
||||
noteBorderColor: border,
|
||||
|
||||
// Brand accents (classDef / linkStyle)
|
||||
primaryColorAccent: primaryAccent,
|
||||
primaryTextColorAccent: primaryAccentText,
|
||||
|
||||
// Status (state / git / quadrant diagrams)
|
||||
successColor: success,
|
||||
errorColor: danger,
|
||||
warningColor: warning,
|
||||
infoColor: info,
|
||||
|
||||
// Sequence / state actors
|
||||
actorBkg: surface,
|
||||
actorBorder: border,
|
||||
actorTextColor: textBase,
|
||||
labelBoxBkgColor: surface,
|
||||
labelTextColor: textBase,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Semantic accent colors for emitting `linkStyle` / `classDef` directives
|
||||
* into diagram source (e.g. coloring policy pass/fail edges).
|
||||
*/
|
||||
public toAccents() {
|
||||
const { readHexColorVariable: read } = this;
|
||||
|
||||
return {
|
||||
success: read("--pf-global--success-color--100"),
|
||||
danger: read("--pf-global--danger-color--100"),
|
||||
warning: read("--pf-global--warning-color--100"),
|
||||
info: read("--pf-global--info-color--100"),
|
||||
primary: read("--pf-global--palette--purple-100"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import MermaidStyles from "./mermaid.css";
|
||||
|
||||
import { DOM_PURIFY_STRICT } from "#common/purify";
|
||||
import { ResolvedUITheme } from "#common/theme";
|
||||
|
||||
import { MermaidThemeAdapter } from "#elements/mermaid/theme";
|
||||
|
||||
import elkLayouts from "@mermaid-js/layout-elk";
|
||||
import type { Mermaid, MermaidConfig } from "mermaid";
|
||||
|
||||
export const DefaultMermaidConfig: Readonly<MermaidConfig> = {
|
||||
logLevel: "fatal",
|
||||
startOnLoad: false,
|
||||
htmlLabels: true,
|
||||
fontFamily: "var(--ak-font-family-sans-serif)",
|
||||
layout: "elk",
|
||||
flowchart: {
|
||||
curve: "linear",
|
||||
|
||||
nodeSpacing: 25,
|
||||
rankSpacing: 25,
|
||||
wrappingWidth: 500,
|
||||
},
|
||||
theme: "base",
|
||||
securityLevel: "strict",
|
||||
dompurifyConfig: DOM_PURIFY_STRICT,
|
||||
};
|
||||
|
||||
let lastActiveTheme: ResolvedUITheme | null = null;
|
||||
let mermaid: Mermaid | null = null;
|
||||
|
||||
/**
|
||||
* Load the Mermaid library and initialize it with the appropriate theme based
|
||||
* on the provided UI theme.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* Mermaid is only loaded once and cached for subsequent calls. Note that
|
||||
* Mermaid is a singleton and does not support multiple instances with different
|
||||
* configurations. Re-initialization occurs only when the active theme changes.
|
||||
*
|
||||
* @param uiTheme The resolved UI theme to derive Mermaid colors from.
|
||||
* @returns The initialized Mermaid singleton.
|
||||
*/
|
||||
export async function loadMermaid(uiTheme: ResolvedUITheme): Promise<Mermaid> {
|
||||
if (!mermaid) {
|
||||
const mermaidModule = await import("mermaid");
|
||||
mermaid = mermaidModule.default;
|
||||
mermaid.registerLayoutLoaders(elkLayouts);
|
||||
}
|
||||
|
||||
if (uiTheme && uiTheme === lastActiveTheme) {
|
||||
return mermaid;
|
||||
}
|
||||
|
||||
await new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
|
||||
const computedStyle = getComputedStyle(document.documentElement);
|
||||
const darkMode = uiTheme === "dark";
|
||||
|
||||
const themeAdapter = new MermaidThemeAdapter(computedStyle);
|
||||
const themeVariables = themeAdapter.toThemeVariables(darkMode);
|
||||
|
||||
mermaid.initialize({
|
||||
...DefaultMermaidConfig,
|
||||
themeVariables: {
|
||||
...themeVariables,
|
||||
},
|
||||
darkMode,
|
||||
themeCSS: String(MermaidStyles),
|
||||
});
|
||||
|
||||
lastActiveTheme = uiTheme;
|
||||
|
||||
return mermaid;
|
||||
}
|
||||
@@ -36,4 +36,9 @@ ak-stage-captcha[theme="dark"].style-scope {
|
||||
background-color: var(--captcha-background-from);
|
||||
animation: captcha-background-animation 1s infinite var(--pf-global--TimingFunction);
|
||||
}
|
||||
|
||||
&[data-transparent-loading="true"][data-ready="loading"] {
|
||||
background-color: transparent;
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { AKFormErrors, ErrorProp } from "#components/ak-field-errors";
|
||||
import { FlowUserDetails } from "#flow/FormStatic";
|
||||
import { BaseStage } from "#flow/stages/base";
|
||||
import Styles from "#flow/stages/captcha/CaptchaStage.css";
|
||||
import { CapController, isCapWidgetURL } from "#flow/stages/captcha/controllers/cap";
|
||||
import {
|
||||
CaptchaController,
|
||||
CaptchaControllerConstructor,
|
||||
@@ -53,7 +54,14 @@ interface LoadMessage {
|
||||
message: "load";
|
||||
}
|
||||
|
||||
type IframeMessageEvent = MessageEvent<CaptchaMessage | LoadMessage>;
|
||||
interface ErrorMessage {
|
||||
source?: string;
|
||||
context?: string;
|
||||
message: "error";
|
||||
error: string;
|
||||
}
|
||||
|
||||
type IframeMessageEvent = MessageEvent<CaptchaMessage | LoadMessage | ErrorMessage>;
|
||||
|
||||
@customElement("ak-stage-captcha")
|
||||
export class CaptchaStage
|
||||
@@ -79,6 +87,7 @@ export class CaptchaStage
|
||||
HCaptchaController,
|
||||
GReCaptchaController,
|
||||
TurnstileController,
|
||||
CapController,
|
||||
]);
|
||||
|
||||
#logger = ConsoleLogger.prefix("flow:captcha");
|
||||
@@ -165,6 +174,9 @@ export class CaptchaStage
|
||||
return match(data)
|
||||
.with({ message: "captcha" }, ({ token }) => this.onTokenChange(token))
|
||||
.with({ message: "load" }, this.#loadListener)
|
||||
.with({ message: "error" }, ({ error }) => {
|
||||
this.error = error;
|
||||
})
|
||||
.otherwise(({ message }) => {
|
||||
this.#logger.debug(`Unknown message: ${message}`);
|
||||
});
|
||||
@@ -183,12 +195,18 @@ export class CaptchaStage
|
||||
}
|
||||
|
||||
if (this.challenge?.interactive) {
|
||||
// Cap renders its own framed widget, so the generic iframe loading shimmer looks like
|
||||
// an extra CAPTCHA box flashing behind it.
|
||||
const isCapChallenge =
|
||||
URL.canParse(this.challenge.jsUrl) && isCapWidgetURL(new URL(this.challenge.jsUrl));
|
||||
|
||||
return html`
|
||||
<iframe
|
||||
aria-label=${msg("CAPTCHA challenge")}
|
||||
${ref(this.iframeRef)}
|
||||
style="height: ${this.iframeHeight}px;"
|
||||
data-ready=${this.#iframeLoaded ? "ready" : "loading"}
|
||||
data-transparent-loading=${isCapChallenge ? "true" : "false"}
|
||||
class="ak-interactive-challenge"
|
||||
id="ak-captcha"
|
||||
></iframe>
|
||||
@@ -306,8 +324,13 @@ export class CaptchaStage
|
||||
|
||||
// Then, load the new script...
|
||||
const scriptElement = document.createElement("script");
|
||||
const matchedController = Array.from(CaptchaStage.controllers).find((Controller) =>
|
||||
Controller.matchesURL(challengeURL),
|
||||
);
|
||||
|
||||
scriptElement.src = challengeURL.toString();
|
||||
scriptElement.type =
|
||||
matchedController?.scriptType === "module" ? "module" : "text/javascript";
|
||||
scriptElement.async = true;
|
||||
scriptElement.defer = true;
|
||||
scriptElement.onload = this.#scriptLoadListener;
|
||||
@@ -528,6 +551,7 @@ export class CaptchaStage
|
||||
challengeURL: challengeURL.toString(),
|
||||
theme: this.activeTheme,
|
||||
scriptOnLoad: !(controller instanceof TurnstileController),
|
||||
scriptType: controller.scriptType,
|
||||
});
|
||||
|
||||
if (
|
||||
|
||||
@@ -28,6 +28,20 @@ export abstract class CaptchaController implements ReactiveController {
|
||||
return (this.constructor as typeof CaptchaController).globalName;
|
||||
}
|
||||
|
||||
public static readonly scriptType: "classic" | "module" = "classic";
|
||||
|
||||
public get scriptType(): "classic" | "module" {
|
||||
return (this.constructor as typeof CaptchaController).scriptType;
|
||||
}
|
||||
|
||||
public static isAvailable(): boolean {
|
||||
return Object.hasOwn(window, this.globalName);
|
||||
}
|
||||
|
||||
public static matchesURL(_url: URL): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A prefix for log messages from this controller.
|
||||
*/
|
||||
@@ -42,7 +56,7 @@ export abstract class CaptchaController implements ReactiveController {
|
||||
): Array<CaptchaControllerConstructor | undefined> {
|
||||
return Array.from(controllerConstructors).filter((Controller) => {
|
||||
// Can we find the global for this captcha provider?
|
||||
return Object.hasOwn(window, Controller.globalName);
|
||||
return Controller.isAvailable();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -98,6 +112,9 @@ export abstract class CaptchaController implements ReactiveController {
|
||||
|
||||
export type CaptchaControllerConstructor = {
|
||||
globalName: string;
|
||||
scriptType: "classic" | "module";
|
||||
isAvailable: () => boolean;
|
||||
matchesURL: (url: URL) => boolean;
|
||||
} & (new (host: CaptchaHandlerHost) => CaptchaController);
|
||||
|
||||
export interface CaptchaHandlerHost extends ReactiveControllerHost {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { CaptchaController } from "#flow/stages/captcha/controllers/CaptchaController";
|
||||
|
||||
import { html } from "lit";
|
||||
|
||||
export function isCapWidgetURL(url: URL): boolean {
|
||||
return url.pathname.includes("cap-widget") || url.pathname.endsWith("/assets/widget.js");
|
||||
}
|
||||
|
||||
export class CapController extends CaptchaController {
|
||||
public static readonly globalName = "cap-widget";
|
||||
|
||||
public static readonly scriptType = "module";
|
||||
|
||||
public static override isAvailable(): boolean {
|
||||
return customElements.get("cap-widget") !== undefined;
|
||||
}
|
||||
|
||||
public static override matchesURL(url: URL): boolean {
|
||||
return isCapWidgetURL(url);
|
||||
}
|
||||
|
||||
public interactive = () => {
|
||||
const endpoint = this.host.challenge?.siteKey ?? "";
|
||||
|
||||
return html`<div id="ak-container" class="cap-container">
|
||||
<cap-widget
|
||||
id="ak-cap-widget"
|
||||
required
|
||||
data-cap-api-endpoint=${endpoint}
|
||||
></cap-widget>
|
||||
</div>
|
||||
<script>
|
||||
const widget = document.getElementById("ak-cap-widget");
|
||||
|
||||
widget.addEventListener("solve", (event) => {
|
||||
callback(event.detail.token);
|
||||
});
|
||||
|
||||
widget.addEventListener("error", (event) => {
|
||||
self.parent.postMessage({
|
||||
message: "error",
|
||||
source: "goauthentik.io",
|
||||
context: "flow-executor",
|
||||
error: event.detail.message,
|
||||
});
|
||||
});
|
||||
</script>`;
|
||||
};
|
||||
|
||||
public refreshInteractive = async () => {
|
||||
this.host.iframeRef.value?.contentWindow?.location.reload();
|
||||
};
|
||||
|
||||
public execute = async () => {
|
||||
throw new Error("Cap requires interactive mode.");
|
||||
};
|
||||
|
||||
public refresh = async () => {
|
||||
throw new Error("Cap requires interactive mode.");
|
||||
};
|
||||
}
|
||||
@@ -30,6 +30,7 @@ export interface IFrameTemplateInit {
|
||||
* Defaults to `true`.
|
||||
*/
|
||||
scriptOnLoad?: boolean;
|
||||
scriptType?: "classic" | "module";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,7 +43,7 @@ export interface IFrameTemplateInit {
|
||||
*/
|
||||
export function iframeTemplate(
|
||||
children: TemplateResult,
|
||||
{ challengeURL, theme, scriptOnLoad = true }: IFrameTemplateInit,
|
||||
{ challengeURL, theme, scriptOnLoad = true, scriptType = "classic" }: IFrameTemplateInit,
|
||||
) {
|
||||
return createDocumentTemplate({
|
||||
head: html`
|
||||
@@ -75,7 +76,7 @@ export function iframeTemplate(
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
background: ${ThemeColor[theme]};
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -88,15 +89,23 @@ export function iframeTemplate(
|
||||
}
|
||||
|
||||
.g-recaptcha,
|
||||
.h-captcha {
|
||||
.h-captcha,
|
||||
.cap-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cap-container {
|
||||
box-sizing: border-box;
|
||||
padding-block: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
${children}
|
||||
<script
|
||||
${scriptOnLoad ? 'onload="loadListener()"' : ""}
|
||||
${scriptType === "module" ? 'type="module"' : ""}
|
||||
src="${challengeURL.toString()}"
|
||||
></script>
|
||||
`,
|
||||
|
||||
@@ -49,6 +49,12 @@ export class CaptchaDisplayController implements ReactiveController {
|
||||
const input = this.#inputRef.value;
|
||||
if (!input) return;
|
||||
input.value = token;
|
||||
// The surrounding identification form only updates its validity when form controls
|
||||
// emit normal input events, so mirror a user's field change after the CAPTCHA solves.
|
||||
input.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
|
||||
input.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
|
||||
this.#loaded = true;
|
||||
this.host.requestUpdate();
|
||||
};
|
||||
|
||||
public onFailure() {
|
||||
|
||||
@@ -6187,10 +6187,6 @@ neprojde, když jedna nebo obě z vybraných možností jsou rovny nebo nad prah
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Volitelně omezte, které typy zařízení WebAuthn mohou být použity. Pokud nejsou vybrány žádné typy zařízení, jsou povolena všechna zařízení.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Toto omezení se vztahuje pouze na zařízení vytvořená v authentik 2024.4 nebo novějších verzích.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Krok použitý k nastavení WebAuthn autentizátoru (např. Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -6213,10 +6213,6 @@ Beim Erstellen eines festen Auswahlfelds aktiviere „Als Ausdruck interpretiere
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Optional kannst du einschränken, welche WebAuthn-Gerätetypen verwendet werden dürfen. Wenn keine Gerätetypen ausgewählt sind, sind alle Geräte erlaubt.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Diese Beschränkung gilt nur für Geräte, die in authentik 2024.4 oder neuer erstellt wurden.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Stage zur Konfiguration eines WebAuthn-Authenticators (z. B. Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -4781,9 +4781,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<trans-unit id="s1f4df216b56de4ac">
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
</trans-unit>
|
||||
|
||||
@@ -6153,10 +6153,6 @@ El valor de este campo se compara con el atributo de pertenencia del usuario.</t
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Opcionalmente, restrinja los tipos de dispositivos WebAuthn que se pueden usar. Si no se selecciona ningún tipo de dispositivo, se permiten todos.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Esta restricción solo se aplica a dispositivos creados en authentik 2024.4 o posterior.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Etapa utilizada para configurar un autenticador WebAuthn (es decir, Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -6328,10 +6328,6 @@ läpäisy estyy kun jompi kumpi tai molemmat vaihtoehdot ylittävät raja-arvon.
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Valinnaisesti voit rajoittaa, mitä WebAuthn-laitetyyppejä voidaan käyttää. Jos mitään tyyppiä ei ole valittu, kaiken tyyppiset laitteet sallitaan.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Tämä rajoitus koskee vain laitteita, jotka on luotu authentik 2024.4 tai uudemmalla versiolla.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Vaihe, jolla määritellään WebAuthn-todentaja (esim. Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -6318,10 +6318,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Optionnel, restreindre quels types d'appareil WebAuthn peuvent être utilisés. Lorsqu'aucun type d'appareil n'est sélectionné, tout les appareils sont autorisés.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Les restrictions ne s'appliquent qu'aux appareils créés dans authentik 2024.4 ou ultérieur.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Étape de configuration d'un authentificateur WebAuthn (Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -6110,10 +6110,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Facoltativamente limitare quali tipi di dispositivi WebAuthn possono essere utilizzati. Quando non vengono selezionati tipi di dispositivi, tutti i dispositivi sono consentiti.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Questa restrizione si applica solo ai dispositivi creati in authentik 2024.4 o versione successiva.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Fase utilizzato per configurare un autenticatore WebAuthn (ovvero Yubikey, FaceId/Windows Hello).</target>
|
||||
|
||||
@@ -6322,10 +6322,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>どの WebAuthn デバイスタイプを使用できるかをオプションで制限します。デバイスタイプが選択されていない場合、すべてのデバイスが許可されます。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>この制限は authentik 2024.4 以降で作成されたデバイスにのみ適用されます。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>WebAuthn 認証器を設定するために使用されるステージ(例:Yubikey、FaceID/Windows Hello)。</target>
|
||||
|
||||
@@ -5880,10 +5880,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<trans-unit id="s1f4df216b56de4ac">
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>이 제한은 authentik 2024.4 또는 이후에 등록된 기기에만 적용됩니다.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>WebAuthn 인증기를 구성하는 데 사용되는 스테이지(예: Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -5665,9 +5665,6 @@ slaagt niet wanneer een of beide geselecteerde opties gelijk zijn aan of boven d
|
||||
<trans-unit id="s1f4df216b56de4ac">
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
</trans-unit>
|
||||
|
||||
@@ -5896,10 +5896,6 @@ Można tu używać tylko zasad, ponieważ dostęp jest sprawdzany przed uwierzyt
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Opcjonalnie ogranicza, które typy urządzeń WebAuthn mogą być używane. Jeśli nie wybrano żadnego typu urządzenia, wszystkie urządzenia są dozwolone.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>To ograniczenie dotyczy tylko urządzeń utworzonych w wersji authentik 2024.4 lub nowszej.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Etap używany do konfiguracji uwierzytelniacza WebAuthn (np. Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -6322,10 +6322,6 @@ retorne uma lista para fornecer várias opções padrão.</target>
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Opcionalmente restrinja quais tipos de dispositivos WebAuthn podem ser usados. Quando nenhum tipo de dispositivo é selecionado, todos os dispositivos são permitidos.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Essa restrição se aplica apenas a dispositivos criados no authentik 2024.4 ou posterior.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Etapa usada para configurar um autenticador WebAuthn (ex.: Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -5946,10 +5946,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>Опционально ограничьте типы устройств WebAuthn, которые могут быть использованы. Если типы устройств не выбраны, разрешены все устройства.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Это ограничение распространяется только на устройства, созданные в authentik 2024.4 или более поздней версии.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Этап, используемый для настройки аутентификатора WebAuthn (например, Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -5944,10 +5944,6 @@ Belirlenen seçeneklerden biri veya her ikisi de eşiğe eşit veya eşiğin üz
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>İsteğe bağlı olarak, hangi WebAuthn cihaz türlerinin kullanılabileceğini kısıtlayın. Hiçbir cihaz türü seçilmediğinde, tüm cihazlara izin verilir.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>Bu kısıtlama yalnızca authentik 2024.4 veya sonraki sürümlerde oluşturulan cihazlar için geçerlidir.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>Bir WebAuthn kimlik doğrulayıcısını yapılandırmak için kullanılan sahne alanı (ör. Yubikey, FaceID/Windows Hello).</target>
|
||||
|
||||
@@ -6379,10 +6379,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
<target>可选的 WebAuthn 可用设备类型限制。如果未选择设备类型,则允许所有设备。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
<target>此限制仅适用于在 authentik 2024.4 或更新版本中创建的设备。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>用来配置 WebAuthn 身份验证器(即 Yubikey、FaceID/Windows Hello)的阶段。</target>
|
||||
|
||||
@@ -5707,9 +5707,6 @@ doesn't pass when either or both of the selected options are equal or above the
|
||||
<trans-unit id="s1f4df216b56de4ac">
|
||||
<source>Optionally restrict which WebAuthn device types may be used. When no device types are selected, all devices are allowed.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s11274960b13cf21a">
|
||||
<source>This restriction only applies to devices created in authentik 2024.4 or later.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s24bce955914b1f0a">
|
||||
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
|
||||
<target>用於設定 WebAuthn 身份認證器的階段(例如 Yubikey、FaceID/Windows Hello)。</target>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Captcha stage
|
||||
---
|
||||
|
||||
The Captcha stage adds CAPTCHA verification to a flow by using Google reCAPTCHA or compatible alternatives like hCaptcha and Cloudflare Turnstile.
|
||||
The Captcha stage adds CAPTCHA verification to a flow by using Google reCAPTCHA or compatible alternatives like hCaptcha, Cloudflare Turnstile, and Cap.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -20,6 +20,7 @@ It can either be bound to a flow or embedded inside the [Identification stage](.
|
||||
- **Error on invalid score**: show an error immediately when the score is outside the configured threshold. If disabled, the flow continues and policies can inspect the result from context.
|
||||
- **JS URL**: JavaScript loader URL for the provider.
|
||||
- **API URL**: verification endpoint URL for the provider.
|
||||
- **Request content type**: content type used when authentik verifies the CAPTCHA token with the provider.
|
||||
|
||||
## Flow integration
|
||||
|
||||
@@ -55,6 +56,25 @@ Recommended values:
|
||||
|
||||
Score thresholds only apply to hCaptcha Enterprise.
|
||||
|
||||
### Cap
|
||||
|
||||
Cap is a self-hostable CAPTCHA server that uses proof-of-work challenges.
|
||||
|
||||
See https://trycap.dev/guide/.
|
||||
|
||||
authentik supports Cap's default widget. The floating widget is not supported.
|
||||
|
||||
Recommended values:
|
||||
|
||||
- **Public key**: public Cap endpoint for the site key path, for example `https://cap.example.com/site-key/`
|
||||
- **Private key**: Cap secret key
|
||||
- **Interactive**: enabled
|
||||
- **JS URL**: self-hosted Cap widget asset, for example `https://cap.example.com/assets/widget.js`. If you use a CDN, pin a reviewed release such as `https://cdn.jsdelivr.net/npm/cap-widget@<version>` instead of the unversioned package URL. See [Cap releases](https://github.com/tiagozip/cap/releases).
|
||||
- **API URL**: Cap verification endpoint, for example `https://cap.example.com/site-key/siteverify`
|
||||
- **Request content type**: JSON
|
||||
|
||||
Cap does not use score thresholds.
|
||||
|
||||
### Cloudflare Turnstile
|
||||
|
||||
See https://developers.cloudflare.com/turnstile/get-started/migrating-from-recaptcha.
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Create a SCIM provider
|
||||
---
|
||||
|
||||
## Create a SCIM provider with token authentication
|
||||
|
||||
To create a provider along with a corresponding application, navigate to **Applications** > **Applications** and click **New Application**. We recommend this combined approach for most common use cases. Alternatively, you can use the legacy method to solely create the provider by navigating to **Applications** > **Providers** and clicking **New Provider**.
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Applications** and click **New Application** to create an application and provider pair.
|
||||
3. On the **Application** page, define the application settings, and then click **Next**.
|
||||
4. Select **SCIM** as the **Provider Type**, and then click **Next**.
|
||||
5. On the **Configure Provider** page, provide the configuration settings, and then click **Next**.
|
||||
6. On the **Configure Bindings** page, click **Next**.
|
||||
7. Click **Create** to create both the application and the provider.
|
||||
|
||||
### Set the SCIM provider as a backchannel provider for the application
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Applications** and click the edit icon of the new SCIM application.
|
||||
3. Click the plus icon (+) next to **Backchannel providers**.
|
||||
4. Select the new SCIM provider, and then click **Confirm**.
|
||||
5. Click **Save changes**.
|
||||
|
||||
## Create a SCIM provider with OAuth authentication
|
||||
|
||||
There are 3 required steps to creating a SCIM provider:
|
||||
|
||||
1. [Create an OAuth source](#create-an-oauth-source)
|
||||
2. [Create a SCIM application and provider](#create-a-scim-application-and-provider)
|
||||
3. [Set the SCIM provider as a backchannel provider for the application](#set-the-scim-provider-as-a-backchannel-provider-for-the-application)
|
||||
|
||||
If using OAuth (Interactive) mode, you will also need to:
|
||||
|
||||
4. [Provide admin authorization](#provide-admin-authorization-oauth-interactive-mode-only)
|
||||
|
||||
### Create an OAuth source
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Directory** > **Federation and Social login** and click **New Source**.
|
||||
3. Select **OpenID OAuth Source** as the **Source type**.
|
||||
4. On the **OpenID OAuth Source Details** page, provide the configuration settings provided by the SCIM endpoint that you are provisioning to, and then click **Create**.
|
||||
|
||||
### Create a SCIM application and provider
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Applications** and click **New Application** to create an application and provider pair.
|
||||
3. On the **Application** page, define the application settings, and then click **Next**.
|
||||
4. Select **SCIM** as the **Provider Type**, and then click **Next**.
|
||||
5. On the **Configure Provider** page, configure the required settings. Set **Authentication mode** to the desired OAuth option, select the **OAuth source** you created in the previous section, and then click **Next**.
|
||||
6. On the **Configure Bindings** page, click **Next**.
|
||||
7. Click **Create** to create both the application and the provider.
|
||||
|
||||
### Set the SCIM provider as a backchannel provider for the application
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Applications** and click the edit icon of the new SCIM application.
|
||||
3. Click the plus icon (+) next to **Backchannel providers**.
|
||||
4. Select the new SCIM provider, and then click **Confirm**.
|
||||
5. Click **Save changes**.
|
||||
|
||||
### Provide admin authorization (OAuth Interactive mode only)
|
||||
|
||||
If you selected **OAuth (Interactive)** as the **Authentication mode** for the SCIM provider, you will need to authorize the initial OAuth connection.
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Providers** and click the name of the new SCIM provider.
|
||||
3. Next to **OAuth Status**, click **(Re-)Authenticate**.
|
||||
4. You should be redirected to the SCIM endpoint that you are provisioning to for authentication.
|
||||
5. Once authenticated, you should be redirected back to authentik. If successful, **OAuth Status** should now show as **Authenticated**.
|
||||
This step is only required when initially configuring the SCIM provider; subsequent authentications will be automatic.
|
||||
@@ -8,13 +8,7 @@ A SCIM provider requires a SCIM base URL for the endpoint and an authentication
|
||||
|
||||
SCIM providers in authentik always serve as [backchannel providers](../../applications/manage_apps.mdx#backchannel-providers), which are used in addition to the main provider that supplies SSO authentication. A backchannel provider is used for an application that requires backend authentication, directory synchronization, or other additional authentication needs.
|
||||
|
||||
## Set up a SCIM provider
|
||||
|
||||
Many applications use SCIM together with another SSO protocol such as OAuth/OIDC or SAML. For example, you can create an application and provider pair for Slack by using SAML for authentication and SCIM for provisioning. For this setup, use the following workflow:
|
||||
|
||||
1. [Create](../../applications/manage_apps.mdx#create-an-application-and-provider-pair) the application and provider pair.
|
||||
2. [Create](../../applications/manage_apps.mdx#backchannel-providers) the SCIM backchannel provider.
|
||||
3. Edit the application, and in the **Backchannel Providers** field add the SCIM provider that you created.
|
||||
For instructions on creating a SCIM provider, refer to the [Create a SCIM provider](./create-scim-provider.md) documentation.
|
||||
|
||||
## Authentication modes
|
||||
|
||||
@@ -23,12 +17,6 @@ In authentik, there are two ways to authenticate SCIM requests:
|
||||
- **Static token** provided by the application. This is the default authentication mode.
|
||||
- **OAuth token** that authentik retrieves from a specified source and uses for authentication.
|
||||
|
||||
When you create a new SCIM provider, select the **Authentication Mode** that the application supports.
|
||||
|
||||

|
||||
|
||||
For either mode, enter the SCIM base **URL** for the endpoint.
|
||||
|
||||
### Static token
|
||||
|
||||
When the authentication mode is set to **Static token**, authentik sends the token provided by the application with outgoing SCIM requests to authenticate each request.
|
||||
@@ -37,6 +25,12 @@ When the authentication mode is set to **Static token**, authentik sends the tok
|
||||
|
||||
When you configure a SCIM provider to use OAuth for authentication, authentik generates short-lived tokens through an OAuth flow and sends them to the SCIM endpoint. This offers improved security and control compared with a static token.
|
||||
|
||||
authentik supports two types of SCIM OAuth authentication:
|
||||
|
||||
- **Silent OAuth** – The system obtains or refreshes access tokens automatically, without any administrator interaction. This is the typical approach used for ongoing SCIM provisioning.
|
||||
|
||||
- **Interactive OAuth** – During setup, an administrator is required to authorize the connection before the SCIM integration can obtain its initial token. authentik then stores a refresh token, and provisioning then runs in the background without further admin interaction.
|
||||
|
||||
You can also add additional token request parameters such as `grant_type`, `subject_token`, or `client_assertion`.
|
||||
|
||||
**Example**:
|
||||
|
||||
@@ -102,7 +102,7 @@ Every application that you add to authentik requires a provider, which is used t
|
||||
authorization, etc.
|
||||
- **Protocol settings**: provide the following required configurations:
|
||||
- Note the **Client ID**, **Client Secret**, and **Slug** values because they will be required later when you configure Grafana to use authentik.
|
||||
- Set the **Redirect URI** as a `Strict` redirect to `https://grafana.company/login/generic_oauth`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://grafana.company/login/generic_oauth`.
|
||||
- <strong className="tip">TIP</strong>: The Redirect URI is where a user is directed to,
|
||||
as soon as authentik's authorization flow is successfully completed.
|
||||
- **Grant Types** (required): Select at least one [grant type](../../add-secure-apps/providers/oauth2/#oauth-20-flows-and-grant-types) that the provider can use.
|
||||
|
||||
@@ -254,7 +254,15 @@ const items = [
|
||||
"add-secure-apps/providers/saml/saml_single_logout",
|
||||
],
|
||||
},
|
||||
"add-secure-apps/providers/scim/index",
|
||||
{
|
||||
type: "category",
|
||||
label: "SCIM Provider",
|
||||
link: {
|
||||
type: "doc",
|
||||
id: "add-secure-apps/providers/scim/index",
|
||||
},
|
||||
items: ["add-secure-apps/providers/scim/create-scim-provider"],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
label: "SSF Provider",
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
:::info Redirect URI changes in authentik 2026.5
|
||||
In authentik versions earlier than 2026.5, all **Redirect URIs** are automatically treated as `Authorization` type. If you are using one of these older authentik versions, add only the `Authorization` URL to your **Redirect URIs** and do not configure a `Post Logout` URI.
|
||||
:::
|
||||
@@ -4,6 +4,8 @@ sidebar_label: AFFiNE
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is AFFiNE?
|
||||
|
||||
> AFFiNE is an open-source, self-hostable workspace for documents, whiteboards, and databases.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of AFFiNE with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -33,7 +37,7 @@ To support the integration of AFFiNE with authentik, you need to create an appli
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Add one `Strict` redirect URI and set it to `https://affine.company/oauth/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://affine.company/oauth/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ sidebar_label: ChatGPT
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
import SAMLProvider20265Warning from "../../_saml-provider-2026-5-warning.mdx";
|
||||
import TabItem from "@theme/TabItem";
|
||||
import Tabs from "@theme/Tabs";
|
||||
@@ -38,6 +39,8 @@ You can configure ChatGPT to use either OIDC or SAML; this guide explains both o
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of ChatGPT with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -48,7 +51,7 @@ To support the integration of ChatGPT with authentik, you need to create an appl
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **Client Secret** values because they will be required later.
|
||||
- Temporarily set a `Strict` redirect URI to `https://temp.temp`.
|
||||
- Temporarily add a **Redirect URI** of type `Strict` `Authorization` as `https://temp.temp`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
@@ -77,7 +80,7 @@ ChatGPT only enables the **Manage SSO** wizard after you verify ownership of you
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Providers** and click the **Edit** icon of the newly created ChatGPT provider.
|
||||
3. Under **Protocol settings**, set the **Redirect URIs** to the **Login redirect URI** from ChatGPT.
|
||||
3. Under **Protocol settings**, add a **Redirect URI** of type `Strict` `Authorization` as the **Login redirect URI** value from ChatGPT.
|
||||
4. Click **Update**.
|
||||
|
||||
</TabItem>
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: EspoCRM
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is EspoCRM?
|
||||
|
||||
> EspoCRM is a CRM (customer relationship management) web application that allows users to store, visualize, and analyze their company's business-related relationships such as opportunities, people, businesses, and projects.
|
||||
@@ -27,6 +29,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of EspoCRM with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -37,7 +41,7 @@ To support the integration of EspoCRM with authentik, you need to create an appl
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://espocrm.company/oauth-callback.php`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://espocrm.company/oauth-callback.php`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings**, set **Subject mode** to **Based on the User's username**.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: grommunio
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
<!-- spellchecker:ignore gromox -->
|
||||
|
||||
## What is grommunio?
|
||||
@@ -25,6 +27,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To integrate authentik with grommunio, you will need to create an application and provider pair in authentik.
|
||||
|
||||
:::info Keycloak-compatible endpoints
|
||||
@@ -39,7 +43,7 @@ grommunio-web expects Keycloak-compatible OIDC endpoints. Because authentik does
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name, the authorization flow to use, and the following required configurations.
|
||||
- Note the **Client ID** and **Client Secret** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://grommunio.company/web`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://grommunio.company/web`.
|
||||
- Set **Signing Key** to an available RSA key.
|
||||
- Under **Advanced protocol settings**:
|
||||
- Add the `authentik default OAuth Mapping: OpenID 'offline_access'` scope to **Selected Scopes**.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: HedgeDoc
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is HedgeDoc?
|
||||
|
||||
> HedgeDoc lets you create real-time collaborative markdown notes.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of HedgeDoc with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -33,7 +37,7 @@ To support the integration of HedgeDoc with authentik, you need to create an app
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **Client Secret** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://hedgedoc.company/auth/oauth2/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://hedgedoc.company/auth/oauth2/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
3. Click **Submit** to save the new application and provider.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Kanboard
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Kanboard?
|
||||
|
||||
> Kanboard is a free and open source Kanban project management software.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Kanboard with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -33,7 +37,7 @@ To support the integration of Kanboard with authentik, you need to create an app
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **Client Secret** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://kanboard.company/oauth/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://kanboard.company/oauth/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: mailcow Logs Viewer
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is mailcow Logs Viewer?
|
||||
|
||||
> A modern, self-hosted dashboard for monitoring, analyzing, and managing your mailcow mail server. Track email delivery, investigate spam, manage quarantine, detect bounce-based abuse, and validate DNS configurations, all from a single interface.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of mailcow Logs Viewer with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -33,7 +37,7 @@ To support the integration of mailcow Logs Viewer with authentik, you need to cr
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **application slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://mailcow-logs-viewer.company/api/auth/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://mailcow-logs-viewer.company/api/auth/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: mailcow
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is mailcow?
|
||||
|
||||
> mailcow is a Dockerized, open-source groupware and email suite based on Docker. It relies on many well-known and long-used components, which, when combined, result in a comprehensive email server solution.
|
||||
@@ -27,6 +29,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of mailcow with authentik, you need to create a property mapping, set the `email_verified` attribute on required users, and create an application/provider pair in authentik.
|
||||
|
||||
### Create a property mapping
|
||||
@@ -56,7 +60,7 @@ Repeat these steps for all users that need to use the Mailcow integration.
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **Client Secret** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://mailcow.company`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://mailcow.company`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings**:
|
||||
- Remove the `authentik default OAuth Mapping: OpenID 'email'` scope from **Selected Scopes**.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Mastodon
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Mastodon?
|
||||
|
||||
> Mastodon is free and open-source software for running self-hosted social networking services. It has microblogging features similar to Twitter
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Mastodon with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -34,7 +38,7 @@ To support the integration of Mastodon with authentik, you need to create an app
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://mastodon.company/auth/auth/openid_connect/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://mastodon.company/auth/auth/openid_connect/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Matrix Synapse
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Matrix Synapse?
|
||||
|
||||
> Matrix is an open source project that publishes the Matrix open standard for secure, decentralized, real-time communication, and its Apache licensed reference implementations.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Matrix Synapse with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -34,7 +38,7 @@ To support the integration of Matrix Synapse with authentik, you need to create
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://matrix.company/_synapse/client/oidc/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://matrix.company/_synapse/client/oidc/callback`.
|
||||
- Select any available RSA signing key. Matrix Synapse doesn't support ECC keys.
|
||||
- Do not set an encryption key because this is not supported by Matrix Synapse.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
+4
-1
@@ -4,6 +4,7 @@ sidebar_label: Mattermost Team Edition
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
import SAMLProvider20265Warning from "../../_saml-provider-2026-5-warning.mdx";
|
||||
import TabItem from "@theme/TabItem";
|
||||
import Tabs from "@theme/Tabs";
|
||||
@@ -45,6 +46,8 @@ Once configured, Mattermost will display a login button with the GitLab icon, bu
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Mattermost Team Edition with authentik, you need to create property mappings and an application/provider pair in authentik.
|
||||
|
||||
### Create property mappings
|
||||
@@ -84,7 +87,7 @@ The following `id` property mapping is optional. If omitted, Mattermost will gen
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **Client Secret** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://mattermost.company/signup/gitlab/complete`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://mattermost.company/signup/gitlab/complete`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings**, add the scopes you just created to the list of selected scopes.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Mobilizon
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Mobilizon?
|
||||
|
||||
> Gather, organize and mobilize yourselves with a convivial, ethical, and emancipating tool. https://joinmobilizon.org
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Mobilizon with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -34,7 +38,7 @@ To support the integration of Mobilizon with authentik, you need to create an ap
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://mobilizon.company/auth/keycloak/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://mobilizon.company/auth/keycloak/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ sidebar_label: Nextcloud
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
import SAMLProvider20265Warning from "../../_saml-provider-2026-5-warning.mdx";
|
||||
|
||||
## What is Nextcloud?
|
||||
@@ -116,13 +117,16 @@ To connect to an existing Nextcloud user, set the `nextcloud_user_id` attribute
|
||||
|
||||
## Create an application and provider in authentik
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
1. Log in to authentik as an administrator and open the authentik Admin interface.
|
||||
2. Navigate to **Applications** > **Applications** and click **New Application** to create an application and provider pair. (Alternatively you can first create a provider separately, then create the application and connect it with the provider.)
|
||||
- **Application**: provide a descriptive name, an optional group for the type of application, the policy engine mode, and optional UI settings.
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://nextcloud.company/apps/user_oidc/code`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://nextcloud.company/apps/user_oidc/code`.
|
||||
- Add a **Redirect URI** of type `Strict` `Post Logout` as `https://nextcloud.company`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings**:
|
||||
- _(optional)_ If you created the `Nextcloud Profile` scope mapping, add it to **Selected Scopes**.
|
||||
|
||||
@@ -4,6 +4,7 @@ sidebar_label: OpenCloud
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
import TabItem from "@theme/TabItem";
|
||||
import Tabs from "@theme/Tabs";
|
||||
|
||||
@@ -35,6 +36,8 @@ Choose your setup below. The **Web only** tab logs in through the browser. The *
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
1. Log in to authentik as an administrator and open the Admin interface.
|
||||
2. Navigate to **Applications** > **Applications** and click **New Application**.
|
||||
- **Application**: provide a name and note the **slug**.
|
||||
@@ -43,9 +46,9 @@ Choose your setup below. The **Web only** tab logs in through the browser. The *
|
||||
- **Client type**: `Public`
|
||||
- **Client ID**: `web`
|
||||
- **Redirect URIs**:
|
||||
- Strict: `https://opencloud.company/oidc-callback.html`
|
||||
- Strict: `https://opencloud.company/oidc-silent-redirect.html`
|
||||
- Strict: `https://opencloud.company/`
|
||||
- `Strict` `Authorization`: `https://opencloud.company/oidc-callback.html`
|
||||
- `Strict` `Authorization`: `https://opencloud.company/oidc-silent-redirect.html`
|
||||
- `Strict` `Authorization`: `https://opencloud.company/`
|
||||
- **Signing Key**: select any available key.
|
||||
- **Scopes**: `openid`, `profile`, `email`.
|
||||
3. Click **Submit**.
|
||||
@@ -112,12 +115,12 @@ With GLOBAL issuer mode enabled, tokens use an issuer of `iss = https://authenti
|
||||
|
||||
Repeat these steps for **each** of the four clients (Web, Desktop, Android, and iOS), using the per-client values from the table below.
|
||||
|
||||
| Client | Client ID | Redirect URIs |
|
||||
| ------- | ------------------ | ------------------------------------------------------------------------------------------- |
|
||||
| Web | `web` | Strict: `https://opencloud.company/oidc-callback.html`, `…/oidc-silent-redirect.html`, `…/` |
|
||||
| Desktop | `OpenCloudDesktop` | Regex: `http://127.0.0.1(:[0-9]+)?(/.*)?` and `http://localhost(:[0-9]+)?(/.*)?` |
|
||||
| Android | `OpenCloudAndroid` | Strict: `oc://android.opencloud.eu` |
|
||||
| iOS | `OpenCloudIOS` | Strict: `oc://ios.opencloud.eu` |
|
||||
| Client | Client ID | Redirect URIs |
|
||||
| ------- | ------------------ | ------------------------------------------------------------------------------------------------------------- |
|
||||
| Web | `web` | `Strict` `Authorization`: `https://opencloud.company/oidc-callback.html`, `…/oidc-silent-redirect.html`, `…/` |
|
||||
| Desktop | `OpenCloudDesktop` | `Regex` `Authorization`: `http://127.0.0.1(:[0-9]+)?(/.*)?` and `http://localhost(:[0-9]+)?(/.*)?` |
|
||||
| Android | `OpenCloudAndroid` | `Strict` `Authorization`: `oc://android.opencloud.eu` |
|
||||
| iOS | `OpenCloudIOS` | `Strict` `Authorization`: `oc://ios.opencloud.eu` |
|
||||
|
||||
1. Log in to authentik as an administrator and open the Admin interface.
|
||||
2. Navigate to **Applications** > **Applications** and click **New Application**.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: OpenProject
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is OpenProject?
|
||||
|
||||
> OpenProject is a web-based project management software. Use OpenProject to manage your projects, tasks and goals. Collaborate via work packages and link them to your pull requests on GitHub.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of OpenProject with authentik, you need to create a property mapping and an application/provider pair in authentik.
|
||||
|
||||
### Create a scope mapping
|
||||
@@ -61,7 +65,7 @@ OpenProject requires a first and last name for each user. By default authentik o
|
||||
- **Protocol settings**:
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- **Redirect URI**:
|
||||
- Strict: `https://openproject.company/auth/oidc-authentik/callback`
|
||||
- `Strict` `Authorization`: `https://openproject.company/auth/oidc-authentik/callback`
|
||||
- **Signing key**: select any available signing key.
|
||||
- **Advanced protocol settings**:
|
||||
- **Scopes**:
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: ownCloud
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is ownCloud?
|
||||
|
||||
> ownCloud is a free and open-source software project for content collaboration and sharing and syncing of files.
|
||||
@@ -23,6 +25,8 @@ This guide focuses on deploying ownCloud installations using Docker. If you depl
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of ownCloud with authentik, you need to create multiple application/provider pairs in authentik. A different pair is required for the Web UI, Desktop application, Android application, and iOS application.
|
||||
|
||||
The configuration for each application is nearly identical, except for the **Client ID**, **Client Secret**, and the **Redirect URI** values, which are [predefined](https://doc.owncloud.com/server/latest/admin_manual/configuration/user/oidc/oidc.html#client-ids-secrets-and-redirect-uris) by ownCloud for the Desktop, Android, and iOS applications.
|
||||
@@ -43,29 +47,29 @@ The configuration for each application is nearly identical, except for the **Cli
|
||||
- **Client ID**: Use the value generated by authentik.
|
||||
- **Client Secret**: Use the value generated by authentik.
|
||||
- **Redirect URIs**:
|
||||
- Strict: `https://owncloud.company/apps/openidconnect/redirect`
|
||||
- `Strict` `Authorization`: `https://owncloud.company/apps/openidconnect/redirect`
|
||||
|
||||
**Desktop Application**
|
||||
- **Signing Key**: Select any available signing key.
|
||||
- **Client ID**: Use the predefined value found in the [ownCloud admin manual](https://doc.owncloud.com/server/latest/admin_manual/configuration/user/oidc/oidc.html#client-id).
|
||||
- **Client Secret**: Use the predefined value found in the [ownCloud admin manual](https://doc.owncloud.com/server/latest/admin_manual/configuration/user/oidc/oidc.html#client-secret).
|
||||
- **Redirect URIs**:
|
||||
- Regex: `http://localhost:\d+`
|
||||
- Regex: `http://127.0.0.1:\d+`
|
||||
- `Regex` `Authorization`: `http://localhost:\d+`
|
||||
- `Regex` `Authorization`: `http://127.0.0.1:\d+`
|
||||
|
||||
**Android Application**
|
||||
- **Signing Key**: Select any available signing key.
|
||||
- **Client ID**: Use the predefined value found in the [ownCloud admin manual](https://doc.owncloud.com/server/latest/admin_manual/configuration/user/oidc/oidc.html#client-id).
|
||||
- **Client Secret**: Use the predefined value found in the [ownCloud admin manual](https://doc.owncloud.com/server/latest/admin_manual/configuration/user/oidc/oidc.html#client-secret).
|
||||
- **Redirect URI**:
|
||||
- Strict: `oc://android.owncloud.com`
|
||||
- `Strict` `Authorization`: `oc://android.owncloud.com`
|
||||
|
||||
**iOS Application**
|
||||
- **Signing Key**: Select any available signing key.
|
||||
- **Client ID**: Use the predefined value found in the [ownCloud admin manual](https://doc.owncloud.com/server/latest/admin_manual/configuration/user/oidc/oidc.html#client-id).
|
||||
- **Client Secret**: Use the predefined value found in the [ownCloud admin manual](https://doc.owncloud.com/server/latest/admin_manual/configuration/user/oidc/oidc.html#client-secret).
|
||||
- **Redirect URI**:
|
||||
- Strict: `oc://ios.owncloud.com`
|
||||
- `Strict` `Authorization`: `oc://ios.owncloud.com`
|
||||
|
||||
- **Advanced protocol settings:**
|
||||
- **Scopes**: Select the following scopes for each of the four application/provider pairs: `email`, `offline_access`, `openid`, `profile`.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Planka
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Planka?
|
||||
|
||||
> Planka is an open-source, Trello-like application with a Kanban board system, used for project management.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Planka with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -33,7 +37,7 @@ To support the integration of Planka with authentik, you need to create an appli
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **Client Secret** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://planka.company/oidc-callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://planka.company/oidc-callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Rocket.chat
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Rocket.chat?
|
||||
|
||||
> Rocket.Chat is an open-source fully customizable communications platform developed in JavaScript for organizations with high standards of data protection. It is licensed under the MIT License with some other licenses mixed in. See [Rocket.chat GitHub](https://github.com/RocketChat/Rocket.Chat/blob/develop/LICENSE) for licensing information.
|
||||
@@ -27,6 +29,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Rocket.chat with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -38,7 +42,7 @@ To support the integration of Rocket.chat with authentik, you need to create an
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://rocket.company/\_oauth/authentik`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://rocket.company/\_oauth/authentik`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Roundcube
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Roundcube?
|
||||
|
||||
> Roundcube is a browser-based multilingual IMAP client with an application-like user interface. It provides the full functionality you expect from an email client, including MIME support, address book, folder manipulation, message searching and spell checking.
|
||||
@@ -29,6 +31,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Roundcube with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create property mappings
|
||||
@@ -59,7 +63,7 @@ To support the integration of Roundcube with authentik, you need to create an ap
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://roundcube.company/index.php?\_task=settings&\_action=plugin.oauth_redirect`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://roundcube.company/index.php?\_task=settings&\_action=plugin.oauth_redirect`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings**:
|
||||
- Under **Scopes**, add `dovecotprofile` and `authentik default OAuth Mapping: OpenID 'offline_access'` to the list of selected scopes.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: SharePoint Server SE
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Microsoft SharePoint?
|
||||
|
||||
> SharePoint is a proprietary, web-based collaborative platform that integrates natively with Microsoft 365.
|
||||
@@ -66,6 +68,8 @@ These guidelines use the following placeholders for the overall setup:
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
### Step 1: Create authentik OpenID property mappings
|
||||
|
||||
SharePoint requires additional properties within the OpenID and profile scopes in order to operate OIDC properly and map incoming authentik OID claims with Microsoft claims.
|
||||
@@ -140,7 +144,7 @@ From the authentik Admin Dashboard:
|
||||
:::info
|
||||
use the explicit flow if user consents are required
|
||||
:::
|
||||
- **Redirect URIs / Origins**: `auth.providerRedirectURI`
|
||||
- **Redirect URIs / Origins** (`Strict` `Authorization`): `auth.providerRedirectURI`
|
||||
- **Signing Key**: authentik Self-signed Certificate
|
||||
:::info
|
||||
The certificate is used for signing JWT tokens; if you change it after the integration do not forget to update your SharePoint Trusted Certificate.
|
||||
|
||||
@@ -4,6 +4,7 @@ sidebar_label: Vikunja
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
import TabItem from "@theme/TabItem";
|
||||
import Tabs from "@theme/Tabs";
|
||||
|
||||
@@ -31,6 +32,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Vikunja with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -41,8 +44,8 @@ To support the integration of Vikunja with authentik, you need to create an appl
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- For web login, set a `Strict` redirect URI to `https://vikunja.company/auth/openid/authentik`.
|
||||
- If using the Vikunja desktop client, add a `Regex` redirect URI such as `^http://127\\.0\\.0\\.1:[0-9]+/auth/openid/authentik$` to allow loopback redirects to `127.0.0.1`.
|
||||
- For web login, add a **Redirect URI** of type `Strict` `Authorization` as `https://vikunja.company/auth/openid/authentik`.
|
||||
- If using the Vikunja desktop client, add a **Redirect URI** of type `Regex` `Authorization` such as `^http://127\\.0\\.0\\.1:[0-9]+/auth/openid/authentik$` to allow loopback redirects to `127.0.0.1`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
3. Click **Submit** to save the new application and provider.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Wekan
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Wekan?
|
||||
|
||||
> Wekan is an open-source kanban board which allows a card-based task and to-do management.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Wekan with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -34,7 +38,7 @@ To support the integration of Wekan with authentik, you need to create an applic
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://wekan.company/_oauth/oidc`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://wekan.company/_oauth/oidc`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Writefreely
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Writefreely?
|
||||
|
||||
> An open source platform for building a writing space on the web.
|
||||
@@ -27,6 +29,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Writefreely with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -38,7 +42,7 @@ To support the integration of Writefreely with authentik, you need to create an
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://writefreely.company/oauth/callback/generic`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://writefreely.company/oauth/callback/generic`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ sidebar_label: Amazon Web Services (Classic IAM)
|
||||
support_level: authentik
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
import SAMLProvider20265Warning from "../../_saml-provider-2026-5-warning.mdx";
|
||||
import TabItem from "@theme/TabItem";
|
||||
import Tabs from "@theme/Tabs";
|
||||
@@ -44,6 +45,8 @@ SCIM Provisioning is only supported in conjunction with [IAM Identity Center](..
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of AWS with authentik via the Classic IAM method, you need to create two property mappings, an application/provider pair, and application entitlements for the AWS roles that users can assume.
|
||||
|
||||
### Create property mappings
|
||||
@@ -273,7 +276,7 @@ To support the integration of AWS with authentik using OIDC, you need to create
|
||||
- **Choose a Provider type**: Select OAuth2/OpenID Provider as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to match the AWS resource that you want to access via OIDC.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` that matches the AWS resource that you want to access via OIDC.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings** > **Selected Scopes**, add `authentik default OAuth Mapping: OpenID 'entitlements'`.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: DigitalOcean
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is DigitalOcean?
|
||||
|
||||
> DigitalOcean is a cloud infrastructure provider that offers developers simple, scalable virtual servers (droplets), managed databases, and other cloud services to deploy and manage applications efficiently.
|
||||
@@ -22,6 +24,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of DigitalOcean with authentik, you need to create a scope mapping, an application/provider pair, and application entitlements for the DigitalOcean roles that users should receive.
|
||||
|
||||
### Create a scope mapping
|
||||
@@ -72,7 +76,7 @@ To support the integration of DigitalOcean with authentik, you need to create a
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://cloud.digitalocean.com/sessions/sso/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://cloud.digitalocean.com/sessions/sso/callback`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings**:
|
||||
- Add the `profile` scope created in the previous section. Do not remove authentik’s `authentik default OAuth Mapping: OpenID 'profile'`, as claims such as `name` are required by DigitalOcean.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Oracle Cloud
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Oracle Cloud?
|
||||
|
||||
> Oracle Cloud is the first public cloud built from the ground up to be a better cloud for every application. By rethinking core engineering and systems design for cloud computing, we created innovations that accelerate migrations, deliver better reliability and performance for all applications, and offer the complete services customers need to build innovative cloud applications.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Oracle Cloud with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -35,7 +39,7 @@ To support the integration of Oracle Cloud with authentik, you need to create an
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://tenant.identity.oraclecloud.com/oauth2/v1/social/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://tenant.identity.oraclecloud.com/oauth2/v1/social/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Dashy
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Dashy?
|
||||
|
||||
> Dashy is a self-hostable personal dashboard built for you. Includes status-checking, widgets, themes, icon packs, a UI editor and tons more.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Dashy with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
If you want to manage Dashy administrator access through authentik, create or choose a group for Dashy administrators and add the appropriate users to it. Note the exact group name because it will be required later.
|
||||
@@ -36,7 +40,7 @@ If you want to manage Dashy administrator access through authentik, create or ch
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **slug** values because they will be required later.
|
||||
- Set the **Client type** to `Public`. Dashy runs entirely in the browser and does not store a client secret.
|
||||
- Create two `Strict` redirect URIs:
|
||||
- Add two **Redirect URIs** of type `Strict` `Authorization`:
|
||||
- `https://dashy.company`
|
||||
- `https://dashy.company/`
|
||||
- Select any available signing key.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Homarr
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Homarr?
|
||||
|
||||
> A sleek, modern dashboard that puts all of your apps and services at your fingertips. Control everything in one convenient location. Seamlessly integrates with the apps you've added, providing you with valuable information.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Homarr with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -34,7 +38,7 @@ To support the integration of Homarr with authentik, you need to create an appli
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Create two `Strict` redirect URIs: `https://homarr.company/api/auth/callback/oidc` and `http://localhost:50575/api/auth/callback/oidc`.
|
||||
- Add two **Redirect URIs** of type `Strict` `Authorization` as `https://homarr.company/api/auth/callback/oidc` and `http://localhost:50575/api/auth/callback/oidc`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Linkwarden
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Linkwarden?
|
||||
|
||||
> Linkwarden is an open-source collaborative bookmark manager used to collect, organize, and preserve webpages.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Linkwarden with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -34,7 +38,7 @@ To support the integration of Linkwarden with authentik, you need to create an a
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://linkwarden.company/api/v1/auth/callback/authentik`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://linkwarden.company/api/v1/auth/callback/authentik`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Coder
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Coder?
|
||||
|
||||
> Coder is an open-source platform that provides browser-based cloud development environments, enabling developers and teams to securely write, edit, and manage code remotely without the need for local setup.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Coder with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -34,7 +38,7 @@ To support the integration of Coder with authentik, you need to create an applic
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://coder.company/api/v2/users/oidc/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://coder.company/api/v2/users/oidc/callback`.
|
||||
- Select any available signing key.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: engomo
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is engomo?
|
||||
|
||||
> engomo is a low-code app development platform to create enterprise apps for smartphones and tablets based on Android, iOS, or iPadOS.
|
||||
@@ -25,6 +27,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Engomo with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create property mappings
|
||||
@@ -46,7 +50,7 @@ To support the integration of Engomo with authentik, you need to create an appli
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID** and **slug** values because they will be required later.
|
||||
- Set the **Client type** to `Public`.
|
||||
- Add two `Strict` redirect URIs and set them to `https://engomo.company/auth` and `com.engomo.engomo://callback/`.
|
||||
- Add two **Redirect URIs** of type `Strict` `Authorization` as `https://engomo.company/auth` and `com.engomo.engomo://callback/`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings**, add the scope you just created to the list of available scopes.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
@@ -4,6 +4,8 @@ sidebar_label: Forgejo
|
||||
support_level: community
|
||||
---
|
||||
|
||||
import RedirectURI20265Note from "../../\_redirect-uri-2026-5-note.mdx";
|
||||
|
||||
## What is Forgejo?
|
||||
|
||||
> Forgejo is a lightweight, self‑hosted alternative to GitHub/GitLab, with a strong emphasis on community governance and open development.
|
||||
@@ -23,6 +25,8 @@ This documentation lists only the settings that you need to change from their de
|
||||
|
||||
## authentik configuration
|
||||
|
||||
<RedirectURI20265Note />
|
||||
|
||||
To support the integration of Forgejo with authentik, you need to create an application/provider pair in authentik.
|
||||
|
||||
### Create an application and provider in authentik
|
||||
@@ -33,7 +37,7 @@ To support the integration of Forgejo with authentik, you need to create an appl
|
||||
- **Choose a Provider type**: select **OAuth2/OpenID Connect** as the provider type.
|
||||
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
|
||||
- Note the **Client ID**, **Client Secret**, and **slug** values because they will be required later.
|
||||
- Set a `Strict` redirect URI to `https://<forgejo.company>/user/oauth2/authentik/callback`.
|
||||
- Add a **Redirect URI** of type `Strict` `Authorization` as `https://<forgejo.company>/user/oauth2/authentik/callback`.
|
||||
- Select any available signing key.
|
||||
- Under **Advanced protocol settings** > **Selected Scopes**, add `authentik default OAuth Mapping: OpenID 'entitlements'`.
|
||||
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/bindings-overview/) (policy, group, or user) to manage the listing and access to applications on a user's **Application Dashboard** page.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user