Compare commits
	
		
			12 Commits
		
	
	
		
			version/20
			...
			version/20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 82b5274b15 | |||
| af56ce3d78 | |||
| f5c6e7aeb0 | |||
| 3809400e93 | |||
| 1def9865cf | |||
| 3716298639 | |||
| c16317d7cf | |||
| bbb8fa8269 | |||
| e4c251a178 | |||
| 0fefd5f522 | |||
| 88057db0b0 | |||
| 91cb6c9beb | 
@ -1,5 +1,5 @@
 | 
			
		||||
[bumpversion]
 | 
			
		||||
current_version = 2023.10.2
 | 
			
		||||
current_version = 2023.10.3
 | 
			
		||||
tag = True
 | 
			
		||||
commit = True
 | 
			
		||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							@ -11,6 +11,7 @@ on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
      - version-*
 | 
			
		||||
 | 
			
		||||
env:
 | 
			
		||||
  POSTGRES_DB: authentik
 | 
			
		||||
@ -185,6 +186,8 @@ jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    needs: ci-core-mark
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      packages: write
 | 
			
		||||
    timeout-minutes: 120
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
@ -235,6 +238,8 @@ jobs:
 | 
			
		||||
  build-arm64:
 | 
			
		||||
    needs: ci-core-mark
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      packages: write
 | 
			
		||||
    timeout-minutes: 120
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							@ -9,6 +9,7 @@ on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
      - version-*
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  lint-golint:
 | 
			
		||||
@ -65,6 +66,8 @@ jobs:
 | 
			
		||||
          - ldap
 | 
			
		||||
          - radius
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      packages: write
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
        with:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/workflows/ci-web.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/ci-web.yml
									
									
									
									
										vendored
									
									
								
							@ -9,6 +9,7 @@ on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
      - version-*
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  lint-eslint:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/workflows/ci-website.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/ci-website.yml
									
									
									
									
										vendored
									
									
								
							@ -9,6 +9,7 @@ on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
      - version-*
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  lint-prettier:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								.github/workflows/release-publish.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/release-publish.yml
									
									
									
									
										vendored
									
									
								
							@ -7,6 +7,8 @@ on:
 | 
			
		||||
jobs:
 | 
			
		||||
  build-server:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      packages: write
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v4
 | 
			
		||||
      - name: Set up QEMU
 | 
			
		||||
@ -52,6 +54,8 @@ jobs:
 | 
			
		||||
            VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
 | 
			
		||||
  build-outpost:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    permissions:
 | 
			
		||||
      packages: write
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Dockerfile
									
									
									
									
									
								
							@ -35,7 +35,14 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
 | 
			
		||||
RUN npm run build
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
@ -57,10 +64,10 @@ ENV CGO_ENABLED=0
 | 
			
		||||
 | 
			
		||||
RUN --mount=type=cache,target=/go/pkg/mod \
 | 
			
		||||
    --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
 | 
			
		||||
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_VERBOSE="true"
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
from os import environ
 | 
			
		||||
from typing import Optional
 | 
			
		||||
 | 
			
		||||
__version__ = "2023.10.2"
 | 
			
		||||
__version__ = "2023.10.3"
 | 
			
		||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,9 +17,15 @@ class Command(BaseCommand):
 | 
			
		||||
    """Run worker"""
 | 
			
		||||
 | 
			
		||||
    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):
 | 
			
		||||
        LOGGER.debug("Celery options", **options)
 | 
			
		||||
        close_old_connections()
 | 
			
		||||
        if CONFIG.get_bool("remote_debug"):
 | 
			
		||||
            import debugpy
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@ from authentik.events.tasks import event_notification_handler, gdpr_cleanup
 | 
			
		||||
from authentik.flows.models import Stage
 | 
			
		||||
from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan
 | 
			
		||||
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.signals import invitation_used
 | 
			
		||||
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)
 | 
			
		||||
def event_user_pre_delete_cleanup(sender, instance: User, **_):
 | 
			
		||||
    """If gdpr_compliance is enabled, remove all the user's events"""
 | 
			
		||||
    gdpr_cleanup.delay(instance.pk)
 | 
			
		||||
    if CONFIG.get_bool("gdpr_compliance", True):
 | 
			
		||||
        gdpr_cleanup.delay(instance.pk)
 | 
			
		||||
 | 
			
		||||
