В итоге я использовал Tornado httpclient
для отправки запросов на сервер OpenID.
import base64
import urllib.parse
import json
import tornado.httpclient
from .base import BaseHandler
from settings import OID_AUTH_API, OID_REDIRECT_URI, OID_CLIENT_ID, OID_CLIENT_PASSWORD
from lib import logger
class LoginHandler(BaseHandler):
_redirect_uri = urllib.parse.quote(OID_REDIRECT_URI, safe='')
_scope = 'openid+profile+email'
_response_type = 'code'
_http_client = tornado.httpclient.AsyncHTTPClient()
async def get(self):
try:
code = self.get_argument('code', None)
if (code is None):
self.redirect('%s/authorization?client_id=%s&scope=%s&response_type=%s&redirect_uri=%s' % (
OID_AUTH_API, OID_CLIENT_ID, self._scope, self._response_type, self._redirect_uri), self.request.uri)
return
# exchange the authorization code with the access token
grant_type = 'authorization_code'
redirect_uri = self._redirect_uri
authorization_header = '%s:%s' % (
OID_CLIENT_ID, OID_CLIENT_PASSWORD)
authorization_header_encoded = base64.b64encode(
authorization_header.encode('UTF-8')).decode('UTF-8')
url = '%s/token?grant_type=%s&code=%s&redirect_uri=%s' % (
OID_AUTH_API, grant_type, code, redirect_uri)
token_exchange_response = await self._http_client.fetch(
url,
method='POST',
headers={
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic %s' % authorization_header_encoded,
'Accept': 'application/json'
},
body='')
token_exchange_response_body_dict = json.loads(
token_exchange_response.body)
access_token = token_exchange_response_body_dict.get(
'access_token')
self.send_response({
'access_token': access_token
})
except tornado.httpclient.HTTPClientError as error:
logger.log_error(error.response.body.decode('UTF-8'))
self.send_response({
'success': False,
'message': 'Error occurred while trying to obtain the access token'
}, 500)
except Exception as error:
logger.log_error_with_traceback(error)
self.send_response({
'success': False,
'message': 'Internal server error. Please try again later.'
}, 500)