From 29d5962c4cb335aeac34f37b46d72916c1e31a44 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 14 Mar 2019 21:18:55 +0100 Subject: [PATCH] add Azure AD Source --- .../templates/passbook-configmap.yaml | 1 + passbook/lib/default.yml | 1 + passbook/oauth_client/forms.py | 14 +++++ .../oauth_client/source_types/azure_ad.py | 52 +++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 passbook/oauth_client/source_types/azure_ad.py diff --git a/helm/passbook/templates/passbook-configmap.yaml b/helm/passbook/templates/passbook-configmap.yaml index 538fbfc7a..8283e8d20 100644 --- a/helm/passbook/templates/passbook-configmap.yaml +++ b/helm/passbook/templates/passbook-configmap.yaml @@ -123,6 +123,7 @@ data: - passbook.oauth_client.source_types.reddit - passbook.oauth_client.source_types.supervisr - passbook.oauth_client.source_types.twitter + - passbook.oauth_client.source_types.azure_ad saml_idp: signing: true autosubmit: false diff --git a/passbook/lib/default.yml b/passbook/lib/default.yml index 032800e2e..ab1015d9e 100644 --- a/passbook/lib/default.yml +++ b/passbook/lib/default.yml @@ -85,6 +85,7 @@ oauth_client: - passbook.oauth_client.source_types.reddit - passbook.oauth_client.source_types.supervisr - passbook.oauth_client.source_types.twitter + - passbook.oauth_client.source_types.azure_ad saml_idp: # List of python packages with provider types to load. types: diff --git a/passbook/oauth_client/forms.py b/passbook/oauth_client/forms.py index cd9036316..3f4db257e 100644 --- a/passbook/oauth_client/forms.py +++ b/passbook/oauth_client/forms.py @@ -108,3 +108,17 @@ class GoogleOAuthSourceForm(OAuthSourceForm): 'access_token_url': 'https://accounts.google.com/o/oauth2/token', 'profile_url': ' https://www.googleapis.com/oauth2/v1/userinfo', } + + +class AzureADOAuthSourceForm(OAuthSourceForm): + """OAuth Source form with pre-determined URL for AzureAD""" + + class Meta(OAuthSourceForm.Meta): + + overrides = { + 'provider_type': 'azure_ad', + 'request_token_url': '', + 'authorization_url': 'https://login.microsoftonline.com/common/oauth2/authorize', + 'access_token_url': 'https://login.microsoftonline.com/common/oauth2/token', + 'profile_url': ' https://login.microsoftonline.com/common/openid/userinfo', + } diff --git a/passbook/oauth_client/source_types/azure_ad.py b/passbook/oauth_client/source_types/azure_ad.py new file mode 100644 index 000000000..3dd2c41b6 --- /dev/null +++ b/passbook/oauth_client/source_types/azure_ad.py @@ -0,0 +1,52 @@ +"""AzureAD OAuth2 Views""" +import json +import uuid +from logging import getLogger + +from requests.exceptions import RequestException + +from passbook.oauth_client.clients import OAuth2Client +from passbook.oauth_client.source_types.manager import MANAGER, RequestKind +from passbook.oauth_client.utils import user_get_or_create +from passbook.oauth_client.views.core import OAuthCallback + +LOGGER = getLogger(__name__) + + +class AzureADOAuth2Client(OAuth2Client): + """AzureAD OAuth2 Client""" + + def get_profile_info(self, raw_token): + "Fetch user profile information." + try: + token = json.loads(raw_token)['access_token'] + headers = { + 'Authorization': 'Bearer %s' % token + } + response = self.request('get', self.source.profile_url, + headers=headers) + response.raise_for_status() + except RequestException as exc: + LOGGER.warning('Unable to fetch user profile: %s', exc) + return None + else: + return response.json() or response.text + + +@MANAGER.source(kind=RequestKind.callback, name='Azure AD') +class AzureADOAuthCallback(OAuthCallback): + """AzureAD OAuth2 Callback""" + + client_class = AzureADOAuth2Client + + def get_user_id(self, source, info): + return uuid.UUID(info.get('objectId')).int + + def get_or_create_user(self, source, access, info): + user_data = { + 'username': info.get('displayName'), + 'email': info.get('mail', None) or info.get('otherMails')[0], + 'name': info.get('displayName'), + 'password': None, + } + return user_get_or_create(**user_data)