@ -188,6 +188,7 @@ def authenticate_provider(request: HttpRequest) -> Optional[OAuth2Provider]:
 | 
			
		||||
    if client_id != provider.client_id or client_secret != provider.client_secret:
 | 
			
		||||
        LOGGER.debug("(basic) Provider for basic auth does not exist")
 | 
			
		||||
        return None
 | 
			
		||||
    CTX_AUTH_VIA.set("oauth_client_secret")
 | 
			
		||||
    return provider
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@ from jwt import PyJWK, PyJWT, PyJWTError, decode
 | 
			
		||||
from sentry_sdk.hub import Hub
 | 
			
		||||
from structlog.stdlib import get_logger
 | 
			
		||||
 | 
			
		||||
from authentik.core.middleware import CTX_AUTH_VIA
 | 
			
		||||
from authentik.core.models import (
 | 
			
		||||
    USER_ATTRIBUTE_EXPIRES,
 | 
			
		||||
    USER_ATTRIBUTE_GENERATED,
 | 
			
		||||
@ -448,6 +449,7 @@ class TokenView(View):
 | 
			
		||||
                if not self.provider:
 | 
			
		||||
                    LOGGER.warning("OAuth2Provider does not exist", client_id=client_id)
 | 
			
		||||
                    raise TokenError("invalid_client")
 | 
			
		||||
                CTX_AUTH_VIA.set("oauth_client_secret")
 | 
			
		||||
                self.params = TokenParams.parse(request, self.provider, client_id, client_secret)
 | 
			
		||||
 | 
			
		||||
            with Hub.current.start_span(
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,9 @@ class PatreonOAuthRedirect(OAuthRedirect):
 | 
			
		||||
    """Patreon OAuth2 Redirect"""
 | 
			
		||||
 | 
			
		||||
    def get_additional_parameters(self, source: OAuthSource):  # pragma: no cover
 | 
			
		||||
        # https://docs.patreon.com/#scopes
 | 
			
		||||
        return {
 | 
			
		||||
            "scope": ["openid", "email", "profile"],
 | 
			
		||||
            "scope": ["identity", "identity[email]"],
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -52,17 +52,13 @@ class EmailStageView(ChallengeStageView):
 | 
			
		||||
            kwargs={"flow_slug": self.executor.flow.slug},
 | 
			
		||||
        )
 | 
			
		||||
        # 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)
 | 
			
		||||
 | 
			
		||||
        # 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)
 | 
			
		||||
        print(query_params)
 | 
			
		||||
        full_url = base_url
 | 
			
		||||
        if len(query_params) > 0:
 | 
			
		||||
            full_url = f"{full_url}?{query_params.urlencode()}"
 | 
			
		||||
 | 
			
		||||
@ -259,7 +259,7 @@ class TestEmailStage(FlowTestCase):
 | 
			
		||||
        session.save()
 | 
			
		||||
 | 
			
		||||
        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)
 | 
			
		||||
        stage_view = EmailStageView(
 | 
			
		||||
            FlowExecutorView(
 | 
			
		||||
@ -273,31 +273,3 @@ class TestEmailStage(FlowTestCase):
 | 
			
		||||
            stage_view.get_full_url(**{QS_KEY_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}"
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ services:
 | 
			
		||||
    volumes:
 | 
			
		||||
      - redis:/data
 | 
			
		||||
  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
 | 
			
		||||
    command: server
 | 
			
		||||
    environment:
 | 
			
		||||
@ -53,7 +53,7 @@ services:
 | 
			
		||||
      - postgresql
 | 
			
		||||
      - redis
 | 
			
		||||
  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
 | 
			
		||||
    command: worker
 | 
			
		||||
    environment:
 | 
			
		||||
 | 
			
		||||
@ -29,4 +29,4 @@ func UserAgent() string {
 | 
			
		||||
	return fmt.Sprintf("authentik@%s", FullVersion())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const VERSION = "2023.10.2"
 | 
			
		||||
const VERSION = "2023.10.3"
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
		client := rs.Client()
 | 
			
		||||
		defer client.Close()
 | 
			
		||||
		keys, err := client.Keys(ctx, fmt.Sprintf("%s*", RedisKeyPrefix)).Result()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,12 @@
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
 | 
			
		||||
COPY . .
 | 
			
		||||
RUN --mount=type=cache,target=/go/pkg/mod \
 | 
			
		||||
    --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
 | 
			
		||||
FROM gcr.io/distroless/static-debian11:debug
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,14 @@ COPY web .
 | 
			
		||||
RUN npm run build-proxy
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
@ -29,7 +36,7 @@ ENV CGO_ENABLED=0
 | 
			
		||||
COPY . .
 | 
			
		||||
RUN --mount=type=cache,target=/go/pkg/mod \
 | 
			
		||||
    --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
 | 
			
		||||
FROM gcr.io/distroless/static-debian11:debug
 | 
			
		||||
 | 
			
		||||
@ -113,7 +113,7 @@ filterwarnings = [
 | 
			
		||||
 | 
			
		||||
[tool.poetry]
 | 
			
		||||
name = "authentik"
 | 
			
		||||
version = "2023.10.2"
 | 
			
		||||
version = "2023.10.3"
 | 
			
		||||
description = ""
 | 
			
		||||
authors = ["authentik Team <hello@goauthentik.io>"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,12 @@
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
 | 
			
		||||
COPY . .
 | 
			
		||||
RUN --mount=type=cache,target=/go/pkg/mod \
 | 
			
		||||
    --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
 | 
			
		||||
FROM gcr.io/distroless/static-debian11:debug
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
openapi: 3.0.3
 | 
			
		||||
info:
 | 
			
		||||
  title: authentik
 | 
			
		||||
  version: 2023.10.2
 | 
			
		||||
  version: 2023.10.3
 | 
			
		||||
  description: Making authentication simple.
 | 
			
		||||
  contact:
 | 
			
		||||
    email: hello@goauthentik.io
 | 
			
		||||
 | 
			
		||||
@ -116,7 +116,7 @@ export class ApplicationForm extends ModelForm<Application, string> {
 | 
			
		||||
        return app;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handleConfirmBackchannelProviders({ items }: { items: Provider[] }) {
 | 
			
		||||
    handleConfirmBackchannelProviders(items: Provider[]) {
 | 
			
		||||
        this.backchannelProviders = items;
 | 
			
		||||
        this.requestUpdate();
 | 
			
		||||
        return Promise.resolve();
 | 
			
		||||
 | 
			
		||||
@ -63,7 +63,7 @@ export class AkBackchannelProvidersInput extends AKElement {
 | 
			
		||||
        return html`
 | 
			
		||||
            <ak-form-element-horizontal label=${this.label} name=${name}>
 | 
			
		||||
                <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">
 | 
			
		||||
                            ${this.tooltip ? this.tooltip : nothing}
 | 
			
		||||
                            <i class="fas fa-plus" aria-hidden="true"></i>
 | 
			
		||||
 | 
			
		||||
@ -334,13 +334,14 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
 | 
			
		||||
                        )}
 | 
			
		||||
                    >
 | 
			
		||||
                    </ak-radio-input>
 | 
			
		||||
                    <ak-switch-input name="includeClaimsInIdToken">
 | 
			
		||||
                    <ak-switch-input
 | 
			
		||||
                        name="includeClaimsInIdToken"
 | 
			
		||||
                        label=${msg("Include claims in id_token")}
 | 
			
		||||
                        ?checked=${first(provider?.includeClaimsInIdToken, true)}
 | 
			
		||||
                        help=${msg(
 | 
			
		||||
                            "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
 | 
			
		||||
                        name="issuerMode"
 | 
			
		||||
                        label=${msg("Issuer mode")}
 | 
			
		||||
 | 
			
		||||
@ -386,6 +386,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
 | 
			
		||||
                            class="pf-c-form-control"
 | 
			
		||||
                            required
 | 
			
		||||
                        />
 | 
			
		||||
                        <p class="pf-c-form__helper-text">${msg("Also known as Client ID.")}</p>
 | 
			
		||||
                    </ak-form-element-horizontal>
 | 
			
		||||
                    <ak-form-element-horizontal
 | 
			
		||||
                        label=${msg("Consumer secret")}
 | 
			
		||||
@ -394,6 +395,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
 | 
			
		||||
                        name="consumerSecret"
 | 
			
		||||
                    >
 | 
			
		||||
                        <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 label=${msg("Scopes")} name="additionalScopes">
 | 
			
		||||
                        <input
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
 | 
			
		||||
export const ERROR_CLASS = "pf-m-danger";
 | 
			
		||||
export const PROGRESS_CLASS = "pf-m-in-progress";
 | 
			
		||||
export const CURRENT_CLASS = "pf-m-current";
 | 
			
		||||
export const VERSION = "2023.10.2";
 | 
			
		||||
export const VERSION = "2023.10.3";
 | 
			
		||||
export const TITLE_DEFAULT = "authentik";
 | 
			
		||||
export const ROUTE_SEPARATOR = ";";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -80,11 +80,12 @@ export class IdentificationStage extends BaseStage<
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createHelperForm(): void {
 | 
			
		||||
        const compatMode = "ShadyDOM" in window;
 | 
			
		||||
        this.form = document.createElement("form");
 | 
			
		||||
        document.documentElement.appendChild(this.form);
 | 
			
		||||
        // Only add the additional username input if we're in a shadow dom
 | 
			
		||||
        // 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
 | 
			
		||||
            // adapted from https://github.com/home-assistant/frontend/issues/3133
 | 
			
		||||
            const username = document.createElement("input");
 | 
			
		||||
@ -104,30 +105,33 @@ export class IdentificationStage extends BaseStage<
 | 
			
		||||
            };
 | 
			
		||||
            this.form.appendChild(username);
 | 
			
		||||
        }
 | 
			
		||||
        const password = document.createElement("input");
 | 
			
		||||
        password.setAttribute("type", "password");
 | 
			
		||||
        password.setAttribute("name", "password");
 | 
			
		||||
        password.setAttribute("autocomplete", "current-password");
 | 
			
		||||
        password.onkeyup = (ev: KeyboardEvent) => {
 | 
			
		||||
            if (ev.key == "Enter") {
 | 
			
		||||
                this.submitForm(ev);
 | 
			
		||||
            }
 | 
			
		||||
            const el = ev.target as HTMLInputElement;
 | 
			
		||||
            // Because the password field is not actually on this page,
 | 
			
		||||
            // and we want to 'prefill' the password for the user,
 | 
			
		||||
            // save it globally
 | 
			
		||||
            PasswordManagerPrefill.password = el.value;
 | 
			
		||||
            // Because password managers fill username, then password,
 | 
			
		||||
            // we need to re-focus the uid_field here too
 | 
			
		||||
            (this.shadowRoot || this)
 | 
			
		||||
                .querySelectorAll<HTMLInputElement>("input[name=uidField]")
 | 
			
		||||
                .forEach((input) => {
 | 
			
		||||
                    // Because we assume only one input field exists that matches this
 | 
			
		||||
                    // call focus so the user can press enter
 | 
			
		||||
                    input.focus();
 | 
			
		||||
                });
 | 
			
		||||
        };
 | 
			
		||||
        this.form.appendChild(password);
 | 
			
		||||
        // Only add the password field when we don't already show a password field
 | 
			
		||||
        if (!compatMode && !this.challenge.passwordFields) {
 | 
			
		||||
            const password = document.createElement("input");
 | 
			
		||||
            password.setAttribute("type", "password");
 | 
			
		||||
            password.setAttribute("name", "password");
 | 
			
		||||
            password.setAttribute("autocomplete", "current-password");
 | 
			
		||||
            password.onkeyup = (ev: KeyboardEvent) => {
 | 
			
		||||
                if (ev.key == "Enter") {
 | 
			
		||||
                    this.submitForm(ev);
 | 
			
		||||
                }
 | 
			
		||||
                const el = ev.target as HTMLInputElement;
 | 
			
		||||
                // Because the password field is not actually on this page,
 | 
			
		||||
                // and we want to 'prefill' the password for the user,
 | 
			
		||||
                // save it globally
 | 
			
		||||
                PasswordManagerPrefill.password = el.value;
 | 
			
		||||
                // Because password managers fill username, then password,
 | 
			
		||||
                // we need to re-focus the uid_field here too
 | 
			
		||||
                (this.shadowRoot || this)
 | 
			
		||||
                    .querySelectorAll<HTMLInputElement>("input[name=uidField]")
 | 
			
		||||
                    .forEach((input) => {
 | 
			
		||||
                        // Because we assume only one input field exists that matches this
 | 
			
		||||
                        // call focus so the user can press enter
 | 
			
		||||
                        input.focus();
 | 
			
		||||
                    });
 | 
			
		||||
            };
 | 
			
		||||
            this.form.appendChild(password);
 | 
			
		||||
        }
 | 
			
		||||
        const totp = document.createElement("input");
 | 
			
		||||
        totp.setAttribute("type", "text");
 | 
			
		||||
        totp.setAttribute("name", "code");
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user