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 authorization_url(self, url, state=None, nonce=None, **kwargs): nonce = nonce or generate_nonce() url, state = super(OidcSession, self).authorization_url(url, state=state, nonce=nonce, **kwargs) return url, state, nonce
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_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 oauth_redirect(self, oauth_session): """ redirect to the oauth url with setting the anti-forgery 'state' token in the session :param oauth_session: instance of OAuth 2 extension to :class:`requests_oauthlib.OAuth2Session`. """ nonce = generate_nonce() authorization_url, state = oauth_session.authorization_url(url=self.oauth_url, prompt=self.prompt, max_age=self.max_age, nonce=nonce) session[AUTH_STATE_KEY] = state session[AUTH_NONCE_KEY] = nonce session.modified = True return redirect(authorization_url)
def authenticate(self, trans): base_authorize_url = self.config['authorization_endpoint'] oauth2_session = self._create_oauth2_session(scope=('openid', 'email', 'profile')) nonce = generate_nonce() nonce_hash = self._hash_nonce(nonce) extra_params = {"nonce": nonce_hash} if "extra_params" in self.config: extra_params.update(self.config['extra_params']) authorization_url, state = oauth2_session.authorization_url( base_authorize_url, **extra_params) trans.set_cookie(value=state, name=STATE_COOKIE_NAME) trans.set_cookie(value=nonce, name=NONCE_COOKIE_NAME) return authorization_url
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 authenticate(self, trans, idphint=None): base_authorize_url = self.config['authorization_endpoint'] scopes = ['openid', 'email', 'profile'] if self.config['provider'] in ['custos', 'cilogon']: scopes.append('org.cilogon.userinfo') oauth2_session = self._create_oauth2_session(scope=scopes) nonce = generate_nonce() nonce_hash = self._hash_nonce(nonce) extra_params = {"nonce": nonce_hash} if idphint is not None: extra_params['idphint'] = idphint if "extra_params" in self.config: extra_params.update(self.config['extra_params']) authorization_url, state = oauth2_session.authorization_url( base_authorize_url, **extra_params) trans.set_cookie(value=state, name=STATE_COOKIE_NAME) trans.set_cookie(value=nonce, name=NONCE_COOKIE_NAME) return authorization_url
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 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 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): __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
from Crypto.Cipher import AES import os from oauthlib.common import generate_nonce from secret import key NONCE = generate_nonce() def encrypt(msg): # funktionsweise AES: # nonce + counter werden verschlüsselt mit einem key # dann wird der plaintext damit gexored # und das ist dan der ciphertext # AES sollte 16 byte blöcke haben aes = AES.new(key, AES.MODE_CTR, nonce=NONCE) # das ganze wird dann noch gehext # d.h. ein buchstabe entspricht zwei zeichen return aes.encrypt(msg).hex() #5cd9430d66c0245e6691568fef403d79 #8711d6da2d63298678978711e5ec78a5 #c2 # die beiden gleichen zeichen gegen die dinger schießen und dann müsste ja da wo die zeichen gleich sind das zeichen der nonce sein # if we flip bits in the cipher text, bits in the plain texts are flipped print(encrypt("hello")) q = input("Encrypt this string:").encode() # dann wird erst q also "Encript this string:" geprintet print(q)
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_nonce(self): """Ping me (ib-lundgren) when you discover how to test randomness.""" nonce = generate_nonce() for i in range(50): self.assertNotEqual(nonce, generate_nonce())
async def obtain_access_token(studip_session: StudIPSession, oauth1_client: OAuth1Client = None, http_session: aiohttp.ClientSession = None, port=OAUTH_CALLBACK_PORT, open_browser=True): if not http_session: http_session = studip_session.http.http_session if not oauth1_client: if isinstance(http_session._default_auth, OAuth1Client): oauth1_client = http_session._default_auth else: oauth1_client = OAuth1Client( *get_tokens(studip_session.studip_base)) http_session._default_auth = oauth1_client try: await studip_session.check_login() return oauth1_client except (HTTPException, aiohttp.ClientResponseError) as e: if e.status != HTTPUnauthorized.status_code \ and getattr(e, "message", "") != "Can't verify request, missing oauth_consumer_key or oauth_token": raise log.info("OAuth Session invalid, starting log-in flow") app = Application() app.add_routes(routes) app["http_session"] = http_session app["studip_session"] = studip_session app["oauth1_client"] = oauth1_client app["finished_client_future"] = asyncio.get_event_loop().create_future() app["check_running_future"] = asyncio.get_event_loop().create_future() runner = AppRunner(app) try: await runner.setup() site = TCPSite(runner, host="127.0.0.1", port=port) await site.start() nonce = generate_nonce() log.debug("nonce %s", nonce) async with http_session.get( url_for("check_running", app=app, site=site).with_query(nonce=nonce)) as resp: resp.raise_for_status() assert await resp.text() == "running" assert await asyncio.wait_for(app["check_running_future"], 0) == nonce log.debug("server check passed") start_addr = str(url_for("start_oauth", app=app, site=site)) log.info("Go to the following address to log in via OAuth1: %s", start_addr) if open_browser is True: import webbrowser open_browser = webbrowser.open if callable(open_browser): await asyncio.get_event_loop().run_in_executor( None, lambda: open_browser(start_addr)), return await app["finished_client_future"] finally: await runner.cleanup()