Skip to content

Commit

Permalink
Merge 517e01f into f794cf3
Browse files Browse the repository at this point in the history
  • Loading branch information
squirly committed Aug 2, 2013
2 parents f794cf3 + 517e01f commit b5f3cb2
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 75 deletions.
3 changes: 2 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ Mackenzie Thompson
Hsiaoming Yang
Devin Sevilla
Clint Ecker
Kyle Valade
Kyle Valade
Tyler Jones (squirly)
12 changes: 8 additions & 4 deletions docs/oauth1/server.rst
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,15 @@ 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__)
@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)
Expand All @@ -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)
Expand Down
19 changes: 8 additions & 11 deletions oauthlib/oauth1/rfc5849/endpoints/access_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,27 +57,24 @@ def create_access_token_response(self, uri, http_method='GET', body=None,
: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....'
... },
... credentials={
... 'my_specific': 'argument',
... })
>>> u
None
>>> h
{'Content-Type': 'application/x-www-form-urlencoded'}
>>> b
Expand Down Expand Up @@ -106,11 +103,11 @@ def create_access_token_response(self, uri, http_method='GET', body=None,
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.
Expand Down
65 changes: 44 additions & 21 deletions oauthlib/oauth1/rfc5849/endpoints/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@

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
Expand Down Expand Up @@ -59,33 +62,48 @@ def create_authorization_response(self, uri, http_method='GET', body=None,
: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)
Expand All @@ -104,11 +122,16 @@ def create_authorization_response(self, uri, http_method='GET', body=None,
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):
Expand Down
19 changes: 8 additions & 11 deletions oauthlib/oauth1/rfc5849/endpoints/request_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,24 @@ def create_request_token_response(self, uri, http_method='GET', body=None,
: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_....'
... },
... credentials={
... 'my_specific': 'argument',
... })
>>> u
None
>>> h
{'Content-Type': 'application/x-www-form-urlencoded'}
>>> b
Expand Down Expand Up @@ -100,11 +97,11 @@ def create_request_token_response(self, uri, http_method='GET', body=None,
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.
Expand Down
6 changes: 5 additions & 1 deletion oauthlib/oauth1/rfc5849/request_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,12 +360,16 @@ def get_realms(self, token, request):
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
Expand Down
14 changes: 7 additions & 7 deletions tests/oauth1/rfc5849/endpoints/test_access_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,33 +39,33 @@ def setUp(self):

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)

Expand All @@ -75,12 +75,12 @@ def test_validate_signature(self):
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)
Expand Down
17 changes: 13 additions & 4 deletions tests/oauth1/rfc5849/endpoints/test_authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ def setUp(self):
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'
Expand All @@ -39,7 +38,17 @@ def test_verify_realms(self):
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)
Loading

0 comments on commit b5f3cb2

Please sign in to comment.