Compare commits

...

12 Commits

Author SHA1 Message Date
82b5274b15 release: 2023.10.3 2023-11-09 18:37:22 +01:00
af56ce3d78 core: fix worker beat toggle inverted (cherry-pick #7508) (#7509)
core: fix worker beat toggle inverted (#7508)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-09 18:36:56 +01:00
f5c6e7aeb0 Web: bugfix: broken backchannel selector (cherry-pick #7480) (#7507)
Web: bugfix: broken backchannel selector (#7480)

* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.

* web: rollback dependabot's upgrade of context

The most frustrating part of this is that I RAN THIS, dammit, with the updated
context and the current Wizard, and it finished the End-to-End tests without
complaint.

* web: bugfix: broken backchannel selector

There were two bugs here, both of them introduced by me because I didn't understand the
system well enough the first time through, and because I didn't test thoroughly enough.

The first is that I was calling the wrong confirmation code; the resulting syntax survived
because `confirm()` is actually a legitimate function call in the context of the DOM Window,
a legacy survivor similar to `alert()` but with a yes/no return value. Bleah.

The second is that the confirm code doesn't appear to pass back a dictionary with the
`{ items: Array<Provider> }` list, it passes back just the `items` as an Array.

Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
2023-11-09 17:58:38 +01:00
3809400e93 events: fix gdpr compliance always running (cherry-pick #7491) (#7505)
events: fix gdpr compliance always running

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-11-09 17:57:25 +01:00
1def9865cf web/flows: attempt to fix bitwareden android compatibility (cherry-pick #7455) (#7457)
web/flows: attempt to fix bitwareden android compatibility (#7455)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-06 23:58:44 +01:00
3716298639 sources/oauth: fix patreon (cherry-pick #7454) (#7456)
sources/oauth: fix patreon (#7454)

* web/admin: add note for potentially confusing consumer key/secret



* sources/oauth: fix patreon default scopes



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-06 16:36:22 +01:00
c16317d7cf providers/proxy: fix closed redis client (cherry-pick #7385) (#7429)
providers/proxy: fix closed redis client (#7385)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 15:46:17 +01:00
bbb8fa8269 ci: explicitly give write permissions to packages (cherry-pick #7428) (#7430)
ci: explicitly give write permissions to packages (#7428)

* ci: explicitly give write permissions to packages



* run full CI on cherry-picks



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 15:46:00 +01:00
e4c251a178 web/admin: fix html error on oauth2 provider page (cherry-pick #7384) (#7424)
web/admin: fix html error on oauth2 provider page (#7384)

* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.

* \# Details

Extra `>` symbol screwed up the reading of the rest of the component.  Unfortunately,
too many fields in an input are optional, so it was easy for this bug to bypass any
checks by the validators.  I should have caught it myself, though.

Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
2023-11-03 13:17:26 +01:00
0fefd5f522 stages/email: fix duplicate querystring encoding (cherry-pick #7386) (#7425)
stages/email: fix duplicate querystring encoding (#7386)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 13:17:18 +01:00
88057db0b0 providers/oauth2: set auth_via for token and other endpoints (cherry-pick #7417) (#7427)
providers/oauth2: set auth_via for token and other endpoints (#7417)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 13:17:10 +01:00
91cb6c9beb root: Improve multi arch Docker image build speed (cherry-pick #7355) (#7426)
root: Improve multi arch Docker image build speed (#7355)

* Improve multi arch Docker image build speed

Use only host architecture for GeoIP database update and for Go cross-compilation

* Speedup Go multi-arch compilation for other images

* Speedup multi-arch ldap image build

Co-authored-by: Philipp Kolberg <39984529+PKizzle@users.noreply.github.com>
2023-11-03 13:16:54 +01:00
29 changed files with 117 additions and 89 deletions

View File

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

View File

@ -11,6 +11,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
env: env:
POSTGRES_DB: authentik POSTGRES_DB: authentik
@ -185,6 +186,8 @@ jobs:
build: build:
needs: ci-core-mark needs: ci-core-mark
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
packages: write
timeout-minutes: 120 timeout-minutes: 120
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -235,6 +238,8 @@ jobs:
build-arm64: build-arm64:
needs: ci-core-mark needs: ci-core-mark
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
packages: write
timeout-minutes: 120 timeout-minutes: 120
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@ -9,6 +9,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
jobs: jobs:
lint-golint: lint-golint:
@ -65,6 +66,8 @@ jobs:
- ldap - ldap
- radius - radius
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
packages: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

View File

@ -9,6 +9,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
jobs: jobs:
lint-eslint: lint-eslint:

View File

@ -9,6 +9,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
jobs: jobs:
lint-prettier: lint-prettier:

View File

@ -7,6 +7,8 @@ on:
jobs: jobs:
build-server: build-server:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
packages: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
@ -52,6 +54,8 @@ jobs:
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
build-outpost: build-outpost:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
packages: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:

View File

@ -35,7 +35,14 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build RUN npm run build
# Stage 3: Build go proxy # Stage 3: Build go proxy
FROM docker.io/golang:1.21.3-bookworm AS go-builder FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS go-builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io WORKDIR /go/src/goauthentik.io
@ -57,10 +64,10 @@ ENV CGO_ENABLED=0
RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/root/.cache/go-build \
go build -o /go/authentik ./cmd/server GOARM="${TARGETVARIANT#v}" go build -o /go/authentik ./cmd/server
# Stage 4: MaxMind GeoIP # Stage 4: MaxMind GeoIP
FROM ghcr.io/maxmind/geoipupdate:v6.0 as geoip FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v6.0 as geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City" ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City"
ENV GEOIPUPDATE_VERBOSE="true" ENV GEOIPUPDATE_VERBOSE="true"

View File

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

View File

@ -17,9 +17,15 @@ class Command(BaseCommand):
"""Run worker""" """Run worker"""
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument("-b", "--beat", action="store_true") parser.add_argument(
"-b",
"--beat",
action="store_false",
help="When set, this worker will _not_ run Beat (scheduled) tasks",
)
def handle(self, **options): def handle(self, **options):
LOGGER.debug("Celery options", **options)
close_old_connections() close_old_connections()
if CONFIG.get_bool("remote_debug"): if CONFIG.get_bool("remote_debug"):
import debugpy import debugpy

View File

@ -13,6 +13,7 @@ from authentik.events.tasks import event_notification_handler, gdpr_cleanup
from authentik.flows.models import Stage from authentik.flows.models import Stage
from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.config import CONFIG
from authentik.stages.invitation.models import Invitation from authentik.stages.invitation.models import Invitation
from authentik.stages.invitation.signals import invitation_used from authentik.stages.invitation.signals import invitation_used
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
@ -92,4 +93,5 @@ def event_post_save_notification(sender, instance: Event, **_):
@receiver(pre_delete, sender=User) @receiver(pre_delete, sender=User)
def event_user_pre_delete_cleanup(sender, instance: User, **_): def event_user_pre_delete_cleanup(sender, instance: User, **_):
"""If gdpr_compliance is enabled, remove all the user's events""" """If gdpr_compliance is enabled, remove all the user's events"""
if CONFIG.get_bool("gdpr_compliance", True):
gdpr_cleanup.delay(instance.pk) gdpr_cleanup.delay(instance.pk)

View File

@ -188,6 +188,7 @@ def authenticate_provider(request: HttpRequest) -> Optional[OAuth2Provider]:
if client_id != provider.client_id or client_secret != provider.client_secret: if client_id != provider.client_id or client_secret != provider.client_secret:
LOGGER.debug("(basic) Provider for basic auth does not exist") LOGGER.debug("(basic) Provider for basic auth does not exist")
return None return None
CTX_AUTH_VIA.set("oauth_client_secret")
return provider return provider

View File

@ -17,6 +17,7 @@ from jwt import PyJWK, PyJWT, PyJWTError, decode
from sentry_sdk.hub import Hub from sentry_sdk.hub import Hub
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.core.middleware import CTX_AUTH_VIA
from authentik.core.models import ( from authentik.core.models import (
USER_ATTRIBUTE_EXPIRES, USER_ATTRIBUTE_EXPIRES,
USER_ATTRIBUTE_GENERATED, USER_ATTRIBUTE_GENERATED,
@ -448,6 +449,7 @@ class TokenView(View):
if not self.provider: if not self.provider:
LOGGER.warning("OAuth2Provider does not exist", client_id=client_id) LOGGER.warning("OAuth2Provider does not exist", client_id=client_id)
raise TokenError("invalid_client") raise TokenError("invalid_client")
CTX_AUTH_VIA.set("oauth_client_secret")
self.params = TokenParams.parse(request, self.provider, client_id, client_secret) self.params = TokenParams.parse(request, self.provider, client_id, client_secret)
with Hub.current.start_span( with Hub.current.start_span(

View File

@ -12,8 +12,9 @@ class PatreonOAuthRedirect(OAuthRedirect):
"""Patreon OAuth2 Redirect""" """Patreon OAuth2 Redirect"""
def get_additional_parameters(self, source: OAuthSource): # pragma: no cover def get_additional_parameters(self, source: OAuthSource): # pragma: no cover
# https://docs.patreon.com/#scopes
return { return {
"scope": ["openid", "email", "profile"], "scope": ["identity", "identity[email]"],
} }

View File

@ -52,17 +52,13 @@ class EmailStageView(ChallengeStageView):
kwargs={"flow_slug": self.executor.flow.slug}, kwargs={"flow_slug": self.executor.flow.slug},
) )
# Parse query string from current URL (full query string) # Parse query string from current URL (full query string)
query_params = QueryDict(self.request.META.get("QUERY_STRING", ""), mutable=True) # this view is only run within a flow executor, where we need to get the query string
# from the query= parameter (double encoded); but for the redirect
# we need to expand it since it'll go through the flow interface
query_params = QueryDict(self.request.GET.get(QS_QUERY), mutable=True)
query_params.pop(QS_KEY_TOKEN, None) query_params.pop(QS_KEY_TOKEN, None)
# Check for nested query string used by flow executor, and remove any
# kind of flow token from that
if QS_QUERY in query_params:
inner_query_params = QueryDict(query_params.get(QS_QUERY), mutable=True)
inner_query_params.pop(QS_KEY_TOKEN, None)
query_params[QS_QUERY] = inner_query_params.urlencode()
query_params.update(kwargs) query_params.update(kwargs)
print(query_params)
full_url = base_url full_url = base_url
if len(query_params) > 0: if len(query_params) > 0:
full_url = f"{full_url}?{query_params.urlencode()}" full_url = f"{full_url}?{query_params.urlencode()}"

View File

@ -259,7 +259,7 @@ class TestEmailStage(FlowTestCase):
session.save() session.save()
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
url += "?foo=bar" url += "?query=" + urlencode({"foo": "bar"})
request = self.factory.get(url) request = self.factory.get(url)
stage_view = EmailStageView( stage_view = EmailStageView(
FlowExecutorView( FlowExecutorView(
@ -273,31 +273,3 @@ class TestEmailStage(FlowTestCase):
stage_view.get_full_url(**{QS_KEY_TOKEN: token}), stage_view.get_full_url(**{QS_KEY_TOKEN: token}),
f"http://testserver/if/flow/{self.flow.slug}/?foo=bar&flow_token={token}", f"http://testserver/if/flow/{self.flow.slug}/?foo=bar&flow_token={token}",
) )
def test_url_existing_params_nested(self):
"""Test to ensure that URL params are preserved in the URL being sent (including nested)"""
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
session = self.client.session
session[SESSION_KEY_PLAN] = plan
session.save()
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
url += "?foo=bar&"
url += "query=" + urlencode({"nested": "value"})
request = self.factory.get(url)
stage_view = EmailStageView(
FlowExecutorView(
request=request,
flow=self.flow,
),
request=request,
)
token = generate_id()
self.assertEqual(
stage_view.get_full_url(**{QS_KEY_TOKEN: token}),
(
f"http://testserver/if/flow/{self.flow.slug}"
f"/?foo=bar&query=nested%3Dvalue&flow_token={token}"
),
)

View File

@ -32,7 +32,7 @@ services:
volumes: volumes:
- redis:/data - redis:/data
server: server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.2} image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
restart: unless-stopped restart: unless-stopped
command: server command: server
environment: environment:
@ -53,7 +53,7 @@ services:
- postgresql - postgresql
- redis - redis
worker: worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.2} image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
restart: unless-stopped restart: unless-stopped
command: worker command: worker
environment: environment:

View File

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

View File

@ -131,7 +131,6 @@ func (a *Application) Logout(ctx context.Context, filter func(c Claims) bool) er
} }
if rs, ok := a.sessions.(*redisstore.RedisStore); ok { if rs, ok := a.sessions.(*redisstore.RedisStore); ok {
client := rs.Client() client := rs.Client()
defer client.Close()
keys, err := client.Keys(ctx, fmt.Sprintf("%s*", RedisKeyPrefix)).Result() keys, err := client.Keys(ctx, fmt.Sprintf("%s*", RedisKeyPrefix)).Result()
if err != nil { if err != nil {
return err return err

View File

@ -1,5 +1,12 @@
# Stage 1: Build # Stage 1: Build
FROM docker.io/golang:1.21.3-bookworm AS builder FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io WORKDIR /go/src/goauthentik.io
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
COPY . . COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/root/.cache/go-build \
go build -o /go/ldap ./cmd/ldap GOARM="${TARGETVARIANT#v}" go build -o /go/ldap ./cmd/ldap
# Stage 2: Run # Stage 2: Run
FROM gcr.io/distroless/static-debian11:debug FROM gcr.io/distroless/static-debian11:debug

View File

@ -15,7 +15,14 @@ COPY web .
RUN npm run build-proxy RUN npm run build-proxy
# Stage 2: Build # Stage 2: Build
FROM docker.io/golang:1.21.3-bookworm AS builder FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io WORKDIR /go/src/goauthentik.io
@ -29,7 +36,7 @@ ENV CGO_ENABLED=0
COPY . . COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/root/.cache/go-build \
go build -o /go/proxy ./cmd/proxy GOARM="${TARGETVARIANT#v}" go build -o /go/proxy ./cmd/proxy
# Stage 3: Run # Stage 3: Run
FROM gcr.io/distroless/static-debian11:debug FROM gcr.io/distroless/static-debian11:debug

View File

@ -113,7 +113,7 @@ filterwarnings = [
[tool.poetry] [tool.poetry]
name = "authentik" name = "authentik"
version = "2023.10.2" version = "2023.10.3"
description = "" description = ""
authors = ["authentik Team <hello@goauthentik.io>"] authors = ["authentik Team <hello@goauthentik.io>"]

View File

@ -1,5 +1,12 @@
# Stage 1: Build # Stage 1: Build
FROM docker.io/golang:1.21.3-bookworm AS builder FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io WORKDIR /go/src/goauthentik.io
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
COPY . . COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/root/.cache/go-build \
go build -o /go/radius ./cmd/radius GOARM="${TARGETVARIANT#v}" go build -o /go/radius ./cmd/radius
# Stage 2: Run # Stage 2: Run
FROM gcr.io/distroless/static-debian11:debug FROM gcr.io/distroless/static-debian11:debug

View File

@ -1,7 +1,7 @@
openapi: 3.0.3 openapi: 3.0.3
info: info:
title: authentik title: authentik
version: 2023.10.2 version: 2023.10.3
description: Making authentication simple. description: Making authentication simple.
contact: contact:
email: hello@goauthentik.io email: hello@goauthentik.io

View File

@ -116,7 +116,7 @@ export class ApplicationForm extends ModelForm<Application, string> {
return app; return app;
} }
handleConfirmBackchannelProviders({ items }: { items: Provider[] }) { handleConfirmBackchannelProviders(items: Provider[]) {
this.backchannelProviders = items; this.backchannelProviders = items;
this.requestUpdate(); this.requestUpdate();
return Promise.resolve(); return Promise.resolve();

View File

@ -63,7 +63,7 @@ export class AkBackchannelProvidersInput extends AKElement {
return html` return html`
<ak-form-element-horizontal label=${this.label} name=${name}> <ak-form-element-horizontal label=${this.label} name=${name}>
<div class="pf-c-input-group"> <div class="pf-c-input-group">
<ak-provider-select-table ?backchannelOnly=${true} .confirm=${confirm}> <ak-provider-select-table ?backchannelOnly=${true} .confirm=${this.confirm}>
<button slot="trigger" class="pf-c-button pf-m-control" type="button"> <button slot="trigger" class="pf-c-button pf-m-control" type="button">
${this.tooltip ? this.tooltip : nothing} ${this.tooltip ? this.tooltip : nothing}
<i class="fas fa-plus" aria-hidden="true"></i> <i class="fas fa-plus" aria-hidden="true"></i>

View File

@ -334,13 +334,14 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
)} )}
> >
</ak-radio-input> </ak-radio-input>
<ak-switch-input name="includeClaimsInIdToken"> <ak-switch-input
name="includeClaimsInIdToken"
label=${msg("Include claims in id_token")} label=${msg("Include claims in id_token")}
?checked=${first(provider?.includeClaimsInIdToken, true)} ?checked=${first(provider?.includeClaimsInIdToken, true)}
help=${msg( help=${msg(
"Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.", "Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.",
)}></ak-switch-input )}
> ></ak-switch-input>
<ak-radio-input <ak-radio-input
name="issuerMode" name="issuerMode"
label=${msg("Issuer mode")} label=${msg("Issuer mode")}

View File

@ -386,6 +386,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
<p class="pf-c-form__helper-text">${msg("Also known as Client ID.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${msg("Consumer secret")} label=${msg("Consumer secret")}
@ -394,6 +395,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
name="consumerSecret" name="consumerSecret"
> >
<textarea class="pf-c-form-control"></textarea> <textarea class="pf-c-form-control"></textarea>
<p class="pf-c-form__helper-text">${msg("Also known as Client Secret.")}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Scopes")} name="additionalScopes"> <ak-form-element-horizontal label=${msg("Scopes")} name="additionalScopes">
<input <input

View File

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

View File

@ -80,11 +80,12 @@ export class IdentificationStage extends BaseStage<
} }
createHelperForm(): void { createHelperForm(): void {
const compatMode = "ShadyDOM" in window;
this.form = document.createElement("form"); this.form = document.createElement("form");
document.documentElement.appendChild(this.form); document.documentElement.appendChild(this.form);
// Only add the additional username input if we're in a shadow dom // Only add the additional username input if we're in a shadow dom
// otherwise it just confuses browsers // otherwise it just confuses browsers
if (!("ShadyDOM" in window)) { if (!compatMode) {
// This is a workaround for the fact that we're in a shadow dom // This is a workaround for the fact that we're in a shadow dom
// adapted from https://github.com/home-assistant/frontend/issues/3133 // adapted from https://github.com/home-assistant/frontend/issues/3133
const username = document.createElement("input"); const username = document.createElement("input");
@ -104,6 +105,8 @@ export class IdentificationStage extends BaseStage<
}; };
this.form.appendChild(username); this.form.appendChild(username);
} }
// Only add the password field when we don't already show a password field
if (!compatMode && !this.challenge.passwordFields) {
const password = document.createElement("input"); const password = document.createElement("input");
password.setAttribute("type", "password"); password.setAttribute("type", "password");
password.setAttribute("name", "password"); password.setAttribute("name", "password");
@ -128,6 +131,7 @@ export class IdentificationStage extends BaseStage<
}); });
}; };
this.form.appendChild(password); this.form.appendChild(password);
}
const totp = document.createElement("input"); const totp = document.createElement("input");
totp.setAttribute("type", "text"); totp.setAttribute("type", "text");
totp.setAttribute("name", "code"); totp.setAttribute("name", "code");