diff options
author | Ib Lundgren <ib.lundgren@gmail.com> | 2013-08-03 11:56:17 -0700 |
---|---|---|
committer | Ib Lundgren <ib.lundgren@gmail.com> | 2013-08-03 11:56:17 -0700 |
commit | 5b8aa2d3762d5f800a1db3d07f15702cb007c7e9 (patch) | |
tree | fbde8ceaf25b34611b2b7ebb212b6592cbf58164 | |
parent | f794cf31971274766378faf140d60e5ec3807286 (diff) | |
parent | 517e01f5db428fe4c3e56119faad1760a8841c9f (diff) | |
download | oauthlib-5b8aa2d3762d5f800a1db3d07f15702cb007c7e9.tar.gz |
Merge pull request #199 from squirly/master
The authorization endpoint now returns a 200 on "oob" oauth_callbacks.
-rw-r--r-- | AUTHORS | 3 | ||||
-rw-r--r-- | docs/oauth1/server.rst | 12 | ||||
-rw-r--r-- | oauthlib/oauth1/rfc5849/endpoints/access_token.py | 19 | ||||
-rw-r--r-- | oauthlib/oauth1/rfc5849/endpoints/authorization.py | 65 | ||||
-rw-r--r-- | oauthlib/oauth1/rfc5849/endpoints/request_token.py | 19 | ||||
-rw-r--r-- | oauthlib/oauth1/rfc5849/request_validator.py | 6 | ||||
-rw-r--r-- | tests/oauth1/rfc5849/endpoints/test_access_token.py | 14 | ||||
-rw-r--r-- | tests/oauth1/rfc5849/endpoints/test_authorization.py | 17 | ||||
-rw-r--r-- | tests/oauth1/rfc5849/endpoints/test_base.py | 14 | ||||
-rw-r--r-- | tests/oauth1/rfc5849/endpoints/test_request_token.py | 16 |
10 files changed, 110 insertions, 75 deletions
@@ -17,4 +17,5 @@ Mackenzie Thompson Hsiaoming Yang Devin Sevilla Clint Ecker -Kyle Valade
\ No newline at end of file +Kyle Valade +Tyler Jones (squirly) diff --git a/docs/oauth1/server.rst b/docs/oauth1/server.rst index cb00257..8fcfd2d 100644 --- a/docs/oauth1/server.rst +++ b/docs/oauth1/server.rst @@ -289,6 +289,7 @@ The example uses Flask but should be transferable to any framework. from flask import Flask, redirect, Response, request, url_for from oauthlib.oauth1 import OAuth1Error + import urlparse app = Flask(__name__) @@ -296,7 +297,7 @@ The example uses Flask but should be transferable to any framework. @app.route('/request_token', methods=['POST']) def request_token(): - _, h, b, s = provider.create_request_token_response(request.url, + h, b, s = provider.create_request_token_response(request.url, http_method=request.method, body=request.data, headers=request.headers) @@ -323,19 +324,22 @@ The example uses Flask but should be transferable to any framework. def post_authorize(): realms = request.form.getlist('realms') try: - u, _, _, _ = provider.create_authorization_response(request.url, + h, b, s = provider.create_authorization_response(request.url, http_method=request.method, body=request.data, headers=request.headers, realms=realms) - return redirect(u) + if s == 200: + return 'Your verifier is: ' + str(urlparse.parse_qs(b)['oauth_verifier'][0]) + else: + return Response(b, status=s, headers=h) except OAuth1Error as e: return redirect(e.in_uri(url_for('/error'))) @app.route('/access_token', methods=['POST']) def access_token(): - _, h, b, s = provider.create_access_token_response(request.url, + h, b, s = provider.create_access_token_response(request.url, http_method=request.method, body=request.data, headers=request.headers) diff --git a/oauthlib/oauth1/rfc5849/endpoints/access_token.py b/oauthlib/oauth1/rfc5849/endpoints/access_token.py index 9950d5b..10d4ad0 100644 --- a/oauthlib/oauth1/rfc5849/endpoints/access_token.py +++ b/oauthlib/oauth1/rfc5849/endpoints/access_token.py @@ -57,18 +57,17 @@ class AccessTokenEndpoint(BaseEndpoint): :param body: The request body as a string. :param headers: The request headers as a dict. :param credentials: A list of extra credentials to include in the token. - :returns: A tuple of 4 elements. - 1. None (uri but n/a for this endpoint, here for consistency. - 2. A dict of headers to set on the response. - 3. The response body as a string. - 4. The response status code as an integer. + :returns: A tuple of 3 elements. + 1. A dict of headers to set on the response. + 2. The response body as a string. + 3. The response status code as an integer. An example of a valid request:: >>> from your_validator import your_validator >>> from oauthlib.oauth1 import AccessTokenEndpoint >>> endpoint = AccessTokenEndpoint(your_validator) - >>> u, h, b, s = endpoint.create_access_token_response( + >>> h, b, s = endpoint.create_access_token_response( ... 'https://your.provider/access_token?foo=bar', ... headers={ ... 'Authorization': 'OAuth oauth_token=234lsdkf....' @@ -76,8 +75,6 @@ class AccessTokenEndpoint(BaseEndpoint): ... credentials={ ... 'my_specific': 'argument', ... }) - >>> u - None >>> h {'Content-Type': 'application/x-www-form-urlencoded'} >>> b @@ -106,11 +103,11 @@ class AccessTokenEndpoint(BaseEndpoint): request) if valid: token = self.create_access_token(request, credentials or {}) - return None, resp_headers, token, 200 + return resp_headers, token, 200 else: - return None, {}, None, 401 + return {}, None, 401 except errors.OAuth1Error as e: - return None, resp_headers, e.urlencoded, e.status_code + return resp_headers, e.urlencoded, e.status_code def validate_access_token_request(self, request): """Validate an access token request. diff --git a/oauthlib/oauth1/rfc5849/endpoints/authorization.py b/oauthlib/oauth1/rfc5849/endpoints/authorization.py index 7fe39c4..5b78299 100644 --- a/oauthlib/oauth1/rfc5849/endpoints/authorization.py +++ b/oauthlib/oauth1/rfc5849/endpoints/authorization.py @@ -13,7 +13,10 @@ from oauthlib.common import Request, add_params_to_uri from .base import BaseEndpoint from .. import errors - +try: + from urllib import urlencode +except ImportError: + from urllib.parse import urlencode class AuthorizationEndpoint(BaseEndpoint): """An endpoint responsible for letting authenticated users authorize access @@ -59,33 +62,48 @@ class AuthorizationEndpoint(BaseEndpoint): :param body: The request body as a string. :param headers: The request headers as a dict. :param credentials: A list of credentials to include in the verifier. - :returns: A tuple of 4 elements. - 1. The URI to be used to redirect the user back to client. - 2. A dict of headers to set on the response. - 3. The response body as a string. - 4. The response status code as an integer. + :returns: A tuple of 3 elements. + 1. A dict of headers to set on the response. + 2. The response body as a string. + 3. The response status code as an integer. + + If the callback URI tied to the current token is "oob", a response with + a 200 status code will be returned. In this case, it may be desirable to + modify the response to better display the verifier to the client. - An example of a valid request:: + An example of an authorization request:: >>> from your_validator import your_validator - >>> from oauthlib.oauth1 import RequestTokenEndpoint - >>> endpoint = RequestTokenEndpoint(your_validator) - >>> u, h, b, s = endpoint.create_request_token_response( - ... 'https://your.provider/request_token?foo=bar', - ... headers={ - ... 'Authorization': 'OAuth realm=movies user, oauth_....' - ... }, + >>> from oauthlib.oauth1 import AuthorizationEndpoint + >>> endpoint = AuthorizationEndpoint(your_validator) + >>> h, b, s = endpoint.create_authorization_response( + ... 'https://your.provider/authorize?oauth_token=...', ... credentials={ ... 'extra': 'argument', ... }) - >>> u - 'https://the.client/callback?oauth_verifier=...&mextra=argument' >>> h - {} + {'Location': 'https://the.client/callback?oauth_verifier=...&extra=argument'} >>> b - '' + None >>> s 302 + + An example of a request with an "oob" callback:: + + >>> from your_validator import your_validator + >>> from oauthlib.oauth1 import AuthorizationEndpoint + >>> endpoint = AuthorizationEndpoint(your_validator) + >>> h, b, s = endpoint.create_authorization_response( + ... 'https://your.provider/authorize?foo=bar', + ... credentials={ + ... 'extra': 'argument', + ... }) + >>> h + {'Content-Type': 'application/x-www-form-urlencoded'} + >>> b + 'oauth_verifier=...&extra=argument' + >>> s + 200 """ request = self._create_request(uri, http_method=http_method, body=body, headers=headers) @@ -104,11 +122,16 @@ class AuthorizationEndpoint(BaseEndpoint): description=('User granted access to realms outside of ' 'what the client may request.')) + verifier = self.create_verifier(request, credentials or {}) redirect_uri = self.request_validator.get_redirect_uri( request.resource_owner_key, request) - verifier = self.create_verifier(request, credentials or {}) - uri = add_params_to_uri(redirect_uri, verifier.items()) - return uri, {}, None, 302 + if redirect_uri == 'oob': + response_headers = {'Content-Type': 'application/x-www-form-urlencoded'} + response_body = urlencode(verifier) + return response_headers, response_body, 200 + else: + populated_redirect = add_params_to_uri(redirect_uri, verifier.items()) + return {'Location': populated_redirect}, None, 302 def get_realms_and_credentials(self, uri, http_method='GET', body=None, headers=None): diff --git a/oauthlib/oauth1/rfc5849/endpoints/request_token.py b/oauthlib/oauth1/rfc5849/endpoints/request_token.py index 2956bcc..424e33f 100644 --- a/oauthlib/oauth1/rfc5849/endpoints/request_token.py +++ b/oauthlib/oauth1/rfc5849/endpoints/request_token.py @@ -51,18 +51,17 @@ class RequestTokenEndpoint(BaseEndpoint): :param body: The request body as a string. :param headers: The request headers as a dict. :param credentials: A list of extra credentials to include in the token. - :returns: A tuple of 4 elements. - 1. None (uri but n/a for this endpoint, here for consistency. - 2. A dict of headers to set on the response. - 3. The response body as a string. - 4. The response status code as an integer. + :returns: A tuple of 3 elements. + 1. A dict of headers to set on the response. + 2. The response body as a string. + 3. The response status code as an integer. An example of a valid request:: >>> from your_validator import your_validator >>> from oauthlib.oauth1 import RequestTokenEndpoint >>> endpoint = RequestTokenEndpoint(your_validator) - >>> u, h, b, s = endpoint.create_request_token_response( + >>> h, b, s = endpoint.create_request_token_response( ... 'https://your.provider/request_token?foo=bar', ... headers={ ... 'Authorization': 'OAuth realm=movies user, oauth_....' @@ -70,8 +69,6 @@ class RequestTokenEndpoint(BaseEndpoint): ... credentials={ ... 'my_specific': 'argument', ... }) - >>> u - None >>> h {'Content-Type': 'application/x-www-form-urlencoded'} >>> b @@ -100,11 +97,11 @@ class RequestTokenEndpoint(BaseEndpoint): request) if valid: token = self.create_request_token(request, credentials or {}) - return None, resp_headers, token, 200 + return resp_headers, token, 200 else: - return None, {}, None, 401 + return {}, None, 401 except errors.OAuth1Error as e: - return None, resp_headers, e.urlencoded, e.status_code + return resp_headers, e.urlencoded, e.status_code def validate_request_token_request(self, request): """Validate a request token request. diff --git a/oauthlib/oauth1/rfc5849/request_validator.py b/oauthlib/oauth1/rfc5849/request_validator.py index 70ce6d9..933a65a 100644 --- a/oauthlib/oauth1/rfc5849/request_validator.py +++ b/oauthlib/oauth1/rfc5849/request_validator.py @@ -360,12 +360,16 @@ class RequestValidator(object): raise NotImplementedError("Subclasses must implement this function.") def get_redirect_uri(self, token, request): - """Get the redirect uri associated with a request token. + """Get the redirect URI associated with a request token. :param token: The request token string. :param request: An oauthlib.common.Request object. :returns: The redirect URI associated with the request token. + It may be desirable to return a custom URI if the redirect is set to "oob". + In this case, the user will be redirected to the returned URI and at that + endpoint the verifier can be displayed. + This method is used by * AuthorizationEndpoint diff --git a/tests/oauth1/rfc5849/endpoints/test_access_token.py b/tests/oauth1/rfc5849/endpoints/test_access_token.py index 0596eba..8245f61 100644 --- a/tests/oauth1/rfc5849/endpoints/test_access_token.py +++ b/tests/oauth1/rfc5849/endpoints/test_access_token.py @@ -39,33 +39,33 @@ class AccessTokenEndpointTest(TestCase): def test_check_request_token(self): self.validator.check_request_token.return_value = False - u, h, b, s = self.endpoint.create_access_token_response( + h, b, s = self.endpoint.create_access_token_response( self.uri, headers=self.headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) def test_check_verifier(self): self.validator.check_verifier.return_value = False - u, h, b, s = self.endpoint.create_access_token_response( + h, b, s = self.endpoint.create_access_token_response( self.uri, headers=self.headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) def test_validate_client_key(self): self.validator.validate_client_key.return_value = False - u, h, b, s = self.endpoint.create_access_token_response( + h, b, s = self.endpoint.create_access_token_response( self.uri, headers=self.headers) self.assertEqual(s, 401) def test_validate_request_token(self): self.validator.validate_request_token.return_value = False - u, h, b, s = self.endpoint.create_access_token_response( + h, b, s = self.endpoint.create_access_token_response( self.uri, headers=self.headers) self.assertEqual(s, 401) def test_validate_verifier(self): self.validator.validate_verifier.return_value = False - u, h, b, s = self.endpoint.create_access_token_response( + h, b, s = self.endpoint.create_access_token_response( self.uri, headers=self.headers) self.assertEqual(s, 401) @@ -75,12 +75,12 @@ class AccessTokenEndpointTest(TestCase): resource_owner_secret='secret', verifier='verfier') _, headers, _ = client.sign(self.uri + '/extra') - u, h, b, s = self.endpoint.create_access_token_response( + h, b, s = self.endpoint.create_access_token_response( self.uri, headers=headers) self.assertEqual(s, 401) def test_valid_request(self): - u, h, b, s = self.endpoint.create_access_token_response( + h, b, s = self.endpoint.create_access_token_response( self.uri, headers=self.headers) self.assertEqual(s, 200) self.assertIn('oauth_token', b) diff --git a/tests/oauth1/rfc5849/endpoints/test_authorization.py b/tests/oauth1/rfc5849/endpoints/test_authorization.py index c3876e1..d6b1a05 100644 --- a/tests/oauth1/rfc5849/endpoints/test_authorization.py +++ b/tests/oauth1/rfc5849/endpoints/test_authorization.py @@ -15,7 +15,6 @@ class ResourceEndpointTest(TestCase): self.validator.verify_request_token.return_value = True self.validator.verify_realms.return_value = True self.validator.get_realms.return_value = ['test'] - self.validator.get_redirect_uri.return_value = 'https://c.b/cb' self.validator.save_verifier = MagicMock() self.endpoint = AuthorizationEndpoint(self.validator) self.uri = 'https://i.b/authorize?oauth_token=foo' @@ -39,7 +38,17 @@ class ResourceEndpointTest(TestCase): realms=['bar']) def test_create_authorization_response(self): - u, h, b, s = self.endpoint.create_authorization_response(self.uri) + self.validator.get_redirect_uri.return_value = 'https://c.b/cb' + h, b, s = self.endpoint.create_authorization_response(self.uri) self.assertEqual(s, 302) - self.assertTrue(u.startswith('https://c.b/cb')) - self.assertIn('oauth_verifier', u) + self.assertIn('Location', h) + self.assertTrue(location.startswith('https://c.b/cb')) + self.assertIn('oauth_verifier', location) + + def test_create_authorization_response(self): + self.validator.get_redirect_uri.return_value = 'oob' + h, b, s = self.endpoint.create_authorization_response(self.uri) + self.assertEqual(s, 200) + self.assertNotIn('Location', h) + self.assertIn('oauth_verifier', b) + self.assertIn('oauth_token', b) diff --git a/tests/oauth1/rfc5849/endpoints/test_base.py b/tests/oauth1/rfc5849/endpoints/test_base.py index f175e6d..1c6bd33 100644 --- a/tests/oauth1/rfc5849/endpoints/test_base.py +++ b/tests/oauth1/rfc5849/endpoints/test_base.py @@ -27,13 +27,13 @@ class BaseEndpointTest(TestCase): def test_ssl_enforcement(self): uri, headers, _ = self.client.sign('http://i.b/request_token') - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( uri, headers=headers) self.assertEqual(s, 400) self.assertIn('insecure_transport_protocol', b) def test_missing_parameters(self): - u, h, b, s = self.endpoint.create_request_token_response(self.uri) + h, b, s = self.endpoint.create_request_token_response(self.uri) self.assertEqual(s, 400) self.assertIn('invalid_request', b) @@ -41,7 +41,7 @@ class BaseEndpointTest(TestCase): headers = {} headers['Authorization'] = self.headers['Authorization'].replace( 'HMAC', 'RSA') - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=headers) self.assertEqual(s, 400) self.assertIn('invalid_signature_method', b) @@ -50,7 +50,7 @@ class BaseEndpointTest(TestCase): headers = {} headers['Authorization'] = self.headers['Authorization'].replace( '1.0', '2.0') - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) @@ -61,21 +61,21 @@ class BaseEndpointTest(TestCase): headers['Authorization'] = sub('timestamp="\d*k?"', 'timestamp="%s"' % pattern, self.headers['Authorization']) - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) def test_client_key_check(self): self.validator.check_client_key.return_value = False - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=self.headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) def test_noncecheck(self): self.validator.check_nonce.return_value = False - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=self.headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) diff --git a/tests/oauth1/rfc5849/endpoints/test_request_token.py b/tests/oauth1/rfc5849/endpoints/test_request_token.py index 47e2c10..773dedf 100644 --- a/tests/oauth1/rfc5849/endpoints/test_request_token.py +++ b/tests/oauth1/rfc5849/endpoints/test_request_token.py @@ -34,45 +34,45 @@ class RequestTokenEndpointTest(TestCase): def test_check_redirect_uri(self): client = Client('foo') uri, headers, _ = client.sign(self.uri) - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( uri, headers=headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) def test_check_realms(self): self.validator.check_realms.return_value = False - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=self.headers) self.assertEqual(s, 400) self.assertIn('invalid_request', b) def test_validate_client_key(self): self.validator.validate_client_key.return_value = False - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=self.headers) self.assertEqual(s, 401) def test_validate_realms(self): self.validator.validate_requested_realms.return_value = False - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=self.headers) self.assertEqual(s, 401) def test_validate_redirect_uri(self): self.validator.validate_redirect_uri.return_value = False - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=self.headers) self.assertEqual(s, 401) def test_validate_signature(self): client = Client('foo', callback_uri='https://c.b/cb') _, headers, _ = client.sign(self.uri + '/extra') - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=headers) self.assertEqual(s, 401) def test_valid_request(self): - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( self.uri, headers=self.headers) self.assertEqual(s, 200) self.assertIn('oauth_token', b) @@ -85,7 +85,7 @@ class RequestTokenEndpointTest(TestCase): client_secret='bar') uri = self.uri + '?realm=foo' _, headers, _ = client.sign(uri) - u, h, b, s = self.endpoint.create_request_token_response( + h, b, s = self.endpoint.create_request_token_response( uri, headers=headers) self.assertEqual(s, 200) self.assertIn('oauth_token', b) |