Commit e6959ba8 authored by Jérome Perrin's avatar Jérome Perrin

oauth2_authorisation: py3

parent 4f423de4
......@@ -70,7 +70,7 @@ from DateTime import DateTime
from Products.ERP5Type import Permissions
from Products.ERP5Type.Message import translateString
from Products.ERP5Type.UnrestrictedMethod import super_user
from Products.ERP5Type.Utils import bytes2str, str2bytes, unicode2str
from Products.ERP5Type.Utils import bytes2str, str2bytes, unicode2str, str2unicode
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Security.ERP5GroupManager import (
disableCache as ERP5GroupManager_disableCache,
......@@ -196,6 +196,7 @@ def substituteRequest(
request_container.REQUEST = inner_request
try:
__traceback_info__ = inner_request
print('inner_request =>', inner_request.text())
yield inner_request
finally:
request_container.REQUEST = request_from_container
......@@ -448,7 +449,7 @@ class _ERP5AuthorisationEndpoint(AuthorizationEndpoint):
}
for x in (
portal.portal_categories.resolveCategory(
'oauth2_scope/' + y.encode('utf-8'),
'oauth2_scope/' + unicode2str(y),
)
for y in scope_list
)
......@@ -699,7 +700,7 @@ class _ERP5RequestValidator(RequestValidator):
client_value=request.client.erp5_client_value,
redirect_uri=request.redirect_uri,
scope_list=[
x.encode('utf-8')
unicode2str(x)
for x in request.scopes
],
code_challenge=request.code_challenge,
......@@ -859,13 +860,13 @@ def _callEndpoint(endpoint, self, REQUEST):
# not have to care about intermediate proxies).
request_header_dict['X_FORWARDED_FOR'] = REQUEST.getClientAddr()
request_body = REQUEST.get('BODY')
if request_body is None and content_type == 'application/x-www-form-urlencoded':
if (not request_body) and content_type == 'application/x-www-form-urlencoded':
# XXX: very imperfect, but should be good enough for OAuth2 usage:
# no standard OAuth2 POST field should be marshalled by Zope.
request_body = urlencode([
(x, y)
for x, y in six.iteritems(REQUEST.form)
if isinstance(y, six.text_type)
if isinstance(y, six.string_types)
])
uri = other.get('URL', '')
query_string = environ.get('QUERY_STRING')
......@@ -1316,7 +1317,7 @@ class OAuth2AuthorisationServerConnector(XMLObject):
Validate non-standard jwt claims against request.
"""
if not isAddressInNetworkList(
address=request.headers['X_FORWARDED_FOR'].decode('utf-8'),
address=str2unicode(request.headers['X_FORWARDED_FOR']),
network_list=token[JWT_CLAIM_NETWORK_LIST_KEY],
):
raise jwt.InvalidTokenError
......@@ -1399,9 +1400,9 @@ class OAuth2AuthorisationServerConnector(XMLObject):
def _getSessionValueFromTokenDict(self, token_dict):
session_value = self._getSessionValue(
token_dict[JWT_PAYLOAD_KEY][
unicode2str(token_dict[JWT_PAYLOAD_KEY][
JWT_PAYLOAD_AUTHORISATION_SESSION_ID_KEY
].encode('utf-8'),
]),
'validated',
)
if session_value is not None:
......
......@@ -5,17 +5,20 @@ Mutate REQUEST to call standard OAuth2 /authorize endpoint from an ERP5 Form in
import json
import six
from erp5.component.document.OAuth2AuthorisationServerConnector import substituteRequest
from Products.ERP5Type.Utils import unicode2str
# XXX: Accessing REQUEST from acquisition is bad. But Base_callDialogMethod
# does not propagate the request cleanly, so no other way so far.
REQUEST = context.REQUEST
form = {
key.encode('utf-8'): value.encode('utf-8')
unicode2str(key): unicode2str(value)
for key, value in six.iteritems(json.loads(request_info_json))
}
if scope_list:
form['scopes'] = ' '.join(scope_list)
portal = context.getPortalObject()
from pprint import pprint
pprint(('substituteRequest form', substituteRequest))
with substituteRequest(
context=portal,
request=REQUEST,
......
......@@ -44,6 +44,8 @@ form = dict(parse_qsl(parsed_came_from.query))
login_retry_url = REQUEST.form.get('login_retry_url')
if login_retry_url is not None:
form['login_retry_url'] = login_retry_url
from pprint import pprint
pprint(('logged_in_once substituteRequest', form))
with substituteRequest(
context=portal,
request=REQUEST,
......
......@@ -45,7 +45,7 @@ from six.moves.urllib.parse import parse_qsl, quote, unquote, urlencode, urlspli
from AccessControl.SecurityManagement import getSecurityManager, setSecurityManager
from DateTime import DateTime
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.ERP5Type.Utils import bytes2str, str2bytes
from Products.ERP5Type.Utils import bytes2str, str2bytes, unicode2str
from Products.ERP5.ERP5Site import (
ERP5_AUTHORISATION_EXTRACTOR_USERNAME_NAME,
ERP5_AUTHORISATION_EXTRACTOR_PASSWORD_NAME,
......@@ -81,7 +81,7 @@ class FormExtractor(HTMLParser):
elif self.__in_form and tag in _HTML_FIELD_TAG_SET:
self.form_list[-1][1].append((
attr_dict['name'],
attr_dict.get('value', '').encode('utf-8'),
unicode2str(attr_dict.get('value', ''))
))
def handle_endtag(self, tag):
......@@ -853,13 +853,13 @@ class TestOAuth2(ERP5TypeTestCase):
path=oauth2_server_connector + '/token',
method='POST',
content_type='application/x-www-form-urlencoded',
body=urlencode({
body=str2bytes(urlencode({
'grant_type': 'authorization_code',
'code': authorisation_code,
'client_id': client_id,
'code_verifier': code_verifier,
'redirect_uri': _EXTERNAL_CLIENT_REDIRECT_URI,
}),
})),
)
time_after = int(time())
self.assertEqual(status, 200, response)
......@@ -881,10 +881,10 @@ class TestOAuth2(ERP5TypeTestCase):
path=oauth2_server_connector + '/token',
method='POST',
content_type='application/x-www-form-urlencoded',
body=urlencode({
body=str2bytes(urlencode({
'grant_type': 'refresh_token',
'refresh_token': refresh_token,
}),
})),
)
self.assertEqual(status, 200)
self.assertEqual(cookie_dict, {})
......@@ -898,10 +898,10 @@ class TestOAuth2(ERP5TypeTestCase):
path=oauth2_server_connector + '/revoke',
method='POST',
content_type='application/x-www-form-urlencoded',
body=urlencode({
body=str2bytes(urlencode({
'token_type_hint': 'refresh_token',
'token': refresh_token,
}),
})),
)
self.assertEqual(status, 200)
self.assertEqual(cookie_dict, {})
......@@ -914,10 +914,10 @@ class TestOAuth2(ERP5TypeTestCase):
path=oauth2_server_connector + '/token',
method='POST',
content_type='application/x-www-form-urlencoded',
body=urlencode({
body=str2bytes(urlencode({
'grant_type': 'refresh_token',
'refresh_token': refresh_token,
}),
})),
)
self.assertEqual(status, 400)
self.assertEqual(cookie_dict, {})
......
......@@ -51,7 +51,7 @@ from OFS.Traversable import NotFound
from Products.ERP5Type import Permissions
from Products.ERP5Type.XMLObject import XMLObject
from Products.ERP5Type.Timeout import getTimeLeft
from Products.ERP5Type.Utils import bytes2str, str2bytes, str2unicode
from Products.ERP5Type.Utils import bytes2str, unicode2str, str2bytes, str2unicode
from Products.ERP5Security.ERP5OAuth2ResourceServerPlugin import (
OAuth2AuthorisationClientConnectorMixIn,
ERP5OAuth2ResourceServerPlugin,
......@@ -313,7 +313,7 @@ class _OAuth2AuthorisationServerProxy(object):
def getAccessTokenSignatureAlgorithmAndPublicKeyList(self):
return tuple(
(signature_algorithm.encode('ascii'), public_key.encode('ascii'))
(unicode2str(signature_algorithm), unicode2str(public_key))
for signature_algorithm, public_key in self._queryERP5(
'getAccessTokenSignatureAlgorithmAndPublicKeyList',
)
......@@ -882,7 +882,7 @@ class OAuth2AuthorisationClientConnector(
came_from = state_dict.get(_STATE_CAME_FROM_NAME)
if came_from:
context = self # whatever
kw['redirect_url'] = came_from.encode('utf-8')
kw['redirect_url'] = unicode2str(came_from)
else:
context = self._getNeutralContextValue()
context.Base_redirect(**kw)
......@@ -930,7 +930,7 @@ class OAuth2AuthorisationClientConnector(
REQUEST=REQUEST,
RESPONSE=RESPONSE,
)
identifier_from_state = state_dict[_STATE_IDENTIFIER_NAME].encode('ascii')
identifier_from_state = unicode2str(state_dict[_STATE_IDENTIFIER_NAME])
for (
state_cookie_name,
identifier_from_cookie,
......@@ -965,7 +965,7 @@ class OAuth2AuthorisationClientConnector(
'code': code,
'redirect_uri': self.getRedirectUri(),
'client_id': self.getReference(),
'code_verifier': state_dict[_STATE_CODE_VERIFIER_NAME].encode('ascii'),
'code_verifier': unicode2str(state_dict[_STATE_CODE_VERIFIER_NAME])
},
)
access_token, _, error_message = self._setCookieFromTokenResponse(
......
......@@ -48,6 +48,7 @@ from Products.PluggableAuthService.interfaces.plugins import (
)
from Products.ERP5Security import _setUserNameForAccessLog
from Products.ERP5Type.Globals import InitializeClass
from Products.ERP5Type.Utils import bytes2str, str2bytes, unicode2str
# Public constants. Must not change once deployed.
......@@ -109,11 +110,11 @@ def encodeAccessTokenPayload(payload):
Encode given json-safe value into a format suitable for
decodeAccessTokenPayload.
"""
return base64.urlsafe_b64encode(
return bytes2str(base64.urlsafe_b64encode(
zlib.compress(
json.dumps(payload),
str2bytes(json.dumps(payload)),
),
)
))
def decodeAccessTokenPayload(encoded_payload):
"""
......@@ -353,7 +354,7 @@ class ERP5OAuth2ResourceServerPlugin(BasePlugin):
if client_id is None:
# Peek into token (without checking its signature) to guess the client_id
# to look for.
client_id = jwt.decode(
client_id = unicode2str(jwt.decode(
raw_token,
# no key.
# any algorithm is fine.
......@@ -361,7 +362,7 @@ class ERP5OAuth2ResourceServerPlugin(BasePlugin):
'verify_signature': False,
'verify_exp': False,
},
)['iss'].encode('utf-8')
)['iss'])
assert client_id is not None
web_service_value_list = list(self.__iterClientConnectorValue(
client_id=client_id,
......@@ -440,9 +441,9 @@ class ERP5OAuth2ResourceServerPlugin(BasePlugin):
return
# JWT is known valid. Access its content.
token_payload = decodeAccessTokenPayload(
token[JWT_PAYLOAD_KEY].encode('ascii'),
bytes2str(token[JWT_PAYLOAD_KEY].encode('ascii')),
)
client_id = token['iss'].encode('utf-8')
client_id = unicode2str(token['iss'])
if self.__getWebServiceValue(
client_id=client_id,
).getSessionVersion(
......@@ -452,8 +453,8 @@ class ERP5OAuth2ResourceServerPlugin(BasePlugin):
return
return {
_PRIVATE_EXTRACTED_KEY: (
token_payload[JWT_PAYLOAD_USER_ID_KEY].encode('utf-8'),
token_payload[JWT_PAYLOAD_USER_CAPTION_KEY].encode('utf-8'),
unicode2str(token_payload[JWT_PAYLOAD_USER_ID_KEY]),
unicode2str(token_payload[JWT_PAYLOAD_USER_CAPTION_KEY]),
),
_PRIVATE_TOKEN_KEY: (access_token, refresh_token),
_PRIVATE_CLIENT_ID: client_id,
......@@ -467,10 +468,10 @@ class ERP5OAuth2ResourceServerPlugin(BasePlugin):
] or '',
},
_PRIVATE_GROUP_LIST_KEY: tuple(
x.encode('utf-8') for x in token_payload[JWT_PAYLOAD_GROUP_LIST_KEY]
unicode2str(x) for x in token_payload[JWT_PAYLOAD_GROUP_LIST_KEY]
),
_PRIVATE_ROLE_LIST_KEY: tuple(
x.encode('utf-8') for x in token_payload[JWT_PAYLOAD_ROLE_LIST_KEY]
unicode2str(x) for x in token_payload[JWT_PAYLOAD_ROLE_LIST_KEY]
),
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment