def _debug_token(self, access_token, id_token=None) -> OAuth2TokenPack: """ Debug adnd get access token that was sent by Mobile SDK :param access_token: :return: """ res = requests.get( self.__verify_token_uri(version=self.channel.api_version), params={'access_token': access_token}) if res.status_code != 200: body = res.json() error, desc = self._get_error(body, action='get_token') logger.warn('Verify access token failed', style='hybrid', provider=self.provider.upper(), **body) self._raise_error(error=self.ERROR_GET_TOKEN_FAILED, msg='{}: {}'.format(error, desc)) token_info = res.json() client_id = token_info['client_id'] if client_id != self.channel.client_id: logger.warn('Access token does not belong to current app', client_id=client_id, expected=self.channel.client_id) raise PermissionDeniedError('Illegal access token') return OAuth2TokenPack(access_token=access_token, expires_in=token_info['expires_in'], token_type='Bearer', id_token=id_token)
def _get_profile_oa1( self, token_tup: Tuple[str, str]) -> Tuple[str, Dict[str, Any]]: profile_uri = self.__profile_uri__(version=self.channel.api_version, numeric_format=True) auth = self.create_authorization_header( method='GET', url=profile_uri, consumer_key=self.channel.client_id, consumer_secret=self.channel.client_secret, oauth_token_secret=token_tup[1], oauth_token=token_tup[0], include_entities='false', skip_status='true', include_email='true') res = requests.get(profile_uri, headers={'Authorization': auth}, params={ 'include_entities': 'false', 'skip_status': 'true', 'include_email': 'true' }) if res.status_code != 200: body = res.json() logger.warn('Getting profile failed', code=res.status_code, **body) self._raise_error(error=self.ERROR_GET_PROFILE_FAILED, msg='Getting profile failed') return self._parse_attributes(response=res.json())
def _get_token(self, code) -> OAuth2TokenPack: """ Get OAuth2 access token by authorization code :param code: :return: """ res = requests.post( self.__token_uri__(version=self.channel.api_version), data={ 'grant_type': 'authorization_code', 'code': code, 'redirect_uri': self.__provider_callback_uri__(), 'client_id': self.channel.client_id, 'client_secret': self.channel.client_secret }) if res.status_code != 200: body = res.json() error, desc = self._get_error(body, action='get_token') logger.warn('Getting access token failed', style='hybrid', provider=self.provider.upper(), **body) self._raise_error(error=self.ERROR_GET_TOKEN_FAILED, msg='{}: {}'.format(error, desc)) return OAuth2TokenPack(data=res.json())
def _parse_oauth_state(self, state: str) -> Tuple[AuthLogs, OAuthSessionParams]: try: log_id, args = jwt_token_helper.decode(token=state) log: Optional[AuthLogs] = AuthLogs.query.filter_by( _id=log_id).one_or_none() if not log or log.nonce != args.get('_nonce'): logger.debug('Invalid OAuth state or nonce does not match') raise BadRequestError('Invalid OAuth state') if log.status != AuthLogs.STATUS_UNKNOWN: logger.debug( 'Validate OAuth state failed. Illegal auth log status.', status=log.status, expected=AuthLogs.STATUS_UNKNOWN) raise BadRequestError('Invalid OAuth state') if log.provider != self.provider: logger.warn( 'Provider in OAuth state does not match with current provider', provider=log.provider, expected=self.provider) raise PermissionDeniedError( 'OAuth state invalid, provider does not match') return log, OAuthSessionParams(data=args) except TokenParseError as e: logger.warning('Parse OAuth state failed', error=e.message, token=state) raise BadRequestError('Invalid OAuth state')
def _verify_auth_request(auth_token, params): log, args = parse_auth_token(auth_token=auth_token) api_key = params.get('api_key') if api_key: expected = (db.session.query(Apps.api_key).filter_by( _id=log.app_id, _deleted=0).scalar()) if expected != api_key: raise UnauthorizedError('API key authorization failed') else: code_challenge = args.get('code_challenge') verifier = params.get('code_verifier', '') if not _verify_code_verifier(verifier=verifier, challenge=code_challenge): logger.warn('code_verifier does not match', verifier=verifier) raise UnauthorizedError('code_verifier does not match') return log, args
def _get_token(self, code: str): res = requests.get( self.__token_uri__(version=self.channel.api_version), params={ 'code': code, 'redirect_uri': self.__provider_callback_uri__(), 'client_id': self.channel.client_id, 'client_secret': self.channel.client_secret }) if res.status_code != 200: body = res.json() error, desc = self._get_error(body, action='get_token') logger.warn('Getting access token failed', provider=self.provider.upper(), **body) self._raise_error(error=self.ERROR_GET_TOKEN_FAILED, msg='{}: {}'.format(error, desc)) return res.json()
def _get_profile( self, token_pack: OAuth2TokenPack) -> Tuple[str, Dict[str, Any]]: fields = self.channel.get_required_fields() res = requests.get( self.__profile_uri__(version=self.channel.api_version), params={ 'fields': ','.join(fields), 'access_token': token_pack.access_token }) if res.status_code != 200: body = res.json() logger.warn('Getting profile failed', style='hybrid', provider=self.provider.upper(), **body) self._raise_error( error=self.ERROR_GET_PROFILE_FAILED, msg='Getting user attributes from provider failed') return self._parse_attributes(response=res.json(), nofilter=True)
def _get_token_oa1(self, oauth_verifier: str) -> Tuple[str, str]: token_uri = self.__token_uri__(version=self.channel.api_version) auth = self.create_authorization_header( method='POST', url=token_uri, consumer_key=self.channel.client_id, consumer_secret=self.channel.client_secret, oauth_token_secret=self.log.oa1_secret, oauth_token=self.log.oa1_token) res = requests.post(token_uri, headers={'Authorization': auth}, data={'oauth_verifier': oauth_verifier}) if res.status_code != 200: body = up.parse_qs(res.text) logger.warn('Getting access token failed', code=res.status_code, **body) self._raise_error(error=self.ERROR_GET_TOKEN_FAILED, msg='Getting access token failed') body = up.parse_qs(res.text) return body['oauth_token'][0], body['oauth_token_secret'][0]
def _get_profile( self, token_pack: OAuth2TokenPack) -> Tuple[str, Dict[str, Any]]: """ Get profile attributes of authenticated profile :param token_pack: :return: """ authorization = token_pack.token_type + ' ' + token_pack.access_token res = requests.get( self.__profile_uri__(version=self.channel.api_version), headers={'Authorization': authorization}) if res.status_code != 200: body = res.json() logger.warn('Getting profile failed', style='hybrid', provider=self.provider.upper(), **body) self._raise_error( error=self.ERROR_GET_PROFILE_FAILED, msg='Getting user attributes from provider failed') return self._parse_attributes(response=res.json())
def _build_authorize_uri(self, state): callback_uri = add_params_to_uri(self.__provider_callback_uri__(), state=state) auth = self.create_authorization_header( method='POST', url=self.REQUEST_TOKEN_URI, consumer_key=self.channel.client_id, consumer_secret=self.channel.client_secret, oauth_callback=callback_uri) res = requests.post(self.REQUEST_TOKEN_URI, headers={'Authorization': auth}) if res.status_code != 200: body = up.parse_qs(res.text) logger.warn('Getting request token failed', code=res.status_code, **body) self._raise_error(error=self.ERROR_GET_TOKEN_FAILED, msg='Getting request token failed') body = up.parse_qs(res.text) if not body['oauth_callback_confirmed'][0]: logger.warn('Getting request token failed', oauth_callback_confirmed=0) self._raise_error( error=self.ERROR_GET_TOKEN_FAILED, msg= 'Getting request token failed: oauth_callback_confirmed=false') token = body['oauth_token'][0] secret = body['oauth_token_secret'][0] self.log.oa1_token = token self.log.oa1_secret = secret uri = add_params_to_uri( uri=self.__authorize_uri__(version=self.channel.api_version), oauth_token=token) return uri
def _get_profile(self, token_pack: OAuth2TokenPack): perms = self.channel.get_permissions() fields = self.channel.get_required_fields() if 'email' in perms and 'emailAddresses' not in fields: fields.append('emailAddresses') fields.remove('#') res = requests.get( self.__profile_uri__(version=self.channel.api_version), params={ 'personFields': ','.join(fields), 'access_token': token_pack.access_token }) if res.status_code != 200: body = res.json() logger.warn('Getting profile failed', style='hybrid', provider=self.provider.upper(), **body) self._raise_error( error=self.ERROR_GET_PROFILE_FAILED, msg='Getting user attributes from provider failed') return self._parse_attributes(response=res.json(), nofilter=True)