summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIb Lundgren <ib.lundgren@gmail.com>2013-05-31 12:27:18 +0100
committerIb Lundgren <ib.lundgren@gmail.com>2013-05-31 12:27:18 +0100
commit9eb671f9d2ebb37fded5f3d77d274fb1c38038ca (patch)
tree1e74cd9b78c1deba0951d18dc1aecbfa8336a4e4
parent79214fe20e9c37b7ef64e6bea7354a9bd0ab2fd0 (diff)
downloadoauthlib-9eb671f9d2ebb37fded5f3d77d274fb1c38038ca.tar.gz
Outline example view setup for providers.
-rw-r--r--docs/oauth2/server.rst140
1 files changed, 136 insertions, 4 deletions
diff --git a/docs/oauth2/server.rst b/docs/oauth2/server.rst
index 5c50d1a..22e5d43 100644
--- a/docs/oauth2/server.rst
+++ b/docs/oauth2/server.rst
@@ -230,7 +230,6 @@ as well as provide an interface for a backend to store tokens, clients, etc.
from my_validator import MyRequestValidator
from oauthlib.oauth2 import WebApplicationServer
- from oauthlib.oauth2.ext.django import OAuth2ProviderDecorator
validator = MyRequestValidator()
server = WebApplicationServer(validator)
@@ -251,12 +250,145 @@ as well as provide an interface for a backend to store tokens, clients, etc.
users to if the client supplied invalid credentials in their redirection,
for example an invalid redirect URI.
- The rest of this section will come soon.
+ The example using Django but should be transferable to any framework.
+
+ .. code-block:: python
+
+ # Handles GET and POST requests to /authorize
+ class AuthorizationView(View):
+
+ def __init__(self):
+ # Using the server from previous section
+ self._authorization_endpoint = server
+ self._error_uri = '/error'
+
+ def get(self, request):
+ # You need to define extract_params and make sure it does not
+ # include file like objects waiting for input. In Django this
+ # is request.META['wsgi.input'] and request.META['wsgi.errors']
+ uri, http_method, body, headers = extract_params(request)
+
+ try:
+ scopes, credentials = self._authorization_endpoint.validate_authorization_request(
+ uri, http_method, body, headers)
+
+ # Not necessarily in session but they need to be
+ # accessible in the POST view after form submit.
+ request.session['oauth2_credentials'] = credentials
+
+ # You probably want to render a template instead.
+ response = HttpResponse()
+ response.write('<h1> Authorize access to %s </h1>' % client_id)
+ response.write('<form method="POST" action="/authorize">')
+ for scope in scopes or []:
+ response.write('<input type="checkbox" name="scopes" ' +
+ 'value="%s"/> %s' % (scope, scope))
+ response.write('<input type="submit" value="Authorize"/>')
+ return response
+
+ # Errors that should be shown to the user on the provider website
+ except errors.FatalClientError as e:
+ return HttpResponseRedirect(e.in_uri(self._error_uri))
+
+ # Errors embedded in the redirect URI back to the client
+ except errors.OAuth2Error as e:
+ return HttpResponseRedirect(e.in_uri(e.redirect_uri))
+
+ @csrf_exempt
+ def post(self, request):
+ uri, http_method, body, headers = extract_params(request)
+
+ # The scopes the user actually authorized, i.e. checkboxes
+ # that were selected.
+ scopes = request.POST.getlist(['scopes'])
+
+ # Extra credentials we need in the validator
+ credentials = {'user': request.user}
+
+ # The previously stored (in authorization GET view) credentials
+ credentials.update(request.session.get('oauth2_credentials', {}))
+
+ try:
+ url, headers, body, status = self._authorization_endpoint.create_authorization_response(
+ uri, http_method, body, headers, scopes, credentials)
+ return HttpResponseRedirect(url)
+
+ except errors.FatalClientError as e:
+ return HttpResponseRedirect(e.in_uri(self._error_uri))
+
+ except errors.OAuth2Error as e:
+ return HttpResponseRedirect(e.in_uri(redirect_uri))
+
+ # Handles requests to /token
+ class TokenView(View):
+
+ def __init__(self):
+ # Using the server from previous section
+ self._token_endpoint = server
+
+ def post(self, request):
+ uri, http_method, body, headers = extract_params(request)
+
+ # If you wish to include request specific extra credentials for
+ # use in the validator, do so here.
+ credentials = {'foo': 'bar'}
+
+ url, headers, body, status = self._token_endpoint.create_token_response(
+ uri, http_method, body, headers, credentials)
+
+ # All requests to /token will return a json response, no redirection.
+ response = HttpResponse(content=body, status=status)
+ for k, v in headers.items():
+ response[k] = v
+ return response
+
+
+ class ErrorView(View):
+ response = HttpResponse()
+ response.write('Evil client is unable to send a proper request.')
+ return response
**5. Protect your APIs using scopes**
- The definition of ``protected_resource_view`` will come soon. Please see
- the framework specific extensions outlined in the beginning for now.
+ Let's define a decorator we can use to protect the views.
+
+ .. code-block:: python
+
+ class OAuth2ProviderDecorator(object):
+
+ def __init__(self, resource_endpoint):
+ self._resource_endpoint = resource_endpoint
+
+ def protected_resource_view(self, scopes=None):
+ def decorator(f):
+ @functools.wraps(f)
+ def wrapper(request):
+ # Get the list of scopes
+ try:
+ scopes_list = scopes(request)
+ except TypeError:
+ scopes_list = scopes
+
+ uri, http_method, body, headers = extract_params(request)
+
+ valid, r = self._resource_endpoint.verify_request(
+ uri, http_method, body, headers, scopes_list)
+
+ # For convenient parameter access in the view
+ add_params(request, {
+ 'client': r.client,
+ 'user': r.user,
+ 'scopes': r.scopes
+ })
+ if valid:
+ return f(request)
+ else:
+ # Framework specific HTTP 403
+ return HttpResponseForbidden()
+ return wrapper
+ return decorator
+
+ provider = OAuth2ProviderDecorator(server)
At this point you are ready to protect your API views with OAuth. Take some
time to come up with a good set of scopes as they can be very powerful in