Files
homelabstack/stacks/authentik/scripts/setup-batch1-oidc.py
T
ginnoir 1ce63153ab Persist TB-006 batch 2 media SSO and batch 1 auth fixes to the repo.
Media sites get Caddy forward_auth; Authentik scripts cover all proxy providers. BookStack OIDC and Plane admin routing fixes included, plus ops scripts for external auth on valhalla.
2026-06-11 01:19:06 -05:00

80 lines
3.2 KiB
Python

"""Create OAuth2 providers for batch-1 apps with native SSO (ak shell: exec(open(...).read()))."""
from authentik.core.models import Application
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.outposts.models import Outpost
from authentik.providers.oauth2.models import OAuth2Provider, RedirectURI, RedirectURIMatchingMode, SubModes
from authentik.providers.proxy.models import ProxyProvider
AUTHZ = Flow.objects.get(slug="default-provider-authorization-implicit-consent")
INVALID = Flow.objects.get(slug="default-provider-invalidation-flow")
DEFAULT_MAPPINGS = OAuth2Provider.objects.get(name="famapp").property_mappings.all()
SIGNING_KEY = CertificateKeyPair.objects.get(name="authentik Self-signed Certificate")
# slug, provider name, redirect URI(s)
OIDC_APPS = [
("bookstack", "bookstack", ["https://docs.ginnoir.com/oidc/callback"]),
("gitea", "gitea", ["https://gitea.ginnoir.com/user/oauth2/Authentik/callback"]),
("portainer", "portainer", ["https://portainer.ginnoir.com/"]),
("minio", "minio-console", ["https://minio.ginnoir.com/oauth_callback"]),
]
native_slugs = []
for slug, pname, redirects in OIDC_APPS:
provider, created = OAuth2Provider.objects.update_or_create(
name=pname,
defaults={
"authorization_flow": AUTHZ,
"invalidation_flow": INVALID,
"signing_key": SIGNING_KEY,
"sub_mode": SubModes.USER_UUID if slug == "bookstack" else SubModes.HASHED_USER_ID,
"redirect_uris": [
RedirectURI(matching_mode=RedirectURIMatchingMode.STRICT, url=url)
for url in redirects
],
"access_code_validity": "minutes=1",
"access_token_validity": "hours=24",
"refresh_token_validity": "days=30",
},
)
provider.property_mappings.set(DEFAULT_MAPPINGS)
provider.save()
app, _ = Application.objects.update_or_create(
slug=slug,
defaults={
"name": pname.replace("-", " ").title(),
"provider": provider,
"meta_launch_url": redirects[0].split("/oidc")[0].split("/user/oauth2")[0].rstrip("/"),
"policy_engine_mode": "any",
},
)
app.provider = provider
app.save()
native_slugs.append(slug)
print(f"oauth2 {slug} created={created} client_id={provider.client_id}")
print(f" {slug.upper()}_OIDC_CLIENT_ID={provider.client_id}")
print(f" {slug.upper()}_OIDC_CLIENT_SECRET={provider.client_secret}")
# Drop native-OIDC apps from the embedded proxy outpost (avoid double auth).
PROXY_NAMES = {
"bookstack": "homelab-bookstack",
"gitea": "homelab-gitea",
"portainer": "homelab-portainer",
"minio": "homelab-minio",
}
outpost = Outpost.objects.get(name="authentik Embedded Outpost")
for slug in native_slugs:
pname = PROXY_NAMES.get(slug)
if not pname:
continue
try:
proxy = ProxyProvider.objects.get(name=pname)
outpost.providers.remove(proxy)
print(f"removed proxy {pname} from embedded outpost")
except ProxyProvider.DoesNotExist:
print(f"proxy {pname} not found (ok)")
print("done — configure each app with printed client_id/secret")