Introduction
In the Getting Started with AuthKit article we saw on way to check user permissions using the authorised() function. This approach required manually raising NotAuthenticatedError and NotAuthorizedError exceptions when necessary.
There are actually three other ways of checking permissions which automatically raise the correct exceptions if a permission check fails.
The authorize_request() Function
Following on from the example in the Getting Started with AuthKit article you can use a the authorize_request() function like this:
...
def app(environ, start_response):
authorize_request(environ, permission)
start_response('200 OK', [('Content-type','text/plain')])
return ['User is an administrator']
}
...
In this case you don't need to worry about handling the case when the user isn't authorized because the authorize_request() function automatically raises the appropriate exception for you.
Authorize Middleware
If for example you wanted to check a particular permission on every request you could setup some authorisation middleware like this:
import authkit.authenticate
import authkit.authorize
from authkit.permissions import HasAuthKitRole
permission = HasAuthKitRole('admin')
app = authkit.authorize.middleware(app, permission)
app = authkit.authenticate.middleware(app, app_conf)
serve(app, port=8080, host='0.0.0.0')
If you take this approach you have to ensure that the authorize middleware is setup before the authenticate middleware.
Authorize Decorator
There is one final way to authorize a user with a permission and that is with the authorise() decorator. The decorator is useful when you are using a WSGI application that takes the form of a class (a Pylons controller is a good example) and you want to check permissions on a method by method basis.
from authkit.authorize import authorize
from authkit.permissions import RemoteUser
permission = RemoteUser()
class TestController:
def index(self):
start_response('200 OK', [('Content-type','text/plain')])
return ['This is public']
@authorize(permission)
def private(self, environ, start_response):
start_response('200 OK', [('Content-type','text/plain')])
return ['This is private']
def __call__(self, environ, start_response):
if environ['PATH_INFO'] == '/':
return self.index(environ, start_response)
elif environ['PATH_INFO'] == '/private':
return self.private(environ, start_response)
else:
raise Exception('Not handled')
Framework-Specific Adaptors
If you've been reading closely you'll have noticed that the authorized() and authorize_request() functions both need to have the WSGI environ as their first argument so that they can obtain information about the request. You may also have noticed that while the @authorize() decorator works well with the type of class described in the example above it won't work with Pylons actions because they don't take environ and start_response as their arguments.
Both these problems are solved with AuthKit's authkit.pylons_adptors module. Here's the @authorize() decorator example using a Pylons controller:
from authkit.pylons_adaptors import authorize
from authkit.permissions import RemoteUser
permission = RemoteUser()
class TestController(BaseController):
def index(self):
return Response('This is public')
@authorize(permission)
def private(self):
return Response('This is private')
Notice we imported the @authorize() decorator from the authkit.pylons_adaptors module rather than the authkit.authorize module. You can also import the authorized() and authorize_request() functions from the authkit.pylons_adaptors module. They behave exactly the same as their authkit.authorize counterparts but don't take the WSGI environ as their first argument since it is obtained automatically from pylons.request.
The authorize middleware works perfectly with any WSGI application including Pylons without needing a framework-specific version.