website/integrations: Update discord integration with guild and role check (#5701)

* Update Discord OAuth instructions - index.md

Adds two sections to this document describing how the required expression policies needed to check users are a member of a certain guild or a member of a certain guild with a certain role.

Signed-off-by: Aterfax <Aterfax@users.noreply.github.com>

* Linting and styleguide amendments.

* Remove spurious empty lines.

* Add an extra line to space comments out.

* Moved warning in wrong place.

* Apply suggestions from code review

Refactor as per BeryJu's suggestions.

Co-authored-by: Jens L. <jens@beryju.org>
Signed-off-by: Aterfax <Aterfax@users.noreply.github.com>

---------

Signed-off-by: Aterfax <Aterfax@users.noreply.github.com>
Co-authored-by: Jens L. <jens@beryju.org>
This commit is contained in:
Aterfax 2023-05-21 13:41:59 +01:00 committed by GitHub
parent b4a3b266b3
commit d8de60b053
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -52,3 +52,93 @@ Save, and you now have Discord as a source.
:::note
For more details on how-to have the new source display on the Login Page see [here](../general#add-sources-to-default-login-page).
:::
### Checking for membership of a Discord Guild
:::info
Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds` scope added under the 'Protocol settings'.
:::
Create a new 'Expression Policy' with the content below, adjusting the variables where required:
```python
# To get the guild ID number for the parameters, open Discord, go to Settings > Advanced and enable developer mode.
# Right-click on the server/guild title and select "Copy ID" to get the guild ID.
ACCEPTED_GUILD_ID = "123456789123456789"
GUILD_NAME_STRING = "The desired server/guild name in the error message."
# Only change below here if you know what you are doing.
# Ensure flow is only run during OAuth logins via Discord
if context['source'].provider_type != "discord":
return True
# Get the user-source connection object from the context, and get the access token
connection = context.get("goauthentik.io/sources/connection")
if not connection:
return False
access_token = connection.access_token
guilds = requests.get(
"https://discord.com/api/users/@me/guilds",
headers= {
"Authorization": f"Bearer {access_token}",
}
).json()
user_matched = any(ACCEPTED_GUILD_ID == g["id"] for g in guilds)
if not user_matched:
ak_message(f"User is not a member of {GUILD_NAME_STRING}.")
return user_matched
```
Now bind this policy to the chosen enrollment and authentication flows for the Discord OAuth source.
### Checking for membership of a Discord Guild role
:::info
Ensure that the Discord OAuth source in 'Federation & Social login' has the additional `guilds guilds.members.read` scopes added under the 'Protocol settings'.
:::
Create a new 'Expression Policy' with the content below, adjusting the variables where required:
```python
# To get the role and guild ID numbers for the parameters, open Discord, go to Settings > Advanced and
# enable developer mode.
# Right-click on the server/guild title and select "Copy ID" to get the guild ID.
# Right-click on the server/guild title and select server settings > roles, right click on the role and click
# "Copy ID" to get the role ID.
ACCEPTED_ROLE_ID = "123456789123456789"
ACCEPTED_GUILD_ID = "123456789123456789"
GUILD_NAME_STRING = "The desired server/guild name in the error message."
ROLE_NAME_STRING = "The desired role name in the error message."
# Only change below here if you know what you are doing.
GUILD_API_URL = f"https://discord.com/api/users/@me/guilds/{ACCEPTED_GUILD_ID}/member"
# Ensure flow is only run during OAuth logins via Discord
if context['source'].provider_type != "discord":
return True
# Get the user-source connection object from the context, and get the access token
connection = context.get("goauthentik.io/sources/connection")
if not connection:
return False
access_token = connection.access_token
guild_member_object = requests.get(
GUILD_API_URL,
headers= {
"Authorization": f"Bearer {access_token}",
}
).json()
user_matched = any(ACCEPTED_ROLE_ID == g for g in guild_member_object["roles"])
if not user_matched:
ak_message(f"User is not a member of the {ROLE_NAME_STRING} role in {GUILD_NAME_STRING}.")
return user_matched
```
Now bind this policy to the chosen enrollment and authentication flows for the Discord OAuth source.