sources/oauth2: migrate to microsoft graph instead of azure graph

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-08-21 15:12:18 +02:00
parent 93e27d1959
commit 2a90c0b35e
3 changed files with 64 additions and 7 deletions

View File

@ -14,9 +14,6 @@ from django.http.response import Http404
from django_redis.exceptions import ConnectionInterrupted from django_redis.exceptions import ConnectionInterrupted
from docker.errors import DockerException from docker.errors import DockerException
from ldap3.core.exceptions import LDAPException from ldap3.core.exceptions import LDAPException
# pylint: disable=no-name-in-module
from psycopg2.errors import Error
from redis.exceptions import ConnectionError as RedisConnectionError from redis.exceptions import ConnectionError as RedisConnectionError
from redis.exceptions import RedisError, ResponseError from redis.exceptions import RedisError, ResponseError
from rest_framework.exceptions import APIException from rest_framework.exceptions import APIException
@ -48,6 +45,9 @@ class SentryIgnoredException(Exception):
def before_send(event: dict, hint: dict) -> Optional[dict]: def before_send(event: dict, hint: dict) -> Optional[dict]:
"""Check if error is database error, and ignore if so""" """Check if error is database error, and ignore if so"""
# pylint: disable=no-name-in-module
from psycopg2.errors import Error
ignored_classes = ( ignored_classes = (
# Inbuilt types # Inbuilt types
KeyboardInterrupt, KeyboardInterrupt,

View File

@ -0,0 +1,46 @@
"""azure ad Type tests"""
from django.test import TestCase
from authentik.sources.oauth.models import OAuthSource
from authentik.sources.oauth.types.azure_ad import AzureADOAuthCallback
# https://docs.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http#response-2
AAD_USER = {
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"@odata.id": (
"https://graph.microsoft.com/v2/7ce9b89e-646a-41d2-9fa6-8371c6a8423d/"
"directoryObjects/018b0aff-8aff-473e-bf9c-b50e27f52208/Microsoft.DirectoryServices.User"
),
"businessPhones": [],
"displayName": "foo bar",
"givenName": "foo",
"jobTitle": None,
"mail": "foo@beryju.org",
"mobilePhone": None,
"officeLocation": None,
"preferredLanguage": None,
"surname": "bar",
"userPrincipalName": "foo@beryju.org",
"id": "018b0aff-8aff-473e-bf9c-b50e27f52208",
}
class TestTypeAzureAD(TestCase):
"""OAuth Source tests"""
def setUp(self):
self.source = OAuthSource.objects.create(
name="test",
slug="test",
provider_type="openid-connect",
authorization_url="",
profile_url="",
consumer_key="",
)
def test_enroll_context(self):
"""Test azure_ad Enrollment context"""
ak_context = AzureADOAuthCallback().get_user_enroll_context(AAD_USER)
self.assertEqual(ak_context["username"], AAD_USER["displayName"])
self.assertEqual(ak_context["email"], AAD_USER["mail"])
self.assertEqual(ak_context["name"], AAD_USER["displayName"])

View File

@ -8,10 +8,20 @@ from structlog.stdlib import get_logger
from authentik.sources.oauth.clients.oauth2 import OAuth2Client from authentik.sources.oauth.clients.oauth2 import OAuth2Client
from authentik.sources.oauth.types.manager import MANAGER, SourceType from authentik.sources.oauth.types.manager import MANAGER, SourceType
from authentik.sources.oauth.views.callback import OAuthCallback from authentik.sources.oauth.views.callback import OAuthCallback
from authentik.sources.oauth.views.redirect import OAuthRedirect
LOGGER = get_logger() LOGGER = get_logger()
class AzureADOAuthRedirect(OAuthRedirect):
"""Azure AD OAuth2 Redirect"""
def get_additional_parameters(self, source): # pragma: no cover
return {
"scope": "openid https://graph.microsoft.com/User.Read",
}
class AzureADClient(OAuth2Client): class AzureADClient(OAuth2Client):
"""Azure AD Oauth client, azure ad doesn't like the ?access_token that is sent by default""" """Azure AD Oauth client, azure ad doesn't like the ?access_token that is sent by default"""
@ -42,7 +52,7 @@ class AzureADOAuthCallback(OAuthCallback):
def get_user_id(self, info: dict[str, Any]) -> Optional[str]: def get_user_id(self, info: dict[str, Any]) -> Optional[str]:
try: try:
return str(UUID(info.get("objectId")).int) return str(UUID(info.get("id")).int)
except TypeError: except TypeError:
return None return None
@ -63,11 +73,12 @@ class AzureADType(SourceType):
"""Azure AD Type definition""" """Azure AD Type definition"""
callback_view = AzureADOAuthCallback callback_view = AzureADOAuthCallback
redirect_view = AzureADOAuthRedirect
name = "Azure AD" name = "Azure AD"
slug = "azure-ad" slug = "azure-ad"
urls_customizable = True urls_customizable = True
authorization_url = "https://login.microsoftonline.com/common/oauth2/authorize" authorization_url = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"
access_token_url = "https://login.microsoftonline.com/common/oauth2/token" # nosec access_token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec
profile_url = "https://graph.windows.net/myorganization/me?api-version=1.6" profile_url = "https://graph.microsoft.com/v1.0/me"