# Authentik SCOPE MAPPING (not a policy): adds two things the apps behind the proxy need and the built-in # mappings do not provide. # # Paste into: Customization -> Property Mappings -> Create -> Scope Mapping # Name: Vanguard profile (nested groups + discord id) # Scope name: profile # Then tick it, NEXT TO the managed "authentik default OAuth Mapping: OpenID 'profile'", on every provider the # community uses: the "Vanguard sites" proxy provider, Jellyfin and Gitea (Advanced protocol settings -> Scopes). # Claims from several mappings are merged, so both run and neither needs removing. Proxy providers re-add the # managed one on every save, which is why this adds to it rather than replacing it. # # 1. groups: the managed mapping emits ak_groups, i.e. DIRECT memberships only, so a group inherited through a # parent never reaches the apps. This emits only the inherited ones; merged with the managed mapping's direct # ones the apps see the full set, with no duplicates. # # 2. discord_id: the Discord snowflake, taken from the source connection Authentik already stores when it links # an account. It reaches the apps in X-Authentik-Jwt. The Discord bot uses it to identify the caller exactly, # instead of matching an Authentik username against Discord names — names are mutable, reusable, and server # nicknames are not unique, so name matching can both lock the right person out and let the wrong one in. # # Takes effect on the next login. DISCORD_SOURCE_SLUG = "discord" direct = set(request.user.ak_groups.all()) inherited = sorted(group.name for group in request.user.all_groups() if group not in direct) discord_id = None for attribute in ("usersourceconnection_set", "source_connections"): # the related name differs by version related = getattr(request.user, attribute, None) if related is None: continue connection = (related.filter(source__slug=DISCORD_SOURCE_SLUG).first() or related.first()) if connection is not None: discord_id = getattr(connection, "identifier", None) or None break return {"groups": inherited, "discord_id": discord_id}