sources/oauth: add Twitch OAuth source (#3746)

* sources/oauth: add Twitch OAuth source

Signed-off-by: Lukas Vögl <lukas@voegl.org>

* website/integrations: add Twitch OAuth source documentation

Signed-off-by: Lukas Vögl <lukas@voegl.org>

Signed-off-by: Lukas Vögl <lukas@voegl.org>
This commit is contained in:
lvoegl 2022-10-10 10:59:07 +02:00 committed by GitHub
parent a96b7dd9a3
commit 3ecc715e91
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 189 additions and 0 deletions

View file

@ -17,6 +17,7 @@ AUTHENTIK_SOURCES_OAUTH_TYPES = [
"authentik.sources.oauth.types.reddit",
"authentik.sources.oauth.types.twitter",
"authentik.sources.oauth.types.mailcow",
"authentik.sources.oauth.types.twitch",
]

View file

@ -115,6 +115,16 @@ class GitHubOAuthSource(OAuthSource):
verbose_name_plural = _("GitHub OAuth Sources")
class TwitchOAuthSource(OAuthSource):
"""Social Login using Twitch."""
class Meta:
abstract = True
verbose_name = _("Twitch OAuth Source")
verbose_name_plural = _("Twitch OAuth Sources")
class MailcowOAuthSource(OAuthSource):
"""Social Login using Mailcow."""

View file

@ -0,0 +1,37 @@
"""Twitch Type tests"""
from django.test import TestCase
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.twitch import TwitchOAuth2Callback
# https://dev.twitch.tv/docs/authentication/getting-tokens-oidc/#getting-claims-information-from-an-access-token
TWITCH_USER = {
"aud": "ym2tq9o71tikh2zyebksiture1hzg5",
"exp": 1665261184,
"iat": 1665260184,
"iss": "https://id.twitch.tv/oauth2",
"sub": "603916897",
"email": "foo@bar.baz",
"preferred_username": "FooBar",
}
class TestTypeTwitch(TestCase):
"""OAuth Source tests"""
def setUp(self):
self.source = OAuthSource.objects.create(
name="test",
slug="test",
provider_type="twitch",
authorization_url="",
profile_url="",
consumer_key="",
)
def test_enroll_context(self):
"""Test twitch Enrollment context"""
ak_context = TwitchOAuth2Callback().get_user_enroll_context(TWITCH_USER)
self.assertEqual(ak_context["username"], TWITCH_USER["preferred_username"])
self.assertEqual(ak_context["email"], TWITCH_USER["email"])
self.assertEqual(ak_context["name"], TWITCH_USER["preferred_username"])

View file

@ -0,0 +1,60 @@
"""Twitch OAuth Views"""
from json import dumps
from typing import Any, Optional
from authentik.sources.oauth.clients.oauth2 import UserprofileHeaderAuthClient
from authentik.sources.oauth.types.registry import SourceType, registry
from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
class TwitchClient(UserprofileHeaderAuthClient):
"""Twitch needs the token_type to be capitalized for the request header."""
def get_profile_info(self, token: dict[str, str]) -> Optional[dict[str, Any]]:
token["token_type"] = token["token_type"].capitalize()
return super().get_profile_info(token)
class TwitchOAuthRedirect(OAuthRedirect):
"""Twitch OAuth2 Redirect"""
def get_additional_parameters(self, source): # pragma: no cover
claims = {"userinfo": {"email": None, "preferred_username": None}}
return {
"scope": ["openid"],
"claims": dumps(claims),
}
class TwitchOAuth2Callback(OAuthCallback):
"""Twitch OAuth2 Callback"""
client_class = TwitchClient
def get_user_id(self, info: dict[str, str]) -> str:
return info.get("sub", "")
def get_user_enroll_context(
self,
info: dict[str, Any],
) -> dict[str, Any]:
return {
"username": info.get("preferred_username"),
"email": info.get("email"),
"name": info.get("preferred_username"),
}
@registry.register()
class TwitchType(SourceType):
"""Twitch Type definition"""
callback_view = TwitchOAuth2Callback
redirect_view = TwitchOAuthRedirect
name = "Twitch"
slug = "twitch"
authorization_url = "https://id.twitch.tv/oauth2/authorize"
access_token_url = "https://id.twitch.tv/oauth2/token" # nosec
profile_url = "https://id.twitch.tv/oauth2/userinfo"

View file

@ -35104,6 +35104,7 @@ components:
- reddit
- twitter
- mailcow
- twitch
type: string
ProxyMode:
enum:

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 23.0.6, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 2400 2800" style="enable-background:new 0 0 2400 2800;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#9146FF;}
</style>
<title>Asset 2</title>
<g>
<polygon class="st0" points="2200,1300 1800,1700 1400,1700 1050,2050 1050,1700 600,1700 600,200 2200,200 "/>
<g>
<g id="Layer_1-2">
<path class="st1" d="M500,0L0,500v1800h600v500l500-500h400l900-900V0H500z M2200,1300l-400,400h-400l-350,350v-350H600V200h1600 V1300z"/>
<rect x="1700" y="550" class="st1" width="200" height="600"/>
<rect x="1150" y="550" class="st1" width="200" height="600"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 887 B

View file

@ -0,0 +1,60 @@
---
title: Twitch
---
<span class="badge badge--secondary">Support level: Community</span>
Allows users to authenticate using their Twitch credentials
## Preparation
The following placeholders will be used:
- `authentik.company` is the FQDN of the authentik install.
## Twitch
1. Click **Register Your Application** in the Twitch Developers Console https://dev.twitch.tv/console
![Register Your Application Button](twitch1.png)
2. Name your Application
3. Add https://authentik.company/source/oauth/callback/twitch in the **OAuth Redirect URLs** field
4. Select a Category for your Application
5. Click **Create** to finish the registration of your Application
![Create Application](twitch2.png)
6. Click **Manage** on your newly created Application
![Manage Application](twitch3.png)
7. Copy your Client ID and save it for later
8. Click **New Secret** to create a new Secret
9. Copy the above Secret and also save it for later
![Copy Keys](twitch4.png)
## authentik
10. Under _Directory -> Federation & Social login_ Click **Create Twitch OAuth Source**
11. **Name:** Choose a name (For the example I used Twitch)
12. **Slug:** twitch (You can choose a different slug, if you do you will need to update the Twitch redirect URL and point it to the correct slug.)
13. **Consumer Key:** Client ID from step 7
14. **Consumer Secret:** Secret from step 9
Here is an example of a complete authentik Twitch OAuth Source
![Authentik Source Example](twitch5.png)
Save, and you now have Twitch as a source.
:::note
For more details on how-to have the new source display on the Login Page see [here](../).
:::

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View file

@ -137,6 +137,7 @@ module.exports = {
"sources/github/index",
"sources/google/index",
"sources/mailcow/index",
"sources/twitch/index",
"sources/plex/index",
"sources/twitter/index",
],