Compare commits
12 Commits
safari-adm
...
version/20
Author | SHA1 | Date | |
---|---|---|---|
82b5274b15 | |||
af56ce3d78 | |||
f5c6e7aeb0 | |||
3809400e93 | |||
1def9865cf | |||
3716298639 | |||
c16317d7cf | |||
bbb8fa8269 | |||
e4c251a178 | |||
0fefd5f522 | |||
88057db0b0 | |||
91cb6c9beb |
@ -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+)
|
||||||
|
5
.github/workflows/ci-main.yml
vendored
5
.github/workflows/ci-main.yml
vendored
@ -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
|
||||||
|
3
.github/workflows/ci-outpost.yml
vendored
3
.github/workflows/ci-outpost.yml
vendored
@ -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:
|
||||||
|
1
.github/workflows/ci-web.yml
vendored
1
.github/workflows/ci-web.yml
vendored
@ -9,6 +9,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
- version-*
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-eslint:
|
lint-eslint:
|
||||||
|
1
.github/workflows/ci-website.yml
vendored
1
.github/workflows/ci-website.yml
vendored
@ -9,6 +9,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
- version-*
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-prettier:
|
lint-prettier:
|
||||||
|
4
.github/workflows/release-publish.yml
vendored
4
.github/workflows/release-publish.yml
vendored
@ -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:
|
||||||
|
13
Dockerfile
13
Dockerfile
@ -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"
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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"""
|
||||||
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:
|
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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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(
|
||||||
|
@ -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]"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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()}"
|
||||||
|
@ -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}"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
@ -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:
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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>"]
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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>
|
||||||
|
@ -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")}
|
||||||
|
@ -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
|
||||||
|
@ -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 = ";";
|
||||||
|
|
||||||
|
@ -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,30 +105,33 @@ export class IdentificationStage extends BaseStage<
|
|||||||
};
|
};
|
||||||
this.form.appendChild(username);
|
this.form.appendChild(username);
|
||||||
}
|
}
|
||||||
const password = document.createElement("input");
|
// Only add the password field when we don't already show a password field
|
||||||
password.setAttribute("type", "password");
|
if (!compatMode && !this.challenge.passwordFields) {
|
||||||
password.setAttribute("name", "password");
|
const password = document.createElement("input");
|
||||||
password.setAttribute("autocomplete", "current-password");
|
password.setAttribute("type", "password");
|
||||||
password.onkeyup = (ev: KeyboardEvent) => {
|
password.setAttribute("name", "password");
|
||||||
if (ev.key == "Enter") {
|
password.setAttribute("autocomplete", "current-password");
|
||||||
this.submitForm(ev);
|
password.onkeyup = (ev: KeyboardEvent) => {
|
||||||
}
|
if (ev.key == "Enter") {
|
||||||
const el = ev.target as HTMLInputElement;
|
this.submitForm(ev);
|
||||||
// Because the password field is not actually on this page,
|
}
|
||||||
// and we want to 'prefill' the password for the user,
|
const el = ev.target as HTMLInputElement;
|
||||||
// save it globally
|
// Because the password field is not actually on this page,
|
||||||
PasswordManagerPrefill.password = el.value;
|
// and we want to 'prefill' the password for the user,
|
||||||
// Because password managers fill username, then password,
|
// save it globally
|
||||||
// we need to re-focus the uid_field here too
|
PasswordManagerPrefill.password = el.value;
|
||||||
(this.shadowRoot || this)
|
// Because password managers fill username, then password,
|
||||||
.querySelectorAll<HTMLInputElement>("input[name=uidField]")
|
// we need to re-focus the uid_field here too
|
||||||
.forEach((input) => {
|
(this.shadowRoot || this)
|
||||||
// Because we assume only one input field exists that matches this
|
.querySelectorAll<HTMLInputElement>("input[name=uidField]")
|
||||||
// call focus so the user can press enter
|
.forEach((input) => {
|
||||||
input.focus();
|
// 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);
|
});
|
||||||
|
};
|
||||||
|
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");
|
||||||
|
Reference in New Issue
Block a user