Compare commits

..

16 Commits

Author SHA1 Message Date
d842fc4958 release: 2023.2.2 2023-02-15 19:53:42 +01:00
19f5e6e07e website/docs: update events page
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 16:44:13 +01:00
acfa9c76d1 providers/ldap: check MFA password on password stage
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 16:27:08 +01:00
bff34cc5dc root: use channel send workaround for sync sending of websocket messages
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 16:08:01 +01:00
7f009f6d02 flows: include flow authentication requirement in diagram
closes #4533

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 16:04:45 +01:00
dfb9ae548c web/admin: fix error when creating new users
Signed-off-by: Jens Langhammer <jens@goauthentik.io>

#4685
2023-02-15 15:32:48 +01:00
7d6b573f8b website: migrate to mermaid charts, rework proxy page
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 12:14:17 +01:00
ade397fc24 web/user: revert truncate behaviour for application description
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 11:17:45 +01:00
d945d30cda providers/proxy: fix value is too long with filesystem sessions
closes #4693

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 10:50:01 +01:00
c8c401e2c5 lib: don't try to cache generated avatar with full user, only cache with name
closes #4690

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 10:49:13 +01:00
e4ca20bfc6 core: bump golang from 1.20.0-bullseye to 1.20.1-bullseye (#4691)
Bumps golang from 1.20.0-bullseye to 1.20.1-bullseye.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-15 10:46:02 +01:00
6347716815 core: bump goauthentik.io/api/v3 from 3.2023012.5 to 3.2023021.1 (#4692)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023012.5 to 3.2023021.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023012.5...v3.2023021.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-15 10:45:20 +01:00
859b6cc60e website: adjust padding on hero header
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 00:28:45 +01:00
06a1a7f076 ci: add time limits to ci jobs
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 00:28:36 +01:00
b6c120f555 providers/proxy: fix client credential flows not using http interceptor
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-02-15 00:22:56 +01:00
6cc363bc5d web: bump API Client version (#4689)
Signed-off-by: GitHub <noreply@github.com>
2023-02-14 20:35:22 +01:00
35 changed files with 1407 additions and 135 deletions

View File

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

View File

@ -80,6 +80,7 @@ jobs:
run: poetry run python -m lifecycle.migrate
test-unittest:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v3
- name: Setup authentik env
@ -94,6 +95,7 @@ jobs:
flags: unit
test-integration:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v3
- name: Setup authentik env
@ -111,6 +113,7 @@ jobs:
test-e2e:
name: test-e2e (${{ matrix.job.name }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:

View File

@ -31,7 +31,7 @@ RUN pip install --no-cache-dir poetry && \
poetry export -f requirements.txt --dev --output requirements-dev.txt
# Stage 4: Build go proxy
FROM docker.io/golang:1.20.0-bullseye AS go-builder
FROM docker.io/golang:1.20.1-bullseye AS go-builder
WORKDIR /work

View File

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

View File

@ -8,7 +8,7 @@ from rest_framework.serializers import CharField
from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import User
from authentik.flows.models import Flow, FlowStageBinding
from authentik.flows.models import Flow, FlowAuthenticationRequirement, FlowStageBinding
@dataclass
@ -160,12 +160,37 @@ class FlowDiagram:
)
return stages + elements
def get_flow_auth_requirement(self) -> list[DiagramElement]:
"""Get flow authentication requirement"""
end_el = DiagramElement(
"done",
_("End of the flow"),
_("Requirement not fulfilled"),
style=["[[", "]]"],
)
elements = []
if self.flow.authentication == FlowAuthenticationRequirement.NONE:
return []
auth = DiagramElement(
"flow_auth_requirement",
_("Flow authentication requirement") + "\n" + self.flow.authentication,
)
elements.append(auth)
end_el.source = [auth]
elements.append(end_el)
elements.append(
DiagramElement("flow_start", "placeholder", _("Requirement fulfilled"), source=[auth])
)
return elements
def build(self) -> str:
"""Build flowchart"""
all_elements = [
"graph TD",
]
all_elements.extend(self.get_flow_auth_requirement())
pre_flow_policies_element = DiagramElement(
"flow_pre", _("Pre-flow policies"), style=["[[", "]]"]
)
@ -179,6 +204,7 @@ class FlowDiagram:
_("End of the flow"),
_("Policy denied"),
flow_policies,
style=["[[", "]]"],
)
)

View File

@ -86,7 +86,7 @@ def generate_colors(text: str) -> tuple[str, str]:
@cache
# pylint: disable=too-many-arguments,too-many-locals
def generate_avatar_from_name(
user: "User",
name: str,
length: int = 2,
size: int = 64,
rounded: bool = False,
@ -98,8 +98,6 @@ def generate_avatar_from_name(
Inspired from: https://github.com/LasseRafn/ui-avatars
"""
name = user.name if user.name != "" else "a k"
name_parts = name.split()
# Only abbreviate first and last name
if len(name_parts) > 2:
@ -152,7 +150,7 @@ def generate_avatar_from_name(
def avatar_mode_generated(user: "User", mode: str) -> Optional[str]:
"""Wrapper that converts generated avatar to base64 svg"""
svg = generate_avatar_from_name(user)
svg = generate_avatar_from_name(user.name if user.name != "" else "a k")
return f"data:image/svg+xml;base64,{b64encode(svg.encode('utf-8')).decode('utf-8')}"

View File

@ -7,7 +7,6 @@ from urllib.parse import urlparse
import yaml
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.core.cache import cache
from django.db import DatabaseError, InternalError, ProgrammingError
from django.db.models.base import Model
@ -43,6 +42,7 @@ from authentik.providers.ldap.controllers.kubernetes import LDAPKubernetesContro
from authentik.providers.proxy.controllers.docker import ProxyDockerController
from authentik.providers.proxy.controllers.kubernetes import ProxyKubernetesController
from authentik.root.celery import CELERY_APP
from authentik.root.messages.storage import closing_send
LOGGER = get_logger()
CACHE_KEY_OUTPOST_DOWN = "outpost_teardown_%s"
@ -217,26 +217,23 @@ def outpost_post_save(model_class: str, model_pk: Any):
def outpost_send_update(model_instace: Model):
"""Send outpost update to all registered outposts, regardless to which authentik
instance they are connected"""
channel_layer = get_channel_layer()
if isinstance(model_instace, OutpostModel):
for outpost in model_instace.outpost_set.all():
_outpost_single_update(outpost, channel_layer)
_outpost_single_update(outpost)
elif isinstance(model_instace, Outpost):
_outpost_single_update(model_instace, channel_layer)
_outpost_single_update(model_instace)
def _outpost_single_update(outpost: Outpost, layer=None):
def _outpost_single_update(outpost: Outpost):
"""Update outpost instances connected to a single outpost"""
# Ensure token again, because this function is called when anything related to an
# OutpostModel is saved, so we can be sure permissions are right
_ = outpost.token
outpost.build_user_permissions(outpost.user)
if not layer: # pragma: no cover
layer = get_channel_layer()
for state in OutpostState.for_outpost(outpost):
for channel in state.channel_ids:
LOGGER.debug("sending update", channel=channel, instance=state.uid, outpost=outpost)
async_to_sync(layer.send)(channel, {"type": "event.update"})
async_to_sync(closing_send)(channel, {"type": "event.update"})
@CELERY_APP.task()

View File

@ -1,6 +1,7 @@
"""Channels Messages storage"""
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from channels import DEFAULT_CHANNEL_LAYER
from channels.layers import channel_layers
from django.contrib.messages.storage.base import Message
from django.contrib.messages.storage.session import SessionStorage
from django.core.cache import cache
@ -10,13 +11,21 @@ SESSION_KEY = "_messages"
CACHE_PREFIX = "goauthentik.io/root/messages_"
async def closing_send(channel, message):
"""Wrapper around layer send that closes the connection"""
# See https://github.com/django/channels_redis/issues/332
# TODO: Remove this after channels_redis 4.1 is released
channel_layer = channel_layers.make_backend(DEFAULT_CHANNEL_LAYER)
await channel_layer.send(channel, message)
await channel_layer.close_pools()
class ChannelsStorage(SessionStorage):
"""Send contrib.messages over websocket"""
def __init__(self, request: HttpRequest) -> None:
# pyright: reportGeneralTypeIssues=false
super().__init__(request)
self.channel = get_channel_layer()
def _store(self, messages: list[Message], response, *args, **kwargs):
prefix = f"{CACHE_PREFIX}{self.request.session.session_key}_messages_"
@ -28,7 +37,7 @@ class ChannelsStorage(SessionStorage):
for key in keys:
uid = key.replace(prefix, "")
for message in messages:
async_to_sync(self.channel.send)(
async_to_sync(closing_send)(
uid,
{
"type": "event.update",

View File

@ -32,7 +32,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.2.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.2.2}
restart: unless-stopped
command: server
environment:
@ -50,7 +50,7 @@ services:
- "${AUTHENTIK_PORT_HTTP:-9000}:9000"
- "${AUTHENTIK_PORT_HTTPS:-9443}:9443"
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.2.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.2.2}
restart: unless-stopped
command: worker
environment:

2
go.mod
View File

@ -25,7 +25,7 @@ require (
github.com/prometheus/client_golang v1.14.0
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.1
goauthentik.io/api/v3 v3.2023012.5
goauthentik.io/api/v3 v3.2023021.1
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f

9
go.sum
View File

@ -380,10 +380,8 @@ go.opentelemetry.io/otel/sdk v1.11.1 h1:F7KmQgoHljhUuJyA+9BiU+EkJfyX5nVVF4wyzWZp
go.opentelemetry.io/otel/trace v1.11.1 h1:ofxdnzsNrGBYXbP7t7zpUK281+go5rF7dvdIZXF8gdQ=
go.opentelemetry.io/otel/trace v1.11.1/go.mod h1:f/Q9G7vzk5u91PhbmKbg1Qn0rzH1LJ4vbPHFGkTPtOk=
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
goauthentik.io/api/v3 v3.2023012.4 h1:Vn85T5WQOEZfyimcAA6Anf4f+S68Lw3Ap5+v9d4+hZA=
goauthentik.io/api/v3 v3.2023012.4/go.mod h1:QM9J32HgYE4gL71lWAfAoXSPdSmLVLW08itfLI3Mo10=
goauthentik.io/api/v3 v3.2023012.5 h1:MRFw5LuRboeb3tD3gl1yRBuAwBLWfOdO9EGXcn/5yIk=
goauthentik.io/api/v3 v3.2023012.5/go.mod h1:QM9J32HgYE4gL71lWAfAoXSPdSmLVLW08itfLI3Mo10=
goauthentik.io/api/v3 v3.2023021.1 h1:UH9MiG9tRvbsV4UeCqvtjxxdl69Z3nIMsulwk9Sn1zM=
goauthentik.io/api/v3 v3.2023021.1/go.mod h1:QM9J32HgYE4gL71lWAfAoXSPdSmLVLW08itfLI3Mo10=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@ -528,8 +526,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -590,7 +586,6 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064 h1:BmCFkEH4nJrYcAc2L08yX5RhYGD4j58PTMkEUDkpz2I=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

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

View File

@ -25,6 +25,7 @@ func (fe *FlowExecutor) solveChallenge_Identification(challenge *api.ChallengeTy
}
func (fe *FlowExecutor) solveChallenge_Password(challenge *api.ChallengeTypes, req api.ApiFlowsExecutorSolveRequest) (api.FlowChallengeResponseRequest, error) {
fe.checkPasswordMFA()
r := api.NewPasswordChallengeResponseRequest(fe.getAnswer(StagePassword))
return api.PasswordChallengeResponseRequestAsFlowChallengeResponseRequest(r), nil
}

View File

@ -36,7 +36,7 @@ func (a *Application) attemptBasicAuth(username, password string) *Claims {
return nil
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
res, err := a.httpClient.Do(req)
res, err := a.publicHostHTTPClient.Do(req)
if err != nil || res.StatusCode > 200 {
b, err := io.ReadAll(res.Body)
if err != nil {

View File

@ -39,7 +39,7 @@ func (a *Application) attemptBearerAuth(token string) *TokenIntrospectionRespons
return nil
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
res, err := a.httpClient.Do(req)
res, err := a.publicHostHTTPClient.Do(req)
if err != nil || res.StatusCode > 200 {
a.log.WithError(err).Warning("failed to send introspection request")
return nil

View File

@ -1,6 +1,8 @@
package codecs
import (
"math"
"github.com/gorilla/securecookie"
log "github.com/sirupsen/logrus"
)
@ -12,6 +14,7 @@ type Codec struct {
func New(maxAge int, hashKey, blockKey []byte) *Codec {
cookie := securecookie.New(hashKey, blockKey)
cookie.MaxAge(maxAge)
cookie.MaxLength(math.MaxInt)
return &Codec{
SecureCookie: cookie,
}

View File

@ -1,5 +1,5 @@
# Stage 1: Build
FROM docker.io/golang:1.20.0-bullseye AS builder
FROM docker.io/golang:1.20.1-bullseye AS builder
WORKDIR /go/src/goauthentik.io

View File

@ -7,7 +7,7 @@ ENV NODE_ENV=production
RUN cd /static && npm ci && npm run build-proxy
# Stage 2: Build
FROM docker.io/golang:1.20.0-bullseye AS builder
FROM docker.io/golang:1.20.1-bullseye AS builder
WORKDIR /go/src/goauthentik.io

View File

@ -1,8 +1,5 @@
[tool.pyright]
ignore = [
"**/migrations/**",
"**/node_modules/**"
]
ignore = ["**/migrations/**", "**/node_modules/**"]
reportMissingTypeStubs = false
strictParameterNoneValue = true
strictDictionaryInference = true
@ -63,14 +60,7 @@ exclude_lines = [
show_missing = true
[tool.pylint.basic]
good-names = [
"pk",
"id",
"i",
"j",
"k",
"_",
]
good-names = ["pk", "id", "i", "j", "k", "_"]
[tool.pylint.master]
disable = [
@ -85,6 +75,7 @@ disable = [
"protected-access",
"unused-argument",
"raise-missing-from",
"fixme",
# To preserve django's translation function we need to use %-formatting
"consider-using-f-string",
]
@ -114,13 +105,13 @@ filterwarnings = [
[tool.poetry]
name = "authentik"
version = "2023.2.1"
version = "2023.2.2"
description = ""
authors = ["authentik Team <hello@goauthentik.io>"]
[tool.poetry.dependencies]
celery = "*"
channels = {version = "*", extras = ["daphne"]}
channels = { version = "*", extras = ["daphne"] }
channels-redis = "*"
codespell = "*"
colorama = "*"
@ -147,7 +138,7 @@ gunicorn = "*"
kubernetes = "*"
ldap3 = "*"
lxml = "*"
opencontainers = {extras = ["reggie"],version = "*"}
opencontainers = { extras = ["reggie"], version = "*" }
packaging = "*"
paramiko = "*"
psycopg2-binary = "*"
@ -163,8 +154,8 @@ swagger-spec-validator = "*"
twilio = "*"
twisted = "*"
ua-parser = "*"
urllib3 = {extras = ["secure"],version = "*"}
uvicorn = {extras = ["standard"],version = "*"}
urllib3 = { extras = ["secure"], version = "*" }
uvicorn = { extras = ["standard"], version = "*" }
webauthn = "*"
wsproto = "*"
xmlsec = "*"
@ -176,7 +167,7 @@ bandit = "*"
black = "*"
bump2version = "*"
colorama = "*"
coverage = {extras = ["toml"],version = "*"}
coverage = { extras = ["toml"], version = "*" }
importlib-metadata = "*"
pylint = "*"
pylint-django = "*"

View File

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

14
web/package-lock.json generated
View File

@ -22,7 +22,7 @@
"@codemirror/theme-one-dark": "^6.1.0",
"@formatjs/intl-listformat": "^7.1.7",
"@fortawesome/fontawesome-free": "^6.3.0",
"@goauthentik/api": "^2023.2.0-1676387781",
"@goauthentik/api": "^2023.2.1-1676400495",
"@hcaptcha/types": "^1.0.3",
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
"@lingui/cli": "^3.17.1",
@ -1975,9 +1975,9 @@
}
},
"node_modules/@goauthentik/api": {
"version": "2023.2.0-1676387781",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.2.0-1676387781.tgz",
"integrity": "sha512-iPNxpL6ej3irMORdQuiOmKsDqI2oc0Mrt86M+UCA6Sm16vxBjiQl8Pq9JFmQ0GLosVXQZXh7NrWM5lXJprByPA=="
"version": "2023.2.1-1676400495",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.2.1-1676400495.tgz",
"integrity": "sha512-NBP17SLYOE+AXIAyhQWdTNm6wkcruzGG1jlGaQQSGa8ShDl6g98bO7F+gLMIyOZTXeKx6+bLlKzsL+QKQ34AeA=="
},
"node_modules/@hcaptcha/types": {
"version": "1.0.3",
@ -11502,9 +11502,9 @@
"integrity": "sha512-qVtd5i1Cc7cdrqnTWqTObKQHjPWAiRwjUPaXObaeNPcy7+WKxJumGBx66rfSFgK6LNpIasVKkEgW8oyf0tmPLA=="
},
"@goauthentik/api": {
"version": "2023.2.0-1676387781",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.2.0-1676387781.tgz",
"integrity": "sha512-iPNxpL6ej3irMORdQuiOmKsDqI2oc0Mrt86M+UCA6Sm16vxBjiQl8Pq9JFmQ0GLosVXQZXh7NrWM5lXJprByPA=="
"version": "2023.2.1-1676400495",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.2.1-1676400495.tgz",
"integrity": "sha512-NBP17SLYOE+AXIAyhQWdTNm6wkcruzGG1jlGaQQSGa8ShDl6g98bO7F+gLMIyOZTXeKx6+bLlKzsL+QKQ34AeA=="
},
"@hcaptcha/types": {
"version": "1.0.3",

View File

@ -66,7 +66,7 @@
"@codemirror/theme-one-dark": "^6.1.0",
"@formatjs/intl-listformat": "^7.1.7",
"@fortawesome/fontawesome-free": "^6.3.0",
"@goauthentik/api": "^2023.2.0-1676387781",
"@goauthentik/api": "^2023.2.1-1676400495",
"@hcaptcha/types": "^1.0.3",
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
"@lingui/cli": "^3.17.1",

View File

@ -51,7 +51,7 @@ export class GroupForm extends ModelForm<Group, string> {
patchedGroupRequest: data,
});
} else {
data.users = Array.from(this.instance?.users || []);
data.users = [];
return new CoreApi(DEFAULT_CONFIG).coreGroupsCreate({
groupRequest: data,
});

View File

@ -48,6 +48,7 @@ export class UserForm extends ModelForm<User, number> {
patchedUserRequest: data,
});
} else {
data.groups = [];
return new CoreApi(DEFAULT_CONFIG).coreUsersCreate({
userRequest: data,
});

View File

@ -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.2.1";
export const VERSION = "2023.2.2";
export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";";

View File

@ -29,6 +29,20 @@ export function convertToTitle(text: string): string {
});
}
/**
* Truncate a string based on maximum word count
*/
export function truncateWords(string: string, length = 10): string {
string = string || "";
const array = string.trim().split(" ");
const ellipsis = array.length > length ? "..." : "";
return array.slice(0, length).join(" ") + ellipsis;
}
/**
* Truncate a string based on character count
*/
export function truncate(string: string, length = 10): string {
return string.length > length ? `${string.substring(0, length)}...` : string;
}

View File

@ -1,6 +1,6 @@
import { uiConfig } from "@goauthentik/common/ui/config";
import { me } from "@goauthentik/common/users";
import { truncate } from "@goauthentik/common/utils";
import { truncateWords } from "@goauthentik/common/utils";
import { AKElement } from "@goauthentik/elements/Base";
import { t } from "@lingui/macro";
@ -127,7 +127,7 @@ export class LibraryApplication extends AKElement {
</div>
</div>
<div class="pf-c-card__body">
${truncate(this.application.metaDescription || "", 35)}
${truncateWords(this.application.metaDescription || "", 35)}
</div>
</div>`;
}

View File

@ -4,11 +4,30 @@ title: Terminology
slug: /terminology
---
![](/img/authentik_objects.svg)
```mermaid
graph LR
source_ldap((LDAP Source)) <-->|Synchronizes| datasource_ldap["FreeIPA/
Active Directory"]
datasource_oauth1(Twtitter) --> source_oauth((OAuth/SAML\nSource))
datasource_oauth2(GitHub) --> source_oauth((OAuth/SAML\nSource))
source_oauth --> authentik_db(authentik Database)
source_ldap --> authentik_db(authentik Database)
### System tasks
app_sso(Gitlab) --> authentik_provider[Provider]
authentik_provider --> authentik_db
authentik_provider --> authentik_app["Application
(Stores permissions and UI details)"]
authentik_app --> authentik_policy_engine[Policy Engine]
authentik_policy_engine --> authentik_db
These are longer-running tasks which authentik runs in the background. This is used to sync LDAP sources, backup the database, and other various tasks.
app_ldap("Applications that only
support LDAP (e.g. pfSense)") --> authentik_outpost_ldap[LDAP Outpost]
app_proxy("Applications that don't
support any SSO (e.g. Plex)") --> authentik_outpost_proxy[Proxy Outpost]
authentik_outpost_ldap --> authentik_outposts[Outposts]
authentik_outpost_proxy --> authentik_outposts[Outposts]
authentik_outposts --> authentik_provider
```
### Application
@ -26,7 +45,7 @@ A Provider is a way for other applications to authenticate against authentik. Co
At a base level a policy is a yes/no gate. It will either evaluate to True or False depending on the Policy Kind and settings. For example, a "Group Membership Policy" evaluates to True if the user is member of the specified Group and False if not. This can be used to conditionally apply Stages, grant/deny access to various objects, and for other custom logic.
See [Policies](./policies/)
See [Policies](../policies/index.md)
### Flows & Stages
@ -34,16 +53,20 @@ Flows are an ordered sequence of stages. These flows can be used to define how a
A stage represents a single verification or logic step. They are used to authenticate users, enroll users, and more. These stages can optionally be applied to a flow via policies.
See [Flows](./flow/)
See [Flows](../flow/index.md)
### Property Mappings
Property Mappings allow you to make information available for external applications. For example, if you want to login to AWS with authentik, you'd use Property Mappings to set the user's roles in AWS based on their group memberships in authentik.
See [Property Mappings](./property-mappings/)
See [Property Mappings](../property-mappings/index.md)
### Outpost
An outpost is a separate component of authentik, which can be deployed anywhere, regardless of the authentik deployment. The outpost offers services that aren't implemented directly into the authentik core, e.g. Reverse Proxying.
See [Outposts](./outposts/)
See [Outposts](../outposts/index.mdx)
### System tasks
These are longer-running tasks which authentik runs in the background. This is used to sync LDAP sources, backup the database, and other various tasks.

View File

@ -4,30 +4,305 @@ title: Events
Events are authentik's built-in logging system. Whenever any of the following actions occur, an event is created:
- A user logs in/logs out (including the source, if available)
- A user fails to login
- A user sets their password
- A user views a token
- An invitation is used
- A user object is written to during a flow
- A user authorizes an application
- A user links a source to their account
- A user starts/ends impersonation, including the user that was impersonated
- A policy is executed (when a policy has "Execution Logging" enabled)
- A policy or property mapping causes an exception
- A configuration error occurs, for example during the authorization of an application
- Any objects is created/updated/deleted
- An update is available
Certain information is stripped from events, to ensure no passwords or other credentials are saved in the log.
If you want to forward these events to another application, simply forward the log output of all authentik containers. Every event creation is logged there.
If you want to forward these events to another application, forward the log output of all authentik containers. Every event creation is logged with the log level "info".
### `login`
A user logs in (including the source, if available)
<details><summary>Example</summary>
<p>
```json
{
"pk": "f00f54e7-2b38-421f-bc78-e61f950048d6",
"user": {
"pk": 1,
"email": "root@localhost",
"username": "akadmin"
},
"action": "login",
"app": "authentik.events.signals",
"context": {
"auth_method": "password",
"http_request": {
"args": {
"query": "next=%2F"
},
"path": "/api/v3/flows/executor/default-authentication-flow/",
"method": "GET"
},
"auth_method_args": {}
},
"client_ip": "::1",
"created": "2023-02-15T15:33:42.771091Z",
"expires": "2024-02-15T15:33:42.770425Z",
"tenant": {
"pk": "fcba828076b94dedb2d5a6b4c5556fa1",
"app": "authentik_tenants",
"name": "Default tenant",
"model_name": "tenant"
}
}
```
</p>
</details>
### `login_failed`
A failed login attempt
<details><summary>Example</summary>
<p>
```json
{
"pk": "2779b173-eb2a-4c2b-a1a4-8283eda308d7",
"user": {
"pk": 2,
"email": "",
"username": "AnonymousUser"
},
"action": "login_failed",
"app": "authentik.events.signals",
"context": {
"stage": {
"pk": "7e88f4a991c442c1a1335d80f0827d7f",
"app": "authentik_stages_password",
"name": "default-authentication-password",
"model_name": "passwordstage"
},
"password": "********************",
"username": "akadmin",
"http_request": {
"args": {
"query": "next=%2F"
},
"path": "/api/v3/flows/executor/default-authentication-flow/",
"method": "POST"
}
},
"client_ip": "::1",
"created": "2023-02-15T15:32:55.319608Z",
"expires": "2024-02-15T15:32:55.314581Z",
"tenant": {
"pk": "fcba828076b94dedb2d5a6b4c5556fa1",
"app": "authentik_tenants",
"name": "Default tenant",
"model_name": "tenant"
}
}
```
</p>
</details>
### `logout`
A user logs out.
<details><summary>Example</summary>
<p>
```json
{
"pk": "474ffb6b-77e3-401c-b681-7d618962440f",
"user": {
"pk": 1,
"email": "root@localhost",
"username": "akadmin"
},
"action": "logout",
"app": "authentik.events.signals",
"context": {
"http_request": {
"args": {
"query": ""
},
"path": "/api/v3/flows/executor/default-invalidation-flow/",
"method": "GET"
}
},
"client_ip": "::1",
"created": "2023-02-15T15:39:55.976243Z",
"expires": "2024-02-15T15:39:55.975535Z",
"tenant": {
"pk": "fcba828076b94dedb2d5a6b4c5556fa1",
"app": "authentik_tenants",
"name": "Default tenant",
"model_name": "tenant"
}
}
```
</p>
</details>
### `user_write`
A user is written to during a flow execution.
<details><summary>Example</summary>
<p>
```json
{
"pk": "d012e8af-cb94-4fa2-9e92-961e4eebc060",
"user": {
"pk": 1,
"email": "root@localhost",
"username": "akadmin"
},
"action": "user_write",
"app": "authentik.events.signals",
"context": {
"name": "authentik Default Admin",
"email": "root@localhost",
"created": false,
"username": "akadmin",
"attributes": {
"settings": {
"locale": ""
}
},
"http_request": {
"args": {
"query": ""
},
"path": "/api/v3/flows/executor/default-user-settings-flow/",
"method": "GET"
}
},
"client_ip": "::1",
"created": "2023-02-15T15:41:18.411017Z",
"expires": "2024-02-15T15:41:18.410276Z",
"tenant": {
"pk": "fcba828076b94dedb2d5a6b4c5556fa1",
"app": "authentik_tenants",
"name": "Default tenant",
"model_name": "tenant"
}
}
```
</p>
</details>
### `suspicious_request`
A suspicious request has been received (for example, a revoked token was used).
### `password_set`
A user sets their password.
### `secret_view`
A user views a token's/certificate's data.
### `secret_rotate`
A token was rotated automatically by authentik.
### `invitation_used`
An invitation is used.
### `authorize_application`
A user authorizes an application.
<details><summary>Example</summary>
<p>
```json
{
"pk": "f52f9eb9-dc2a-4f1e-afea-ad5af90bf680",
"user": {
"pk": 1,
"email": "root@localhost",
"username": "akadmin"
},
"action": "authorize_application",
"app": "authentik.providers.oauth2.views.authorize",
"context": {
"geo": {
"lat": 42.0,
"city": "placeholder",
"long": 42.0,
"country": "placeholder",
"continent": "placeholder"
},
"flow": "53287faa8a644b6cb124cb602a84282f",
"scopes": "ak_proxy profile openid email",
"http_request": {
"args": {
"query": "[...]"
},
"path": "/api/v3/flows/executor/default-provider-authorization-implicit-consent/",
"method": "GET"
},
"authorized_application": {
"pk": "bed6a2495fdc4b2e8c3f93cb2ed7e021",
"app": "authentik_core",
"name": "Alertmanager",
"model_name": "application"
}
},
"client_ip": "::1",
"created": "2023-02-15T10:02:48.615499Z",
"expires": "2023-04-26T10:02:48.612809Z",
"tenant": {
"pk": "10800be643d44842ab9d97cb5f898ce9",
"app": "authentik_tenants",
"name": "Default tenant",
"model_name": "tenant"
}
}
```
</p>
</details>
### `source_linked`
A user links a source to their account
### `impersonation_started` / `impersonation_ended`
A user starts/ends impersonation, including the user that was impersonated
### `policy_execution`
A policy is executed (when a policy has "Execution Logging" enabled).
### `policy_exception` / `property_mapping_exception`
A policy or property mapping causes an exception
### `system_task_exception`
An exception occurred in a system task.
### `system_exception`
A general exception in authentik occurred.
### `configuration_error`
A configuration error occurs, for example during the authorization of an application
### `model_created` / `model_updated` / `model_deleted`
Logged when any model is created/updated/deleted, including the user that sent the request.
### `email_sent`
An email has been sent. Included is the email that was sent.
### `update_available`
An update is available

View File

@ -1,28 +1,94 @@
---
title: Overview
title: Proxy Provider
---
```mermaid
sequenceDiagram
participant u as User accesses service
participant rp as Reverse proxy
participant ak as authentik
participant s as Service
u->>rp: Initial request
rp->>ak: Checks authentication
alt User is authenticated
ak ->> rp: Successful response
rp ->> s: Initial request is forwarded
else User needs to be authenticated
ak ->> rp: Redirect to the login page
rp ->> u: Redirect is passed to enduser
end
```
## Headers
The proxy outpost sets the following user-specific headers:
- X-authentik-username: `akadmin`
### `X-authentik-username`
The username of the currently logged in user
Example value: `akadmin`
- X-authentik-groups: `foo|bar|baz`
The username of the currently logged in user
The groups the user is member of, separated by a pipe
### `X-authentik-groups`
- X-authentik-email: `root@localhost`
Example value: `foo|bar|baz`
The email address of the currently logged in user
The groups the user is member of, separated by a pipe
- X-authentik-name: `authentik Default Admin`
### `X-authentik-email`
Full name of the current user
Example value: `root@localhost`
- X-authentik-uid: `900347b8a29876b45ca6f75722635ecfedf0e931c6022e3a29a8aa13fb5516fb`
The email address of the currently logged in user
The hashed identifier of the currently logged in user.
### `X-authentik-name`
Example value: `authentik Default Admin`
Full name of the current user
### `X-authentik-uid`
Example value: `900347b8a29876b45ca6f75722635ecfedf0e931c6022e3a29a8aa13fb5516fb`
The hashed identifier of the currently logged in user.
Besides these user-specific headers, some application specific headers are also set:
### `X-authentik-meta-outpost`
Example value: `authentik Embedded Outpost`
The authentik outpost's name.
### `X-authentik-meta-provider`
Example value: `test`
The authentik provider's name.
### `X-authentik-meta-app`
Example value: `test`
The authentik application's slug.
### `X-authentik-meta-version`
Example value: `goauthentik.io/outpost/1.2.3`
The authentik outpost's version.
### `X-Forwarded-Host`
:::info
Only set in proxy mode
:::
The original Host header sent by the client. This is set as the `Host` header is set to the host of the configured backend.
### Additional headers
Additionally, you can set `additionalHeaders` attribute on groups or users to set additional headers:
@ -31,30 +97,6 @@ additionalHeaders:
X-test-header: test-value
```
Besides these user-specific headers, some application specific headers are also set:
- X-authentik-meta-outpost: `authentik Embedded Outpost`
The authentik outpost's name.
- X-authentik-meta-provider: `test`
The authentik provider's name.
- X-authentik-meta-app: `test`
The authentik application's slug.
- X-authentik-meta-version: `goauthentik.io/outpost/1.2.3`
The authentik outpost's version.
### Only in proxy mode
- X-Forwarded-Host:
The original Host header sent by the client. This is set as the `Host` header is set to the host of the configured backend.
## HTTPS
The outpost listens on both 9000 for HTTP and 9443 for HTTPS.

View File

@ -169,6 +169,10 @@ module.exports = {
},
],
],
markdown: {
mermaid: true,
},
themes: ["@docusaurus/theme-mermaid"],
scripts: [
{
src: "https://goauthentik.io/js/script.js",

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
"dependencies": {
"@docusaurus/plugin-client-redirects": "2.3.1",
"@docusaurus/preset-classic": "2.3.1",
"@docusaurus/theme-mermaid": "^2.3.1",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"disqus-react": "^1.1.5",

View File

@ -24,6 +24,7 @@
}
.hero--primary {
padding-bottom: 5.3rem !important;
-webkit-clip-path: polygon(0 0, 100% 0, 100% 100%, 0 calc(100% - 3vw));
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 calc(100% - 3vw));
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 24 KiB