def _check_errors(response): try: data = response.json() except ValueError: # JSONDecodeError on py3 raise OAuth2Error("Invalid JSON from Battle.net API: %r" % (response.text)) if response.status_code >= 400 or "error" in data: # For errors, we expect the following format: # {"error": "error_name", "error_description": "Oops!"} # For example, if the token is not valid, we will get: # { # "error": "invalid_token", # "error_description": "Invalid access token: abcdef123456" # } # For the profile API, this may also look like the following: # {"code": 403, "type": "Forbidden", "detail": "Account Inactive"} error = data.get("error", "") or data.get("type", "") desc = data.get("error_description", "") or data.get("detail", "") raise OAuth2Error("Battle.net error: %s (%s)" % (error, desc)) # The expected output from the API follows this format: # {"id": 12345, "battletag": "Example#12345"} # The battletag is optional. if "id" not in data: # If the id is not present, the output is not usable (no UID) raise OAuth2Error("Invalid data from Battle.net API: %r" % (data)) return data
def _check_errors(response): # 403 error's are presented as user-facing errors if response.status_code == 403: msg = response.content raise OAuth2Error("Invalid data from GitLab API: %r" % (msg)) try: data = response.json() except ValueError: # JSONDecodeError on py3 raise OAuth2Error("Invalid JSON from GitLab API: %r" % (response.text)) if response.status_code >= 400 or "error" in data: # For errors, we expect the following format: # {"error": "error_name", "error_description": "Oops!"} # For example, if the token is not valid, we will get: # {"message": "status_code - message"} error = data.get("error", "") or response.status_code desc = data.get("error_description", "") or data.get("message", "") raise OAuth2Error("GitLab error: %s (%s)" % (error, desc)) # The expected output from the API follows this format: # {"id": 12345, ...} if "id" not in data: # If the id is not present, the output is not usable (no UID) raise OAuth2Error("Invalid data from GitLab API: %r" % (data)) return data
def complete_login(self, request, app, token, **kwargs): params = {"oauth_token": token.token, "client_id": app.client_id} response = requests.get(self.profile_url, params=params) data = response.json() if response.status_code >= 400: error = data.get("error", "") message = data.get("message", "") raise OAuth2Error("Twitch API Error: %s (%s)" % (error, message)) if "_id" not in data: raise OAuth2Error("Invalid data from Twitch API: %r" % (data)) return self.get_provider().sociallogin_from_response(request, data)
def _check_errors(response): try: data = response.json() except json.decoder.JSONDecodeError: raise OAuth2Error("Invalid JSON from Microsoft Graph API: {}".format( response.text)) if "id" not in data: error_message = "Error retrieving Microsoft profile" microsoft_error_message = data.get("error", {}).get("message") if microsoft_error_message: error_message = ": ".join((error_message, microsoft_error_message)) raise OAuth2Error(error_message) return data
def complete_login(self, request, app, token, **kwargs): resp = requests.get(self.profile_url, params={ 'access_token': token.token, 'alt': 'json' }) resp.raise_for_status() extra_data = resp.json() try: login = self.get_provider() \ .sociallogin_from_response(request, extra_data) except Exception as e: logger.error( f'GoogleOAuth2Adapter.complete_login: error in provider.sociallogin_from_response(): {e}' ) raise login.user.origin = User.USER_ORIGIN_SOCIAL if 'name' in extra_data: login.user.name = extra_data['name'] or login.user.name if not email_follows_pattern(login.user.email): msg = 'Email domain is not allowed' logger.error(f'GoogleOAuth2Adapter.complete_login: {msg}') raise OAuth2Error(msg) return login
def get_access_token(self, code): data = { "grant_type": "authorization_code", "code": code, "app_access_token": self.app_access_token(), } params = None self._strip_empty_keys(data) url = self.access_token_url if self.access_token_method == "GET": params = data data = None # TODO: Proper exception handling resp = requests.request( self.access_token_method, url, params=params, data=json.dumps(data), headers={"Content-Type": "application/json"}, ) resp.raise_for_status() access_token = resp.json() if ( not access_token or "data" not in access_token or "access_token" not in access_token["data"] ): raise OAuth2Error("Error retrieving access token: %s" % resp.content) return access_token["data"]
def get_access_token(self, code): url = self.access_token_url client_secret = self.generate_client_secret() data = { 'client_id': self.consumer_key, 'code': code, 'grant_type': 'authorization_code', 'redirect_uri': self.callback_url, 'client_secret': client_secret } self._strip_empty_keys(data) resp = requests.request(self.access_token_method, url, data=data, headers=self.headers) access_token = None if resp.status_code in [200, 201]: if (resp.headers['content-type'].split(';')[0] == 'application/json' or resp.text[:2] == '{"'): access_token = resp.json() else: access_token = dict(parse_qsl(resp.text)) if not access_token or 'access_token' not in access_token: raise OAuth2Error('Error retrieving access token: %s' % resp.content) return access_token
def get_access_token(self, code): url = self.access_token_url client_secret = self.generate_client_secret() data = { "client_id": self.get_client_id(), "code": code, "grant_type": "authorization_code", "redirect_uri": self.callback_url, "client_secret": client_secret, } self._strip_empty_keys(data) logger.debug(f'[django-allauth] Token request:' f'{self.access_token_method} {url},' f' data: {data},' f' headers: {self.headers}') resp = requests.request(self.access_token_method, url, data=data, headers=self.headers) access_token = None if resp.status_code in [200, 201]: try: access_token = resp.json() except ValueError: access_token = dict(parse_qsl(resp.text)) if not access_token or "access_token" not in access_token: raise OAuth2Error("Error retrieving access token: %s" % resp.content) return access_token
def get_access_token(self, code): data = { "appid": self.consumer_key, "redirect_uri": self.callback_url, "grant_type": "authorization_code", "secret": self.consumer_secret, "scope": self.scope, "code": code, } params = None self._strip_empty_keys(data) url = self.access_token_url if self.access_token_method == "GET": params = data data = None # TODO: Proper exception handling resp = requests.request(self.access_token_method, url, params=params, data=data) access_token = None if resp.status_code == 200: access_token = resp.json() if not access_token or "access_token" not in access_token: raise OAuth2Error("Error retrieving access token: %s" % resp.content) return access_token
def parse_token(self, data, app=None): # parse token header and get relevant public key unverified_header, unverified_claims = jwt.process_jwt( data['id_token']) public_key = self.get_public_key(unverified_header.get('kid')) # verify signature, iat, exp header, claims = jwt.verify_jwt(data['id_token'], public_key, ['RS256'], timedelta(minutes=1), checks_optional=True) # Verify we are the intended audience for the token intended_audiences = [self.intended_aud] if app is not None: intended_audiences.append(app.client_id) if claims.get('aud') is not None and claims.get( 'aud') not in intended_audiences: raise OAuth2Error( "JWT aud {} does not match intended audience {}".format( claims.get('aud'), self.intended_aud)) social_token = SocialToken(token=data['id_token']) social_token.expires_at = datetime.fromtimestamp(claims['iat'], tz=timezone.utc) return social_token
def get_access_token(self, code): data = { "client_id": self.consumer_key, "redirect_url": self.callback_url, "grant_type": "authorization_code", "response_type": "code", "client_secret": self.consumer_secret, "code": code, } params = None self._strip_empty_keys(data) url = self.access_token_url if self.access_token_method == "GET": params = data data = None # Allow custom User Agent to comply with Untappd API settings = app_settings.PROVIDERS.get(UntappdProvider.id, {}) headers = {"User-Agent": settings.get("USER_AGENT", "django-allauth")} # TODO: Proper exception handling resp = requests.request( self.access_token_method, url, params=params, data=data, headers=headers, ) access_token = None if resp.status_code == 200: access_token = resp.json()["response"] if not access_token or "access_token" not in access_token: raise OAuth2Error("Error retrieving access token: %s" % resp.content) return access_token
def get_access_token(self, code): url = self.access_token_url client_secret = self.generate_client_secret() data = { 'client_id': self.get_client_id(), 'code': code, 'grant_type': 'authorization_code', 'redirect_uri': self.callback_url, 'client_secret': client_secret, } self._strip_empty_keys(data) resp = requests.request(self.access_token_method, url, data=data, headers=self.headers) access_token = None if resp.status_code in [200, 201]: try: access_token = resp.json() except ValueError: access_token = dict(parse_qsl(resp.text)) if not access_token or 'access_token' not in access_token: raise OAuth2Error('Error retrieving access token: %s' % resp.content) return access_token
def get_access_token(self, code): data = {'client_id': self.consumer_key, 'redirect_url': self.callback_url, 'grant_type': 'authorization_code', 'response_type': 'code', 'client_secret': self.consumer_secret, 'code': code} params = None self._strip_empty_keys(data) url = self.access_token_url if self.access_token_method == 'GET': params = data data = None # TODO: Proper exception handling resp = requests.request(self.access_token_method, url, params=params, data=data) access_token = None if resp.status_code == 200: access_token = resp.json()['response'] if not access_token or 'access_token' not in access_token: raise OAuth2Error('Error retrieving access token: %s' % resp.content) return access_token
def get_data(self, token): # Verify the user first resp = requests.get( self.identity_url, params={'token': token} ) resp = resp.json() if not resp.get('ok'): raise OAuth2Error() # Fill in their generic info info = { 'name': resp.get('user'), 'user': { 'name': resp.get('user'), 'id': resp.get('user_id') }, 'team': { 'name': resp.get('team'), 'id': resp.get('team_id') } } return info
def _get_cert(self): """Get the UWUM certificate.""" cert = UWUMProvider.settings.get('CERT') if not path.exists(cert): raise OAuth2Error('UWUM certificate not found') return cert
def get_data(self, token): # Verify the user first resp = requests.get(self.identity_url, params={'token': token}) resp = resp.json() if not resp.get('ok'): raise OAuth2Error() return resp
def _check_errors(data): # The expected output from the Battle.net API follows this format: # {"id": 12345, "battletag": "Example#12345"} # The battletag is optional. if "error" in data: # For errors, we expect the following format: # {"error": "error_name", "error_description": "Oops!"} # For example, if the token is not valid, we will get: # { # "error": "invalid_token", # "error_description": "Invalid access token: abcdef123456" # } error = data["error"] desc = data.get("error_description", "") raise OAuth2Error("Battle.net error: %s (%s)" % (error, desc)) elif "id" not in data: # If the id is not present, the output is not usable (no UID) raise OAuth2Error("Invalid data from Battle.net API: %r" % (data))
def get_data(self, token): # Verify the user first hed = {"Authorization": "Bearer " + token} resp = requests.get(self.identity_url, headers=hed) resp = resp.json() if not resp.get("ok"): raise OAuth2Error() return resp
def get_data(self, token): # Verify the user first resp = requests.get( self.identity_url, params={'token': token} ) resp = resp.json() if not resp.get('ok'): raise OAuth2Error(f'UserInfo Exception: {resp.get("error")}') userid = resp.get('user', {}).get('id') user_info = requests.get( self.user_detail_url, params={'token': settings.SLACK_BOT_TOKEN, 'user': userid} ) user_info = user_info.json() if not user_info.get('ok'): raise OAuth2Error(f'UserInfo Exception: {user_info.get("error")}') user_info = user_info.get('user', {}) display_name = user_info.get('profile', {}).get('display_name_normalized') teamid = resp.get('team').get('id') if not resp.get('user', {}).get('email'): resp['user']['email'] = user_info.get('email') resp['user']['display_name'] = display_name resp['user']['username'] = f'{userid}_{teamid}' resp['user']['full_name'] = user_info.get('profile', {}).get('real_name') resp['user']['first_name'] = user_info.get('profile', {}).get('first_name') resp['user']['last_name'] = user_info.get('profile', {}).get('last_name') # This key is not present in the response if the user has not # uploaded an image and the field cannot be None resp['user']['image_original'] = (user_info.get( 'profile', {}).get('image_original') or '') resp['user']['title'] = user_info.get('profile', {}).get('title') resp['user']['timezone'] = user_info.get('tz') return resp
def _get_apple_public_key(self, kid): response = requests.get(self.public_key_url) response.raise_for_status() try: data = response.json() except json.JSONDecodeError as e: raise OAuth2Error("Error retrieving apple public key.") from e for d in data["keys"]: if d["kid"] == kid: return d
def complete_login(self, request, app, token, **kwargs): headers = {'Authorization': 'Bearer {}'.format(token.token)} response = requests.get(self.profile_url, headers=headers) data = response.json() if response.status_code >= 400: error = data.get("error", "") message = data.get("message", "") raise OAuth2Error("Twitch API Error: %s (%s)" % (error, message)) try: user_info = data.get('data', [])[0] except IndexError: raise OAuth2Error("Invalid data from Twitch API: %s" % (data)) if "id" not in user_info: raise OAuth2Error("Invalid data from Twitch API: %s" % (user_info)) return self.get_provider().sociallogin_from_response( request, user_info)
def get_verified_identity_data(self, id_token): provider = self.get_provider() allowed_auds = self.get_client_id(provider) try: public_key = self.get_public_key(id_token) identity_data = jwt.decode(id_token, '', verify=False) return identity_data except jwt.PyJWTError as e: raise OAuth2Error("Invalid id_token") from e
def get_data(self, token): resp = requests.get( self.identity_url, headers={'Authorization': 'Bearer {}'.format(token)}) resp = resp.json() if not resp.get('ok'): raise OAuth2Error() info = { 'user': resp.get('user'), } return info
def pre_social_login(self, request, sociallogin): if sociallogin.is_existing: return if not sociallogin.user.email: raise OAuth2Error( 'Для авторицации необходимо дать доступ к электронному адресу') try: user = User.objects.get(email__iexact=sociallogin.user.email) sociallogin.connect(request, user) except User.DoesNotExist: sociallogin.state['next'] = reverse('profile:edit')
def get_data(self, token): # Verify the user first resp = requests.get(self.identity_url, params={"token": token}) resp = resp.json() print('resp ', resp) if not resp.get("ok"): print('identity error') raise OAuth2Error() return resp
def get_access_token(self, code): """ This whole method is unchanged except for the `params = {"realm": "/individu"}` hack. Original code: https://github.com/pennersr/django-allauth/blob/6a6d3c618ab018234dde8701173093274710ee0a/allauth/socialaccount/providers/oauth2/client.py#L44 """ data = { "redirect_uri": self.callback_url, "grant_type": "authorization_code", "code": code } if self.basic_auth: auth = requests.auth.HTTPBasicAuth(self.consumer_key, self.consumer_secret) else: auth = None data.update({ "client_id": self.consumer_key, "client_secret": self.consumer_secret }) params = {"realm": "/individu"} self._strip_empty_keys(data) url = self.access_token_url if self.access_token_method == "GET": params = data data = None resp = requests.request( self.access_token_method, url, params=params, data=data, headers=self.headers, auth=auth, timeout=settings.REQUESTS_TIMEOUT, ) access_token = None if resp.status_code in [200, 201]: # Weibo sends json via 'text/plain;charset=UTF-8' if resp.headers["content-type"].split( ";")[0] == "application/json" or resp.text[:2] == '{"': access_token = resp.json() else: access_token = dict(parse_qsl(resp.text)) if not access_token or "access_token" not in access_token: raise OAuth2Error("Error retrieving access token: %s" % resp.content) return access_token
def complete_login(self, request, app, token, **kwargs): resp = requests.post(self.profile_url, json={}, headers={'Authorization': f'Bearer {token.token}'}) resp.raise_for_status() extra_data = resp.json() login = self.get_provider() \ .sociallogin_from_response(request, extra_data) login.user.origin = User.USER_ORIGIN_SOCIAL if 'name' in extra_data: login.user.name = extra_data['name'] or login.user.name if not email_follows_pattern(login.user.email): raise OAuth2Error(f'Email domain is not allowed') return login
def complete_login(self, request, app, token, **kwargs): resp = requests.get( self.user_info_url, headers={ 'Content-Type': 'application/json', 'Authorization': f'Bearer {token}', }, ) resp.raise_for_status() extra_data = resp.json() if extra_data['code'] != 0: raise OAuth2Error("Error retrieving code: %s" % resp.content) extra_data = extra_data['data'] return self.get_provider().sociallogin_from_response( request, extra_data)
def complete_login(self, request, app, token, **kwargs): resp = requests.get( self.user_info_url, headers={ "Content-Type": "application/json", "Authorization": "Bearer " + token.token, }, ) resp.raise_for_status() extra_data = resp.json() if extra_data["code"] != 0: raise OAuth2Error("Error retrieving code: %s" % resp.content) extra_data = extra_data["data"] return self.get_provider().sociallogin_from_response( request, extra_data)
def test_custom_500_view__ip_restricted_error(render): try: # raise this to populate info for # call to sys.exec_info() in the view raise OAuth2Error( 'Error retrieving access token: b\'{"error":"invalid_grant","error_description":"ip restricted"}\'' ) except OAuth2Error: allow_list = "0.0.0.1, 0.0.0.2, 0.0.0.3" with mock.patch("metadeploy.views.IP_RESTRICTED_MESSAGE", allow_list): factory = RequestFactory() request = factory.get("/accounts/salesforce/login/callback/") request.user = AnonymousUser() custom_500_view(request) assert allow_list == render.call_args[1]["context"]["JS_CONTEXT"]["error_message"]