* blueprints: emit draft-07 `definitions` instead of `$defs`
The generated blueprint schema declares draft-07:
"$schema": "http://json-schema.org/draft-07/schema"
but stored every model definition under `$defs` and referenced them as
`#/$defs/...`. `$defs` is 2020-12 vocabulary; draft-07 spells it `definitions`.
A validator honouring the declared dialect therefore cannot resolve any of
those references, so nothing consuming the published schema.json can validate
a blueprint at all — which is what #24248 reports.
Switching the declared dialect to 2020-12 instead is not a drop-in: the schema
also uses draft-07-style plain-fragment `$id` values (`#/properties/version`),
which 2020-12 does not permit — it uses `$anchor` for that. Renaming the
keyword keeps the schema internally consistent with what it already claims to
be, and is the smaller change.
Adds a regression test that validates the schema the way a consumer does:
serialized through `json_default`, exactly as `build_schema` writes it, since
the in-memory dict still holds gettext_lazy proxies. It asserts the schema
passes `Draft7Validator.check_schema` and that every `$ref` resolves to a real
definition.
Verified:
manage.py test authentik.blueprints.tests.test_schema.TestSchema -> 5 passed
reverting schema.py -> 3 failed
ruff check / ruff format -> clean
Note: authentik.blueprints.tests.test_v1.TestBlueprintsV1.test_import_yaml_tags
fails identically with and without this change on current main.
closes#24248
* re-gen
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
* server/static: cover range requests for static assets
The Go web server this originally fixed is gone — `ak server` now execs the
Rust binary, and its static handler is a tower-http `ServeDir` behind a
compression layer. Both halves of the old fix are moot there: `ServeDir`
serves ranges itself, tower-http never compresses a response carrying
`Content-Range`, and no ETag middleware survived the rewrite.
Nothing to port, then, but the events map still byte-serves its PMTiles
basemap out of `/static/dist/`, so pin the behavior it depends on: a ranged
request comes back as an uncompressed 206 with an accurate `Content-Length`,
while a full request is still gzipped. The compression layer moves behind a
named constructor so the test exercises the same configuration the router
builds.
refs #21849
* brands: add branding_map_tiles for the events map tile source (#24253)
* brands: add branding_map_tiles for the events map tile source
Brand-level override for where the events map loads its vector tiles:
empty keeps the bundled basemap, a pmtiles:// archive URL or XYZ template
points at your own. Includes the migration, schema, and regenerated
clients.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
* packages/geo: add @goauthentik/geo and the hexworld event map (#24255)
A standalone Lit + MapLibre package for the events map: a tilted globe
that bins events into H3 cells and raises them as action-colored pie
columns, over a hex basemap bundled as a PMTiles archive — no tile server
and no external requests, so it works air-gapped. Zoom bands cross-fade
and columns animate between re-bins. Ships the archive, the generator CLI,
and node tests for the geometry, styling, and tiling plan.
Co-authored-by: Teffen Ellis <teffen@Teffens-MacBook-Pro.local>
---------
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Teffen Ellis <teffen@Teffens-MacBook-Pro.local>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* web: replace the OpenLayers events map with ak-map (#24257)
* brands: add branding_map_tiles for the events map tile source
Brand-level override for where the events map loads its vector tiles:
empty keeps the bundled basemap, a pmtiles:// archive URL or XYZ template
points at your own. Includes the migration, schema, and regenerated
clients.
* packages/geo: add @goauthentik/geo and the hexworld event map
A standalone Lit + MapLibre package for the events map: a tilted globe
that bins events into H3 cells and raises them as action-colored pie
columns, over a hex basemap bundled as a PMTiles archive — no tile server
and no external requests, so it works air-gapped. Zoom bands cross-fade
and columns animate between re-bins. Ships the archive, the generator CLI,
and node tests for the geometry, styling, and tiling plan.
* web: replace the OpenLayers events map with ak-map
EventMap now renders @goauthentik/geo's globe: events show as extruded
columns split by action, hovering shows a localized breakdown, and
clicking a column filters the list to that cell's events. The build copies
the bundled archive and glyphs into dist. OpenLayers and the pin-marker
path are removed.
---------
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Co-authored-by: Teffen Ellis <teffen@Teffens-MacBook-Pro.local>
* Format.
* brands: note that branding_map_tiles is served unauthenticated
The events map is admin-only, but branding_map_tiles rides along in
CurrentBrandSerializer, which /core/brands/current/ exposes with
AllowAny. Commercial tile providers carry their API key in the URL, and
the help text invites pasting exactly such a URL, so say plainly that
the value is world-readable.
Migration 0016 is edited in place rather than superseded — it has not
shipped, and makemigrations reports no pending changes. Schema and
clients regenerated.
* geo: strip build-machine paths from the shipped basemap archive
The committed hexworld.pmtiles carried the absolute path of the scratch
directory it was built in — including a session uuid — in its metadata
name, description and generator_options, shipped to every install.
tile-join inherits those fields from its first input file, so pass
--name/--description/--attribution explicitly to stop it recurring.
The archive itself is rewritten in place rather than regenerated:
pmtiles v3 lays out header, root directory, metadata, leaf directories
and tile data contiguously, and directory entries address tiles relative
to tileDataOffset, so resizing the metadata only shifts two header
offsets. Verified with the pmtiles reader — header fields match and 634
sampled tiles across z0-7 are byte-identical.
* web: drop the unused OpenLayers map pin
map_pin.svg was the marker icon the OpenLayers events map drew; ak-map
renders extruded columns instead and nothing references the file.
Also correct the preserveSymlinks comment. The flag is load-bearing, but
not for the stated reason: geo resolves its own dependencies fine from
its own node_modules. What it prevents is resolving them by realpath,
which pulls a second copy of the Lit runtime out of .pnpm alongside the
one in web/node_modules — two lit-html/lit-element/@lit-reactive-element
trees and two ReactiveElement hierarchies in one bundle.
* build: pin playwright through the pnpm catalog in both workspaces
The root and web/ are separate pnpm workspaces with separate lockfiles,
so a caret range let them resolve playwright independently — root landed
on 1.62.0 while web sat at 1.61.1, and `playwright install` downloads a
~95 MB browser build keyed to the exact version. Two versions, two
downloads. Catalog entries plus lint-catalogs turn that drift into a
failing check; the pin is exact because a range is what allowed it.
Held at 1.61.1 rather than the newest: 1.62.0 cannot resolve a bare
package name in a tsconfig `extends`, and web/tsconfig.json extends
"@goauthentik/tsconfig", so loading web's playwright.config.js fails and
the e2e suite never runs. `playwright test --list` discovers 25 tests on
1.61.1 and dies before discovery on 1.62.0.
vitest, vite and the @vitest/browser pair join the same catalog since
geo now uses them too and @vitest/browser-playwright drives whichever
playwright it finds.
* geo: rebuild ak-map on re-parent, run tests from source under vitest
disconnectedCallback tore the MapLibre instance down but firstUpdated
only ever fires once, so re-parenting <ak-map> left it permanently
blank. Rebuild from connectedCallback once the element has updated.
The new Chromium test covers exactly that: it fails without the fix and
passes with it, and no other test moves.
Tests move from node:test over compiled out/*.js to vitest over src, so
they exercise the source rather than a stale build and need no build
step. Six of them reached for ../out/*.js through a dynamic import and
would have kept asserting against whatever was last compiled.
Along the way, three things that were already broken:
- `tsc -p scripts` never ran anywhere and does not compile — its
tsconfig omits the DOM lib while its import graph reaches
src/style.ts, which uses `window`. There is now a lint:types script
covering src, scripts and test.
- TippecanoeFeature extended a bare Feature though placeFeature
always emits a Point with fixed properties.
- The README described a previous generation of the generator: wrong
script path, wrong cut names, a zoom band that stops at z7 rather
than z8, a shipped archive listed at 8.8 MB when it is 22 MiB, and
markers painted "via MapLibre feature-state" when they are a
fill-extrusion source.
publishConfig is dropped rather than `private`: geo depends on
@goauthentik/api via link:, which cannot survive publication, so the
package is unpublishable either way and publishConfig was the dead half.
* rust nits
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
* website/docs: document the hexworld event map
* website/docs: drop the OSM tile server from the air-gapped outbound list
The events map no longer reaches tile.openstreetmap.org — the bundled
basemap makes no outbound connections. Note the one way it can reach out
again: a custom basemap configured on a brand.
* Ignore build info.
* Ignore build info.
* Fix pins.
* Fix formatting.
* Fix duplicate package entries.
* Move runtime code to web.
---------
Signed-off-by: Teffen Ellis <592134+GirlBossRush@users.noreply.github.com>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Teffen Ellis <teffen@Teffens-MacBook-Pro.local>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
* add USER_OFFBOARDED event
* Add UserOffboarding model
* add shared offboard_user service
* add offboarding API and scheduled sweeper
* regenerate schema and TS client
* first pass of offboarding UI
* add initiator for event audit attribution
* refactor ReviewerUser to PartialUser since now that's the way to go
* make it atomic
* prevent 2 workers to offboard an user at the same time
* update migration file
* fix linting
* add missing migration
* add test for prevent self offboard
* Add UserOffboarding.cancel() and log who cancelled
* Add confirmation dialog for cancel offboarding and add IDs to strings
* Reference user_id, not user, to avoid a DB fetch
* update schema and clients
* Add enum overrides for offboarding
* prevent duplicate offboardings and show API errors
* use send_with_options(rel_obj=Schedule…) so executions show under their schedule
* use partial index
* refactor comment
* Add datetime-local fallback
* prevent cancel/excecute race condition, make records inmutable
* add authentik.enterprise.core.revocation for shared functionality
* refactor account lockdown to use shared revocation functionality
* Simplify transaction
* switch to mixin composition for UserOffboardingViewSet
* use new @enterprise_test decorator
* refactor lifecycle app between review and offboarding
* prevent unnecessary redaction of revoke_tokens boolean in the logs
* prevent an user/admin to cancel their own offboarding
* rename scheduled_at and executed_at fields
* improve help text to be more accurate
* change button color
* use task.rel_obj, apply code review suggestions
---------
Signed-off-by: Marcelo Elizeche Landó <marcelo@goauthentik.io>
* sources/ldap: add sync_group_parentage field
* sources/ldap: regenerate schema after adding field
* sources/ldap: add group parentage synchronizer
* web/admin: add LDAP source toggle for sync_group_parentage
* sources/ldap: rename LDAPSource fields to more accurate names
* web/admin: update admin UI with new field names
Also added better descriptions to all relevant fields, explaining how they interact with each other.
* sources/ldap: add unit tests
* sources/ldap: fix problem discovered by test
* sources/ldap: lint
* web/admin: lint
* website/docs: update LDAP source docs about lookup fields & membership
* sources/ldap: fix renamed attributes
* web/admin: make web
* sources/ldap: update tests and entries.json fixture
* sources/ldap: update migration with current help_text
* sources/ldap: fix lint error
* sources/ldap: restore membership.py to main, with renamed fields
in prep for separating out the synchronizers
* sources/ldap: abstract get_group into BaseMembershipLDAPSynchronizer
* sources/ldap: add separate ParentshipLDAPSynchronizer
* sources/ldap: fix wrong attribute name in extra parents filtering
* remove renames
* rename `sync_group_parents` to `sync_group_hierarchy`
* set `sync_group_hierarchy` default to `False`
This is a breaking change if it's `True`. It should be changed
eventually, but not in this release.
* revert pagination function change
I'm not entirely sure why, but this change hangs the test
`test_membership_sync_special_chars_in_group_dn`.
* add `sync_group_hierarchy` guard to hierarchy sync
* simplify hierarchy sync
* reword group `parentship` to `hierarchy`
* fix lint
* remove dead code
* move `syncGroupHierarchy` toggle next to similar toggles
---------
Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Simonyi Gergő <gergo@goauthentik.io>
* sources/oauth: allow long authorization URLs on OAuth sources
CharField(max_length=255) is too short for Authorization URLs that
include static query parameters such as CILogon's idphint with multiple
IdP EntityIDs. Switch the OAuth source URL fields to TextField, matching
oidc_well_known_url / oidc_jwks_url.
Co-authored-by: Cursor <cursoragent@cursor.com>
* sources/oauth: add test and regenerate schema for long URL fields
Add an API test covering saving an authorization URL longer than 255
characters, and regenerate schema.yml to drop the maxLength: 255
constraint now that these fields are TextField.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* sources/oauth: fix long-URL test to patch all required URL fields
Verified locally: full backend dev environment (Postgres, uv sync,
migrations), full authentik.sources.oauth suite (49 passed), schema.yml
diffed byte-for-byte against 'make gen-build' output (no diff), Ruff/Black
clean, no pending migrations.
* sources/oauth: regenerate blueprints/schema.json for URL TextField change
CI's test-gen job diffs blueprints/schema.json against 'make gen-build'
output; the earlier commit only updated schema.yml and missed this file.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* sources/saml: fix issuer generation
* change field to issuer override
* fix field description and form location
* update front-end and docs
* Update index.md
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
* build docs
---------
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
* providers/oauth2: add token exchange grant type and error codes
Add the RFC 8693 grant type identifier, the token type identifiers for
access tokens and JWTs, and the invalid_target error code. The grant is
added to the available choices only; existing providers are not opted in.
Signed-off-by: Aubin Morand <aubin.mora@gmail.com>
* providers/oauth2: implement RFC 8693 token exchange
Add the token exchange grant to the token endpoint, implementing the
impersonation case: a subject token issued by a federated provider or
source is traded for an access token that speaks for the same user.
Subject tokens are verified through the existing JWT federation trust,
so a provider may only exchange tokens it already trusts for
machine-to-machine authentication. Confidential clients must
authenticate; the subject token is not a substitute for client
credentials.
Delegation is out of scope, so an actor token is refused rather than
ignored. Token targeting is likewise unimplemented, so audience and
resource are refused with invalid_target as required by RFC 8693
section 2.2.2. Both would otherwise leave a client believing a
restriction had been applied when it had not.
Signed-off-by: Aubin Morand <aubin.mora@gmail.com>
* providers/oauth2: add token exchange tests
Cover the impersonation path, the rejection of delegation and token
targeting, unsupported token types, untrusted and unverifiable subject
tokens, and the client authentication requirement.
Signed-off-by: Aubin Morand <aubin.mora@gmail.com>
* website: document the token exchange grant
Describe the trust configuration the grant relies on, the supported
token type identifiers, and the parameters authentik refuses rather
than silently ignores.
Signed-off-by: Aubin Morand <aubin.mora@gmail.com>
* core: regenerate schema and API client for token exchange
Signed-off-by: Aubin Morand <aubin.mora@gmail.com>
* web/admin: expose the token exchange grant type
Add the grant to the selectable list. It is deliberately absent from the
default grant types, so the grant stays opt-in for new providers.
Signed-off-by: Aubin Morand <aubin.mora@gmail.com>
* include more in login event
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: Aubin Morand <aubin.mora@gmail.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
* stages/captcha: add Cap and JSON verification support
Add a configurable verification request content type so CAPTCHA providers can use either form-encoded or JSON token verification.
Add Cap as a preset and flow controller, including module-script loading, interactive widget handling, generated API/client types, tests, and docs.
* web/admin: clarify Cap captcha configuration
Treat the Cap endpoint as a form-only alias for the existing public key field and document Cap alongside the other CAPTCHA providers.
Agent-thread: https://sdko.org/internal/threads/019e737a-314e-72d0-98ae-201cb855df3a
A7k-product: product
A7k-product-repo: 2
Co-authored-by: Agent <agent@svc.sdko.net>
* stages/captcha: prefer self-hosted Cap widget URL
Default the Cap provider guidance to the self-hosted widget asset and keep CDN usage pinned to reviewed releases.
Agent-thread: https://sdko.org/internal/thr/ak/019ead31-2435-7e12-b933-e873155d6894
A7k-product: product
A7k-product-repo: 2
Co-authored-by: Agent <agent@svc.sdko.net>
* floating
---------
Co-authored-by: Agent <agent@svc.sdko.net>
Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
- Use the pending lockdown target in the example blueprint warning and avoid repeating the username when email/name is not distinct.
- Hide the admin Account Lockdown action for internal service accounts.
* initial
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* use same startup template
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix check not working
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* unrelated: fix inspector auth
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add tests
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* update docs
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* ensure oobe flow can only accessed via correct url
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* set setup flag when applying bootstrap blueprint when env is set
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add system visibility to flags to make them non-editable
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* set setup flag for e2e tests
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix tests and linting
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix tests
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* make github lint happy
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* make tests have less assumptions
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* Update docs
* include more heuristics in migration
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add management command to set any flag
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* migrate worker command to signal
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* improved api for setting flags
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* short circuit
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>