Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Release 2.0.8 #545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ Joel Stevenson
Brendan McCollam
Jonathan Huot
Pieter Ennes
Olaf Conradi
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

2.0.8 (2018-05-18)
------------------

* Fixed some copy and paste typos (#535)
* Use secrets module in Python 3.6 and later (#533)
* Add request argument to confirm_redirect_uri (#504)
* Avoid populating spurious token credentials (#542, #546)

2.0.7 (2018-03-19)
------------------

Expand Down
12 changes: 7 additions & 5 deletions docs/oauth1/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ A few important facts regarding OAuth security

* **Tokens must be random**, OAuthLib provides a method for generating
secure tokens and it's packed into ``oauthlib.common.generate_token``,
use it. If you decide to roll your own, use ``random.SystemRandom``
which is based on ``os.urandom`` rather than the default ``random``
based on the effecient but not truly random Mersenne Twister.
Predictable tokens allow attackers to bypass virtually all defences
OAuth provides.
use it. If you decide to roll your own, use ``secrets.SystemRandom``
for Python 3.6 and later. The ``secrets`` module is designed for
generating cryptographically strong random numbers. For earlier versions
of Python, use ``random.SystemRandom`` which is based on ``os.urandom``
rather than the default ``random`` based on the effecient but not truly
random Mersenne Twister. Predictable tokens allow attackers to bypass
virtually all defences OAuth provides.

* **Timing attacks are real** and more than possible if you host your
application inside a shared datacenter. Ensure all ``validate_`` methods
Expand Down
2 changes: 1 addition & 1 deletion examples/skeleton_oauth2_web_application_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def validate_code(self, client_id, code, client, request, *args, **kwargs):
# state and user to request.scopes and request.user.
pass

def confirm_redirect_uri(self, client_id, code, redirect_uri, client, *args, **kwargs):
def confirm_redirect_uri(self, client_id, code, redirect_uri, client, request, *args, **kwargs):
# You did save the redirect uri with the authorization code right?
pass

Expand Down
2 changes: 1 addition & 1 deletion oauthlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"""

__author__ = 'The OAuthlib Community'
__version__ = '2.0.7'
__version__ = '2.0.8'


import logging
Expand Down
11 changes: 8 additions & 3 deletions oauthlib/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@
import collections
import datetime
import logging
import random
import re
import sys
import time

try:
from secrets import randbits
from secrets import SystemRandom
except ImportError:
from random import getrandbits as randbits
from random import SystemRandom
try:
from urllib import quote as _quote
from urllib import unquote as _unquote
Expand Down Expand Up @@ -202,7 +207,7 @@ def generate_nonce():
.. _`section 3.2.1`: https://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01#section-3.2.1
.. _`section 3.3`: https://tools.ietf.org/html/rfc5849#section-3.3
"""
return unicode_type(unicode_type(random.getrandbits(64)) + generate_timestamp())
return unicode_type(unicode_type(randbits(64)) + generate_timestamp())


def generate_timestamp():
Expand All @@ -225,7 +230,7 @@ def generate_token(length=30, chars=UNICODE_ASCII_CHARACTER_SET):
and entropy when generating the random characters is important. Which is
why SystemRandom is used instead of the default random.choice method.
"""
rand = random.SystemRandom()
rand = SystemRandom()
return ''.join(rand.choice(chars) for x in range(length))


Expand Down
23 changes: 17 additions & 6 deletions oauthlib/oauth2/rfc6749/clients/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from __future__ import absolute_import, unicode_literals

import time
import warnings

from oauthlib.common import generate_token
from oauthlib.oauth2.rfc6749 import tokens
Expand Down Expand Up @@ -111,8 +112,10 @@ def __init__(self, client_id,
self.state_generator = state_generator
self.state = state
self.redirect_url = redirect_url
self.code = None
self.expires_in = None
self._expires_at = None
self._populate_attributes(self.token)
self.populate_token_attributes(self.token)

@property
def token_types(self):
Expand Down Expand Up @@ -406,7 +409,7 @@ def parse_request_body_response(self, body, scope=None, **kwargs):
.. _`Section 7.1`: https://tools.ietf.org/html/rfc6749#section-7.1
"""
self.token = parse_token_response(body, scope=scope)
self._populate_attributes(self.token)
self.populate_token_attributes(self.token)
return self.token

def prepare_refresh_body(self, body='', refresh_token=None, scope=None, **kwargs):
Expand Down Expand Up @@ -460,7 +463,18 @@ def _add_mac_token(self, uri, http_method='GET', body=None,
return uri, headers, body

def _populate_attributes(self, response):
"""Add commonly used values such as access_token to self."""
warnings.warn("Please switch to the public method "
"populate_token_attributes.", DeprecationWarning)
return self.populate_token_attributes(response)

def populate_code_attributes(self, response):
"""Add attributes from an auth code response to self."""

if 'code' in response:
self.code = response.get('code')

def populate_token_attributes(self, response):
"""Add attributes from a token exchange response to self."""

if 'access_token' in response:
self.access_token = response.get('access_token')
Expand All @@ -478,9 +492,6 @@ def _populate_attributes(self, response):
if 'expires_at' in response:
self._expires_at = int(response.get('expires_at'))

if 'code' in response:
self.code = response.get('code')

if 'mac_key' in response:
self.mac_key = response.get('mac_key')

Expand Down
2 changes: 1 addition & 1 deletion oauthlib/oauth2/rfc6749/clients/mobile_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,5 @@ def parse_request_uri_response(self, uri, state=None, scope=None):
.. _`Section 3.3`: https://tools.ietf.org/html/rfc6749#section-3.3
"""
self.token = parse_implicit_response(uri, state=state, scope=scope)
self._populate_attributes(self.token)
self.populate_token_attributes(self.token)
return self.token
4 changes: 2 additions & 2 deletions oauthlib/oauth2/rfc6749/clients/service_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ def prepare_request_body(self,
' token requests.')
claim = {
'iss': issuer or self.issuer,
'aud': audience or self.issuer,
'sub': subject or self.issuer,
'aud': audience or self.audience,
'sub': subject or self.subject,
'exp': int(expires_at or time.time() + 3600),
'iat': int(issued_at or time.time()),
}
Expand Down
2 changes: 1 addition & 1 deletion oauthlib/oauth2/rfc6749/clients/web_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,5 +172,5 @@ def parse_request_uri_response(self, uri, state=None):
oauthlib.oauth2.rfc6749.errors.MismatchingStateError
"""
response = parse_authorization_code_response(uri, state=state)
self._populate_attributes(response)
self.populate_code_attributes(response)
return response
3 changes: 2 additions & 1 deletion oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,8 @@ def validate_token_request(self, request):
# authorization request as described in Section 4.1.1, and their
# values MUST be identical.
if not self.request_validator.confirm_redirect_uri(request.client_id, request.code,
request.redirect_uri, request.client):
request.redirect_uri, request.client,
request):
log.debug('Redirect_uri (%r) invalid for client %r (%r).',
request.redirect_uri, request.client_id, request.client)
raise errors.MismatchingRedirectURIError(request=request)
Expand Down
2 changes: 1 addition & 1 deletion oauthlib/oauth2/rfc6749/request_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def authenticate_client_id(self, client_id, request, *args, **kwargs):
"""
raise NotImplementedError('Subclasses must implement this method.')

def confirm_redirect_uri(self, client_id, code, redirect_uri, client,
def confirm_redirect_uri(self, client_id, code, redirect_uri, client, request,
*args, **kwargs):
"""Ensure that the authorization process represented by this authorization
code began with this 'redirect_uri'.
Expand Down
12 changes: 12 additions & 0 deletions tests/oauth2/rfc6749/clients/test_mobile_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ def test_implicit_token_uri(self):
uri = client.prepare_request_uri(self.uri, **self.kwargs)
self.assertURLEqual(uri, self.uri_kwargs)

def test_populate_attributes(self):

client = MobileApplicationClient(self.client_id)

response_uri = (self.response_uri + "&code=EVIL-CODE")

client.parse_request_uri_response(response_uri, scope=self.scope)

# We must not accidentally pick up any further security
# credentials at this point.
self.assertIsNone(client.code)

def test_parse_token_response(self):
client = MobileApplicationClient(self.client_id)

Expand Down
19 changes: 19 additions & 0 deletions tests/oauth2/rfc6749/clients/test_web_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,25 @@ def test_parse_grant_uri_response(self):
self.response_uri,
state="invalid")

def test_populate_attributes(self):

client = WebApplicationClient(self.client_id)

response_uri = (self.response_uri +
"&access_token=EVIL-TOKEN"
"&refresh_token=EVIL-TOKEN"
"&mac_key=EVIL-KEY")

client.parse_request_uri_response(response_uri, self.state)

self.assertEqual(client.code, self.code)

# We must not accidentally pick up any further security
# credentials at this point.
self.assertIsNone(client.access_token)
self.assertIsNone(client.refresh_token)
self.assertIsNone(client.mac_key)

def test_parse_token_response(self):
client = WebApplicationClient(self.client_id)

Expand Down