def get_oauth_params(self, request): """Get the basic OAuth parameters to be used in generating a signature. """ nonce = (generate_nonce() if self.nonce is None else self.nonce) timestamp = (generate_timestamp() if self.timestamp is None else self.timestamp) params = [ ('oauth_nonce', nonce), ('oauth_timestamp', timestamp), ('oauth_version', '1.0'), ('oauth_signature_method', self.signature_method), ('oauth_consumer_key', self.client_key), ] if self.resource_owner_key: params.append(('oauth_token', self.resource_owner_key)) if self.callback_uri: params.append(('oauth_callback', self.callback_uri)) if self.verifier: params.append(('oauth_verifier', self.verifier)) # providing body hash for requests other than x-www-form-urlencoded # as described in https://tools.ietf.org/html/draft-eaton-oauth-bodyhash-00#section-4.1.1 # 4.1.1. When to include the body hash # * [...] MUST NOT include an oauth_body_hash parameter on requests with form-encoded request bodies # * [...] SHOULD include the oauth_body_hash parameter on all other requests. # Note that SHA-1 is vulnerable. The spec acknowledges that in https://tools.ietf.org/html/draft-eaton-oauth-bodyhash-00#section-6.2 # At this time, no further effort has been made to replace SHA-1 for the OAuth Request Body Hash extension. content_type = request.headers.get('Content-Type', None) content_type_eligible = content_type and content_type.find('application/x-www-form-urlencoded') < 0 if request.body is not None and content_type_eligible: params.append(('oauth_body_hash', base64.b64encode(hashlib.sha1(request.body.encode('utf-8')).digest()).decode('utf-8'))) return params
def get_oauth_params(self, request): """Get the basic OAuth parameters to be used in generating a signature. """ nonce = (generate_nonce() if self.nonce is None else self.nonce) timestamp = (generate_timestamp() if self.timestamp is None else self.timestamp) params = [ ('oauth_nonce', nonce), ('oauth_timestamp', timestamp), ('oauth_version', '1.0'), ('oauth_signature_method', self.signature_method), ('oauth_consumer_key', self.client_key), ] if self.resource_owner_key: params.append(('oauth_token', self.resource_owner_key)) if self.callback_uri: params.append(('oauth_callback', self.callback_uri)) if self.verifier: params.append(('oauth_verifier', self.verifier)) # providing body hash for requests other than x-www-form-urlencoded # as described in http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html # 4.1.1. When to include the body hash # * [...] MUST NOT include an oauth_body_hash parameter on requests with form-encoded request bodies # * [...] SHOULD include the oauth_body_hash parameter on all other requests. content_type = request.headers.get('Content-Type', None) content_type_eligible = content_type and content_type.find( 'application/x-www-form-urlencoded') < 0 if request.body is not None and content_type_eligible: params.append(('oauth_body_hash', base64.b64encode( hashlib.sha1(request.body.encode( 'utf-8')).digest()).decode('utf-8'))) return params
def get_oauth_params(self, request): """Get the basic OAuth parameters to be used in generating a signature. """ nonce = (generate_nonce() if self.nonce is None else self.nonce) timestamp = (generate_timestamp() if self.timestamp is None else self.timestamp) params = [ ('oauth_nonce', nonce), ('oauth_timestamp', timestamp), ('oauth_version', '1.0'), ('oauth_signature_method', self.signature_method), ('oauth_consumer_key', self.client_key), ] if self.resource_owner_key: params.append(('oauth_token', self.resource_owner_key)) if self.callback_uri: params.append(('oauth_callback', self.callback_uri)) if self.verifier: params.append(('oauth_verifier', self.verifier)) # providing body hash for requests other than x-www-form-urlencoded # as described in http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html # 4.1.1. When to include the body hash # * [...] MUST NOT include an oauth_body_hash parameter on requests with form-encoded request bodies # * [...] SHOULD include the oauth_body_hash parameter on all other requests. content_type = request.headers.get('Content-Type', None) content_type_eligible = content_type and content_type.find('application/x-www-form-urlencoded') < 0 if request.body is not None and content_type_eligible: params.append(('oauth_body_hash', base64.b64encode(hashlib.sha1(request.body.encode('utf-8')).digest()).decode('utf-8'))) return params
def get_context_data(self, **kwargs): role = self.request.GET.get('role', '') campus = self.request.GET.get('campus', '') lti_parameters = [ ("roles", self._lti_role[role]), ("ext_roles", self._lti_ext_role[role]), ("custom_canvas_account_sis_id", 'uwcourse:{}:arts-&-sciences:psych:psych'.format(campus)), ("oauth_timestamp", generate_timestamp()), ("oauth_nonce", generate_nonce()), ("resource_link_title", "UW LTI Development ({})".format(self.lti_app())), ] lti_parameters += self._static_lti_parameters # sign payload lti_app_uri = self.lti_app_uri() sbs = signature_base_string('POST', base_string_uri(lti_app_uri + '/'), normalize_parameters(lti_parameters)) client_key = self._client_key client = Client(client_key, client_secret=self._client_secrets[client_key]) signature = sign_hmac_sha1_with_client(sbs, client) lti_parameters.append(("oauth_signature", signature)) context = super().get_context_data(**kwargs) context['uri'] = lti_app_uri context['campus'] = campus context['role_name'] = role context['lti_parameters'] = lti_parameters return context
def get_oauth_params(self): """Get the basic OAuth parameters to be used in generating a signature. """ params = [ ('oauth_nonce', generate_nonce()), ('oauth_timestamp', generate_timestamp()), ('oauth_version', '1.0'), ('oauth_signature_method', self.signature_method), ('oauth_consumer_key', self.client_key), ] if self.resource_owner_key: params.append(('oauth_token', self.resource_owner_key)) if self.callback_uri: params.append(('oauth_callback', self.callback_uri)) if self.verifier: params.append(('oauth_verifier', self.verifier)) return params
def get_oauth_params(self): """Get the basic OAuth parameters to be used in generating a signature. """ params = [ (u"oauth_nonce", generate_nonce()), (u"oauth_timestamp", generate_timestamp()), (u"oauth_version", u"1.0"), (u"oauth_signature_method", self.signature_method), (u"oauth_consumer_key", self.client_key), ] if self.resource_owner_key: params.append((u"oauth_token", self.resource_owner_key)) if self.callback_uri: params.append((u"oauth_callback", self.callback_uri)) if self.verifier: params.append((u"oauth_verifier", self.verifier)) return params
def get_oauth_params(self, request): """Get the basic OAuth parameters to be used in generating a signature. """ nonce = generate_nonce() if self.nonce is None else self.nonce timestamp = generate_timestamp() if self.timestamp is None else self.timestamp params = [ ("oauth_nonce", nonce), ("oauth_timestamp", timestamp), ("oauth_version", "1.0"), ("oauth_signature_method", self.signature_method), ("oauth_consumer_key", self.client_key), ] if self.resource_owner_key: params.append(("oauth_token", self.resource_owner_key)) if self.callback_uri: params.append(("oauth_callback", self.callback_uri)) if self.verifier: params.append(("oauth_verifier", self.verifier)) return params
def sign(self, url, method=u'POST', signature_method=u'HMAC-SHA1'): """ Use this method to create a signature over the authorization header, and the url query parameters :param url: request url :param method: request method (i.e. POST, GET) :param signature_method: method of signature. Only supports (HMAC-SHA1, PLAINTEXT) Note: that HMAC-SHA1 is required by Yahoo API queries since they are sent insecurely """ # could change this to support additional methods # for now only support HMAC-SHA1 and PLAINTEXT (Yahoo only supports these) self.add_param(u'oauth_signature_method', signature_method) self.add_param(u'oauth_nonce', generate_nonce()) self.add_param(u'oauth_timestamp', generate_timestamp()) if signature_method == u'HMAC-SHA1': base_string = construct_base_string(unicode(method), normalize_base_string_uri(unicode(url)), normalize_parameters(self.params)) signature = sign_hmac_sha1(base_string, self.client_secret, self.oauth_token_secret) else: signature = quote(self.client_secret + u'&' + self.oauth_token_secret) self.add_param(u'oauth_signature', signature)
def get_oauth_params(self, request): """Get the basic OAuth parameters to be used in generating a signature. """ nonce = (generate_nonce() if self.nonce is None else self.nonce) timestamp = (generate_timestamp() if self.timestamp is None else self.timestamp) params = [ ('oauth_nonce', nonce), ('oauth_timestamp', timestamp), ('oauth_version', self.version), ('oauth_signature_method', self.signature_method), ('oauth_consumer_key', self.client_key), ] if self.resource_owner_key: params.append(('oauth_token', self.resource_owner_key)) if self.callback_uri: params.append(('oauth_callback', self.callback_uri)) if self.verifier: params.append(('oauth_verifier', self.verifier)) return params
def get_oauth_params(self, request): __doc__ = Client.get_oauth_params.__doc__ nonce = (generate_nonce() if self.nonce is None else self.nonce) timestamp = (generate_timestamp() if self.timestamp is None else self.timestamp) params = [ ('oauth_nonce', nonce), ('oauth_timestamp', timestamp), ('oauth_version', '1.0'), ('oauth_signature_method', self.signature_method), ('oauth_consumer_key', self.client_key), ] if self.resource_owner_key: params.append(('oauth_token', self.resource_owner_key)) else: params.append(('oauth_body_hash', self.hash_body(request))) if self.callback_uri: params.append(('oauth_callback', self.callback_uri)) if self.verifier: params.append(('oauth_verifier', self.verifier)) return params
def prepare_mac_header(token, uri, key, http_method, nonce=None, headers=None, body=None, ext='', hash_algorithm='hmac-sha-1', issue_time=None, draft=0): """Add an `MAC Access Authentication`_ signature to headers. Unlike OAuth 1, this HMAC signature does not require inclusion of the request payload/body, neither does it use a combination of client_secret and token_secret but rather a mac_key provided together with the access token. Currently two algorithms are supported, "hmac-sha-1" and "hmac-sha-256", `extension algorithms`_ are not supported. Example MAC Authorization header, linebreaks added for clarity Authorization: MAC id="h480djs93hd8", nonce="1336363200:dj83hs9s", mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM=" .. _`MAC Access Authentication`: http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01 .. _`extension algorithms`: http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01#section-7.1 :param uri: Request URI. :param headers: Request headers as a dictionary. :param http_method: HTTP Request method. :param key: MAC given provided by token endpoint. :param hash_algorithm: HMAC algorithm provided by token endpoint. :param issue_time: Time when the MAC credentials were issues as a datetime object. :param draft: MAC authentication specification version. :return: headers dictionary with the authorization field added. """ http_method = http_method.upper() host, port = utils.host_from_uri(uri) if hash_algorithm.lower() == 'hmac-sha-1': h = hashlib.sha1 elif hash_algorithm.lower() == 'hmac-sha-256': h = hashlib.sha256 else: raise ValueError('unknown hash algorithm') if draft == 0: nonce = nonce or '{0}:{1}'.format(utils.generate_age(issue_time), common.generate_nonce()) else: ts = common.generate_timestamp() nonce = common.generate_nonce() sch, net, path, par, query, fra = urlparse(uri) if query: request_uri = path + '?' + query else: request_uri = path # Hash the body/payload if body is not None and draft == 0: bodyhash = b2a_base64(h(body.encode('utf-8')).digest())[:-1].decode('utf-8') else: bodyhash = '' # Create the normalized base string base = [] if draft == 0: base.append(nonce) else: base.append(ts) base.append(nonce) base.append(http_method.upper()) base.append(request_uri) base.append(host) base.append(port) if draft == 0: base.append(bodyhash) base.append(ext or '') base_string = '\n'.join(base) + '\n' # hmac struggles with unicode strings - http://bugs.python.org/issue5285 if isinstance(key, unicode_type): key = key.encode('utf-8') sign = hmac.new(key, base_string.encode('utf-8'), h) sign = b2a_base64(sign.digest())[:-1].decode('utf-8') header = [] header.append('MAC id="%s"' % token) if draft != 0: header.append('ts="%s"' % ts) header.append('nonce="%s"' % nonce) if bodyhash: header.append('bodyhash="%s"' % bodyhash) if ext: header.append('ext="%s"' % ext) header.append('mac="%s"' % sign) headers = headers or {} headers['Authorization'] = ', '.join(header) return headers
def prepare_mac_header(token, uri, key, http_method, nonce=None, headers=None, body=None, ext='', hash_algorithm='hmac-sha-1', issue_time=None, draft=0): """Add an `MAC Access Authentication`_ signature to headers. Unlike OAuth 1, this HMAC signature does not require inclusion of the request payload/body, neither does it use a combination of client_secret and token_secret but rather a mac_key provided together with the access token. Currently two algorithms are supported, "hmac-sha-1" and "hmac-sha-256", `extension algorithms`_ are not supported. Example MAC Authorization header, linebreaks added for clarity Authorization: MAC id="h480djs93hd8", nonce="1336363200:dj83hs9s", mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM=" .. _`MAC Access Authentication`: http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01 .. _`extension algorithms`: http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01#section-7.1 :param uri: Request URI. :param headers: Request headers as a dictionary. :param http_method: HTTP Request method. :param key: MAC given provided by token endpoint. :param hash_algorithm: HMAC algorithm provided by token endpoint. :param issue_time: Time when the MAC credentials were issued (datetime). :param draft: MAC authentication specification version. :return: headers dictionary with the authorization field added. """ http_method = http_method.upper() host, port = utils.host_from_uri(uri) if hash_algorithm.lower() == 'hmac-sha-1': h = hashlib.sha1 elif hash_algorithm.lower() == 'hmac-sha-256': h = hashlib.sha256 else: raise ValueError('unknown hash algorithm') if draft == 0: nonce = nonce or '{0}:{1}'.format(utils.generate_age(issue_time), common.generate_nonce()) else: ts = common.generate_timestamp() nonce = common.generate_nonce() sch, net, path, par, query, fra = urlparse(uri) if query: request_uri = path + '?' + query else: request_uri = path # Hash the body/payload if body is not None and draft == 0: body = body.encode('utf-8') bodyhash = b2a_base64(h(body).digest())[:-1].decode('utf-8') else: bodyhash = '' # Create the normalized base string base = [] if draft == 0: base.append(nonce) else: base.append(ts) base.append(nonce) base.append(http_method.upper()) base.append(request_uri) base.append(host) base.append(port) if draft == 0: base.append(bodyhash) base.append(ext or '') base_string = '\n'.join(base) + '\n' # hmac struggles with unicode strings - http://bugs.python.org/issue5285 if isinstance(key, unicode_type): key = key.encode('utf-8') sign = hmac.new(key, base_string.encode('utf-8'), h) sign = b2a_base64(sign.digest())[:-1].decode('utf-8') header = [] header.append('MAC id="%s"' % token) if draft != 0: header.append('ts="%s"' % ts) header.append('nonce="%s"' % nonce) if bodyhash: header.append('bodyhash="%s"' % bodyhash) if ext: header.append('ext="%s"' % ext) header.append('mac="%s"' % sign) headers = headers or {} headers['Authorization'] = ', '.join(header) return headers
def test_generate_timestamp(self): timestamp = generate_timestamp() self.assertIsInstance(timestamp, unicode_type) self.assertTrue(int(timestamp)) self.assertGreater(int(timestamp), 1331672335)