Dashboard > AuthKit Cookbook > ... > AuthKit Authentication Methods > Forward
  AuthKit Cookbook Log In | Sign Up   View a printable version of the current page.  
  Forward
Added by James Gardner, last edited by Brandon Singer on Jul 23, 2007  (view change)
Labels: 
(None)

Forwarding

Arguably the most flexible and powerful system for authentication is for the middleware to internally forward the request to a different part of the application if a 401 status is intercepted. The application itself is then responsible for displaying that page to take care of displaying a sign in form, authenticate a user, set a cookie and sign the user out in whichever way the application author thinks is best.

The foward middleware sets up the cookie middleware used by the form method but you still need to manually set the cookie after the user has signed in using your own custom sign in form which you would have implemented yourself.

The cookie can be set like this:

1
environ['paste.auth_tkt.set_user'](username)

To use paste.auth_tkt.set_user, you need to first include cookie in the authkit.setup.method setting like this:

1
authkit.setup.method = forward, cookie

If you specify a cookie_signoutpath when you set up the authentication middleware the user will be signed out automatically when visiting that path but you will still need to display a "signed out" path at that URL or the user will see a 404 page and think they haven't been signed out.

Alternatively you can sign out the user manually by setting a cookie with the same name but no value or using the environ['paste.auth_tkt.logout_user']() method documented here: http://pythonpaste.org/module-paste.auth.auth_tkt.html

Here is a simple complete example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from authkit.authenticate import middleware

def sample_app(environ, start_response):
    """
    A sample WSGI application that returns a 401 status code when the path
    ``/private`` is entered, triggering the authenticate middleware to
    forward to ``/signin`` where the user is prompted to sign in.

    If the sign in is successful a cookie is set and the user can visit
    the ``/private`` path.

    The path ``/signout`` will display a signed out message if
    and sign the user out if cookie_signout = '/signout' is specified in
    the middelware config.

    The path ``/`` always displays the environment.
    """
    if environ['PATH_INFO'] == '/private' and 'REMOTE_USER' not in environ:
        start_response('401 Not signed in', [])
    elif environ['PATH_INFO'] == '/signout':
        start_response('200 OK', [('Content-type', 'text/plain')])
        if 'REMOTE_USER' in environ:
            return ["Signed Out"]
        else:
            return ["Not signed in"]
    elif environ['PATH_INFO'] == '/signin':
        page = """
            <html>
            <body>
            %s
            <form action="/signin">
            Username: <input type="text" name="username" />
            Password: <input type="password" name="password" />
            <br />
            <input type="submit" value="Sign in" />
            </body>
            </html>
            """
        if 'QUERY_STRING' not in environ:
            start_response(
                '200 Sign in required',
                [('Content-type', 'text/html')]
            )
            return [page % '<p>Please Sign In</p>']
        else:
            # Quick and dirty sign in check, do it properly in your code
            params = {}
            for part in environ['QUERY_STRING'].split('&'):
                params[part.split("=")[0]] = part.split('=')[1]
            if params['username'] and params['username'] == params['password']:
                start_response('200 OK', [('Content-type', 'text/html')])
                environ['paste.auth_tkt.set_user'](params['username'])
                return ["Signed in."]
            else:
                start_response('200 OK', [('Content-type', 'text/html')])
                return [page % '<p>Invalid details</p>']

    start_response('200 OK', [('Content-type', 'text/plain')])
    result = ['You Have Access To This Page.\n\nHere is the environment...\n\n']
    for k,v in environ.iteritems():
        result.append('%s: %s\n'%(k,v))
    return result


app = middleware(
    sample_app,
    setup_method='forward,cookie',
    forward_internalpath = '/signin',
    cookie_signoutpath = '/signout',
    cookie_secret = 'somesecret',
)

if __name__ == '__main__':
    from paste.httpserver import serve
    serve(app, host='0.0.0.0', port=8080)

Note

If you are using any of the examples shown so far with permissions objects (described later) you will also need to include the paste httpexceptions middleware otherwise the NotAuthorizedError and NotAuthenticatedError errors will not be converted to status codes which the authenticate middleware use.

You can set this up by adding the following lines before you add the authenticate middleware:

1
2
from paste import httpexceptions
test_app = httpexceptions.middleware(test_app)

A full description of the cookie options you can use is described in the cookie options section.

Site running on a free Atlassian Confluence Open Source Project License granted to Pylons. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.3.3 Build:#645 Feb 13, 2007) - Bug/feature request - Contact Administrators