# Authentik expression policy: allow Discord logins only for members of one Discord server (guild). # Paste into: Customization -> Policies -> Create -> Expression Policy (name: discord-guild-member) # Bind to BOTH flows: default-source-enrollment and default-source-authentication # (Flows & Stages -> Flows -> -> Policy / Group / User Bindings -> Bind existing policy) # Requires the "guilds" scope on the Discord source (source -> Protocol settings -> Scopes: guilds). # # Server ID: Discord -> User Settings -> Advanced -> Developer Mode on; right-click the server -> Copy Server ID. ACCEPTED_GUILD_ID = "1387203044084551690" # <- your Discord server ID GUILD_NAME = "Vanguard" # <- shown in the denial message GUILD_API_URL = "https://discord.com/api/users/@me/guilds" # Only act on logins that came through the Discord source; let everything else (akadmin password login) pass. source = context.get("source") if not source or getattr(source, "provider_type", "") != "discord": return True connection = context.get("goauthentik.io/sources/connection") if not connection: ak_message("No Discord connection in context.") return False resp = requests.get(GUILD_API_URL, headers={"Authorization": f"Bearer {connection.access_token}"}, timeout=10) if resp.status_code != 200: ak_message(f"Could not read Discord server list ({resp.status_code}). Try again.") return False is_member = any(g.get("id") == ACCEPTED_GUILD_ID for g in resp.json()) if not is_member: ak_message(f"You must be a member of the {GUILD_NAME} Discord server to log in.") return is_member