def verify_oauth_body_sign(self, request, content_type='application/x-www-form-urlencoded' ): """ Verify grade request from LTI provider using OAuth body signing. Uses http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html:: This specification extends the OAuth signature to include integrity checks on HTTP request bodies with content types other than application/x-www-form-urlencoded. Arguments: request: DjangoWebobRequest. Raises: LTIError if request is incorrect. """ client_key, client_secret = self.get_client_key_secret() headers = { 'Authorization': six.text_type(request.headers.get('Authorization')), 'Content-Type': content_type, } sha1 = hashlib.sha1() sha1.update(request.body) oauth_body_hash = base64.b64encode(sha1.digest()) oauth_params = signature.collect_parameters( headers=headers, exclude_oauth_signature=False) oauth_headers = dict(oauth_params) oauth_signature = oauth_headers.pop('oauth_signature') mock_request_lti_1 = mock.Mock(uri=six.text_type( six.moves.urllib.parse.unquote(self.get_outcome_service_url())), http_method=six.text_type( request.method), params=list(oauth_headers.items()), signature=oauth_signature) mock_request_lti_2 = mock.Mock( uri=six.text_type(six.moves.urllib.parse.unquote(request.url)), http_method=six.text_type(request.method), params=list(oauth_headers.items()), signature=oauth_signature) if oauth_body_hash != oauth_headers.get('oauth_body_hash'): log.error("OAuth body hash verification failed, provided: {}, " "calculated: {}, for url: {}, body is: {}".format( oauth_headers.get('oauth_body_hash'), oauth_body_hash, self.get_outcome_service_url(), request.body)) raise LTIError("OAuth body hash verification is failed.") if (not signature.verify_hmac_sha1(mock_request_lti_1, client_secret) and not signature.verify_hmac_sha1(mock_request_lti_2, client_secret)): log.error("OAuth signature verification failed, for " "headers:{} url:{} method:{}".format( oauth_headers, self.get_outcome_service_url(), six.text_type(request.method))) raise LTIError("OAuth signature verification has failed.")
def verify_oauth_body_sign(self, request, content_type="application/x-www-form-urlencoded"): """ Verify grade request from LTI provider using OAuth body signing. Uses http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html:: This specification extends the OAuth signature to include integrity checks on HTTP request bodies with content types other than application/x-www-form-urlencoded. Arguments: request: DjangoWebobRequest. Raises: LTIError if request is incorrect. """ client_key, client_secret = self.get_client_key_secret() headers = {"Authorization": unicode(request.headers.get("Authorization")), "Content-Type": content_type} sha1 = hashlib.sha1() sha1.update(request.body) oauth_body_hash = base64.b64encode(sha1.digest()) oauth_params = signature.collect_parameters(headers=headers, exclude_oauth_signature=False) oauth_headers = dict(oauth_params) oauth_signature = oauth_headers.pop("oauth_signature") mock_request_lti_1 = mock.Mock( uri=unicode(urllib.unquote(self.get_outcome_service_url())), http_method=unicode(request.method), params=oauth_headers.items(), signature=oauth_signature, ) mock_request_lti_2 = mock.Mock( uri=unicode(urllib.unquote(request.url)), http_method=unicode(request.method), params=oauth_headers.items(), signature=oauth_signature, ) if oauth_body_hash != oauth_headers.get("oauth_body_hash"): log.error( "OAuth body hash verification failed, provided: {}, " "calculated: {}, for url: {}, body is: {}".format( oauth_headers.get("oauth_body_hash"), oauth_body_hash, self.get_outcome_service_url(), request.body ) ) raise LTIError("OAuth body hash verification is failed.") if not signature.verify_hmac_sha1(mock_request_lti_1, client_secret) and not signature.verify_hmac_sha1( mock_request_lti_2, client_secret ): log.error( "OAuth signature verification failed, for " "headers:{} url:{} method:{}".format( oauth_headers, self.get_outcome_service_url(), unicode(request.method) ) ) raise LTIError("OAuth signature verification has failed.")
def _check_oauth_signature(self, params, client_signature): """ Checks oauth signature from client. `params` are params from post request except signature, `client_signature` is signature from request. Builds mocked request and verifies hmac-sha1 signing:: 1. builds string to sign from `params`, `url` and `http_method`. 2. signs it with `client_secret` which comes from server settings. 3. obtains signature after sign and then compares it with request.signature (request signature comes form client in request) Returns `True` if signatures are correct, otherwise `False`. """ client_secret = str(self.server.config.get('client_secret', self.DEFAULT_CLIENT_SECRET)) host = os.environ.get('BOK_CHOY_HOSTNAME', '127.0.0.1') port = self.server.server_address[1] lti_base = self.DEFAULT_LTI_ADDRESS.format(host=host, port=port) lti_endpoint = self.server.config.get('lti_endpoint', self.DEFAULT_LTI_ENDPOINT) url = lti_base + lti_endpoint request = mock.Mock() request.params = [(str(k), str(v)) for k, v in params.items()] request.uri = str(url) request.http_method = 'POST' request.signature = str(client_signature) return signature.verify_hmac_sha1(request, client_secret)
def validate_2legged_oauth(oauth, uri, method, auth_header): """ "Two-legged" OAuth authorization isn't standard and so not supported by current versions of oauthlib. The implementation here is sufficient for simple developer tools and testing. Real usage of OAuth will always require directing the user to the authorization page so that a resource-owner token can be generated. """ req = Request(uri, method, "", auth_header) typ, params, oauth_params = oauth._get_signature_type_and_params(req) oauth_params = dict(oauth_params) req.params = filter(lambda x: x[0] not in ("oauth_signature", "realm"), params) req.signature = oauth_params.get("oauth_signature") req.client_key = oauth_params.get("oauth_consumer_key") req.nonce = oauth_params.get("oauth_nonce") req.timestamp = oauth_params.get("oauth_timestamp") if oauth_params.get("oauth_signature_method").lower() != "hmac-sha1": raise TwoLeggedOAuthError(u"unsupported signature method " + oauth_params.get("oauth_signature_method")) secret = validator.get_client_secret(req.client_key, req) valid_signature = signature.verify_hmac_sha1(req, secret, None) if valid_signature: return req.client_key else: raise TwoLeggedOAuthError(u"Cannot find APIAccess token with that key: %s" % req.client_key)
def check_oauth_signature(self, params, client_signature): ''' Checks oauth signature from client. `params` are params from post request except signature, `client_signature` is signature from request. Builds mocked request and verifies hmac-sha1 signing:: 1. builds string to sign from `params`, `url` and `http_method`. 2. signs it with `client_secret` which comes from server settings. 3. obtains signature after sign and then compares it with request.signature (request signature comes form client in request) Returns `True` if signatures are correct, otherwise `False`. ''' client_secret = unicode(self.oauth_settings['client_secret']) url = self.oauth_settings['lti_base'] + self.oauth_settings[ 'lti_endpoint'] request = mock.Mock() request.params = [(unicode(k), unicode(v)) for k, v in params.items()] request.uri = unicode(url) request.http_method = u'POST' request.signature = unicode(client_signature) return signature.verify_hmac_sha1(request, client_secret)
def _check_oauth_signature(self, params, client_signature): """ Checks oauth signature from client. `params` are params from post request except signature, `client_signature` is signature from request. Builds mocked request and verifies hmac-sha1 signing:: 1. builds string to sign from `params`, `url` and `http_method`. 2. signs it with `client_secret` which comes from server settings. 3. obtains signature after sign and then compares it with request.signature (request signature comes form client in request) Returns `True` if signatures are correct, otherwise `False`. """ client_secret = unicode(self.server.config.get('client_secret', self.DEFAULT_CLIENT_SECRET)) port = self.server.server_address[1] lti_base = self.DEFAULT_LTI_ADDRESS.format(port=port) lti_endpoint = self.server.config.get('lti_endpoint', self.DEFAULT_LTI_ENDPOINT) url = lti_base + lti_endpoint request = mock.Mock() request.params = [(unicode(k), unicode(v)) for k, v in params.items()] request.uri = unicode(url) request.http_method = u'POST' request.signature = unicode(client_signature) return signature.verify_hmac_sha1(request, client_secret)
def check_oauth_signature(self, params, client_signature): ''' Checks oauth signature from client. `params` are params from post request except signature, `client_signature` is signature from request. Builds mocked request and verifies hmac-sha1 signing:: 1. builds string to sign from `params`, `url` and `http_method`. 2. signs it with `client_secret` which comes from server settings. 3. obtains signature after sign and then compares it with request.signature (request signature comes form client in request) Returns `True` if signatures are correct, otherwise `False`. ''' client_secret = unicode(self.oauth_settings['client_secret']) url = self.oauth_settings['lti_base'] + self.oauth_settings['lti_endpoint'] request = mock.Mock() request.params = [(unicode(k), unicode(v)) for k, v in params.items()] request.uri = unicode(url) request.http_method = u'POST' request.signature = unicode(client_signature) return signature.verify_hmac_sha1(request, client_secret)
def validate_2legged_oauth(oauth, uri, method, auth_header): """ "Two-legged" OAuth authorization isn't standard and so not supported by current versions of oauthlib. The implementation here is sufficient for simple developer tools and testing. Real usage of OAuth will always require directing the user to the authorization page so that a resource-owner token can be generated. """ req = Request(uri, method, '', auth_header) typ, params, oauth_params = oauth._get_signature_type_and_params(req) oauth_params = dict(oauth_params) req.params = filter(lambda x: x[0] not in ("oauth_signature", "realm"), params) req.signature = oauth_params.get('oauth_signature') req.client_key = oauth_params.get('oauth_consumer_key') req.nonce = oauth_params.get('oauth_nonce') req.timestamp = oauth_params.get('oauth_timestamp') if oauth_params.get('oauth_signature_method').lower() != 'hmac-sha1': raise TwoLeggedOAuthError(u'unsupported signature method ' + oauth_params.get('oauth_signature_method')) secret = validator.get_client_secret(req.client_key, req) valid_signature = signature.verify_hmac_sha1(req, secret, None) if valid_signature: return req.client_key else: raise TwoLeggedOAuthError( u'Cannot find APIAccess token with that key: %s' % req.client_key)
def check_oauth(self): """ Checks whether the request passes Oauth signature check :return valid_oauth """ resp = dict(self.__httprequest.POST.dict()) orderedresp = OrderedDict(sorted(resp.items(), key=lambda t: t[0])) query_string = urllib.urlencode(orderedresp) oauth_headers = dict( signature.collect_parameters(query_string, exclude_oauth_signature=False)) sig = oauth_headers.pop('oauth_signature') consumer_secret = self.get_oauthsecret_for_key( orderedresp.get('oauth_consumer_key')) oauthrequest = Oauthrequest() oauthrequest.params = oauth_headers.items() oauthrequest.uri = unicode( urllib.unquote(self.__httprequest.build_absolute_uri())) oauthrequest.http_method = unicode('POST') oauthrequest.signature = sig if signature.verify_hmac_sha1(request=oauthrequest, client_secret=unicode(consumer_secret)): return True return False
def test_sign_hmac_sha1_with_client(self): """ Test sign and verify with HMAC-SHA1. """ self.assertEqual( self.expected_signature_hmac_sha1, sign_hmac_sha1_with_client(self.eg_signature_base_string, self.hmac_client)) self.assertTrue(verify_hmac_sha1( MockRequest('POST', 'http://example.com/request', self.eg_params, self.expected_signature_hmac_sha1), self.hmac_client.client_secret, self.hmac_client.resource_owner_secret))
def verify_oauth_body_sign(self, request): """ Verify grade request from LTI provider using OAuth body signing. Uses http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html:: This specification extends the OAuth signature to include integrity checks on HTTP request bodies with content types other than application/x-www-form-urlencoded. Arguments: request: DjangoWebobRequest. Raises: LTIError if request is incorrect. """ client_key, client_secret = self.get_client_key_secret() headers = { 'Authorization':unicode(request.headers.get('Authorization')), 'Content-Type': 'application/x-www-form-urlencoded', } sha1 = hashlib.sha1() sha1.update(request.body) oauth_body_hash = base64.b64encode(sha1.digest()) oauth_params = signature.collect_parameters(headers=headers, exclude_oauth_signature=False) oauth_headers =dict(oauth_params) oauth_signature = oauth_headers.pop('oauth_signature') mock_request = mock.Mock( uri=unicode(urllib.unquote(request.url)), http_method=unicode(request.method), params=oauth_headers.items(), signature=oauth_signature ) if oauth_body_hash != oauth_headers.get('oauth_body_hash'): log.debug("[LTI]: OAuth body hash verification is failed.") raise LTIError if not signature.verify_hmac_sha1(mock_request, client_secret): log.debug("[LTI]: OAuth signature verification is failed.") raise LTIError
def clean_oauth_signature(self): """ Cleans and validates the 'oauth signature'. The signature is verified by calculating the hash (using the algorithm specified in 'oauth_signature_method') of the URL, METHOD and BODY. After the calculation the signature is compared with the 'oauth_signature' to check if they match. When the signatures match we can assure that the request is from a authorized entity. """ oauth_request = Request(self.request.build_absolute_uri(), self.request.method, self.request.POST) oauth_request.signature = self.cleaned_data["oauth_signature"] oauth_request.params = [(k, v) for k, v in self.request.POST.items() if k != "oauth_signature"] if not oauth.verify_hmac_sha1(oauth_request, settings.LTI_SECRET): raise ValidationError( "Invalid signature, URL: {}, method: {}".format( self.request.build_absolute_uri(), self.request.method)) return self.cleaned_data["oauth_signature"]
def verify_oauth_body_sign(self, request, content_type='application/x-www-form-urlencoded' ): """ Verify grade request from LTI provider using OAuth body signing. Uses http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html:: This specification extends the OAuth signature to include integrity checks on HTTP request bodies with content types other than application/x-www-form-urlencoded. Arguments: request: DjangoWebobRequest. Raises: LTIError if request is incorrect. """ client_key, client_secret = self.get_client_key_secret() headers = { 'Authorization': unicode(request.headers.get('Authorization')), 'Content-Type': content_type, } sha1 = hashlib.sha1() sha1.update(request.body) oauth_body_hash = base64.b64encode(sha1.digest()) oauth_params = signature.collect_parameters( headers=headers, exclude_oauth_signature=False) oauth_headers = dict(oauth_params) oauth_signature = oauth_headers.pop('oauth_signature') mock_request = mock.Mock(uri=unicode(urllib.unquote(request.url)), http_method=unicode(request.method), params=oauth_headers.items(), signature=oauth_signature) if oauth_body_hash != oauth_headers.get('oauth_body_hash'): raise LTIError("OAuth body hash verification is failed.") if not signature.verify_hmac_sha1(mock_request, client_secret): raise LTIError("OAuth signature verification is failed.")
def check_oauth(self): """ Checks whether the request passes Oauth signature check :return valid_oauth """ resp = dict(self.__httprequest.POST.dict()) orderedresp = OrderedDict(sorted(resp.items(), key=lambda t: t[0])) query_string = urllib.urlencode(orderedresp) oauth_headers = dict(signature.collect_parameters(query_string, exclude_oauth_signature=False)) sig = oauth_headers.pop('oauth_signature') consumer_secret = self.get_oauthsecret_for_key(orderedresp.get('oauth_consumer_key')) oauthrequest = Oauthrequest() oauthrequest.params = oauth_headers.items() oauthrequest.uri = unicode(urllib.unquote(self.__httprequest.build_absolute_uri())) oauthrequest.http_method = unicode('POST') oauthrequest.signature = sig if signature.verify_hmac_sha1(request=oauthrequest, client_secret=unicode(consumer_secret)): return True return False