Version 2.4.0 12 04 08 Français

16. Authentication and user management

16.1 Login(), Logout() and Role()

For user authentication, Karrigell provides a framework using 3 built-in functions, Login(), Logout() and Role(). The default implementation relies on a users database managed by the script users.ks, which is reserved to the site administrator. This script is available from the home page : Administration/Users management Users can have different roles, returned by function Role() :
  • None if user is not logged in
  • visit if user is logged as "visitor" : can only see pages, but not edit them
  • edit if user is logged as "editor" : can edit data
  • admin if user is logged as site administrator

The user management script allows you to create other roles (link "Manage user roles") ; you can add other roles and remove default roles, except admin

To restrict the access to a script to users who have a given role, use the function Login(role=list_of_roles). When it is executed, it checks if the user is authenticated (using a cookie mechanism) ; if not :

  • a redirection is performed to a script (by default /login.ks/login) which prompts the user for a login and password
  • nother script checks if login and password are present in the users database and if the user with these login and password has the requested role
  • if so, a redirection is performed to the original script, or to another path which can be specified as argument to Login() : Login(role=["admin"],path="/send_me_here_after_login")

Another script than the default /login.ks/login can be specified as argument to the Login() function : Login("/utils/custom_login.py") for instance

Logout() writes a link to a logout script. The text of this link is "Logout" by default, it can be specified as argument : Logout("Disconnect"). If the user is not authenticated, the empty string is returned

16.2 Example

This is the script loginTest.ks in webapps/demo:

def index():
    # check if user is the administrator
    Login(role=["edit","admin"])
    # only shows is Login successful
    print "Logged in as ",Role()
    print "<br>",Logout()

If user is not logged is as administrator or editor, Login() redirects to the page requesting login and password

If he is logged as "edit" or "admin", Login() doesn't do anything and the rest of the function index() is run : function Role() returns the current user role and presents a link to log out

If the user clicks on this link, after the logout script is run, a redirection is performed to the script. Since user is no more logged in, the Login() function redirects again to the login form

16.3 Basic HTTP authentication

Karrigell supports basic HTTP authentication, a way to protect access to some files by requesting a user identifier and a password. The server receives user input and stores it in the global variables AUTH_USER and AUTH_PASSWORD. If the user enters a couple which is allowed by the server then the page is sent back ; if the couple is not allowed then the user is requested a new couple ; if the user cancels his request an error message is sent to him

In Karrigell, authentication is handled through the Authentication function ; call Authentication(testFunction[,realm, errorMessage]) where testFunction is a user-defined function taking no argument, which returns true if the authentication test succeeds (depending on the values of AUTH_USER and AUTH_PASSWORD) and false otherwise, realm is a string with the name of the authentication domain (the one that will appear on the popup window) and errorMessage is a string displayed on the browser if the user cancels his authentication request. Both realm and errorMessage have default values

Here is an example with a very simple test function :

<%
def authTest():
    return (AUTH_USER=="proust" and AUTH_PASSWORD=="marcel")
Authentication(authTest,"Authentication test",\
    "Sorry, you are not allowed to access this page")
%>
Welcome, authenticated user !

With this test function, if a visitor finds a way to read the source code, he will easily discover a valid login/password couple. A better solution is to use md5 : it is a function which takes a string as argument, and returns a 16-bytes "digest". The digest is guaranteed to be different for two different strings, and it is impossible to find the string if you only know the digest
A good method is to compute the md5 digests of user and password and store them in a file. The authentication test will read this file, compute the digests of AUTH_USER and AUTH_PASSWORD, and return true if the digests match

<%
import md5
digests=open("digest.ini","rb").read()
userDigest=digests[:16]
passwordDigest=digests[16:]
def authTest():
    return (md5.new(AUTH_USER).digest()==userDigest and \
        md5.new(AUTH_PASSWORD).digest()==passwordDigest)
Authentication(authTest,"Authentication test",\
    "Sorry, you are not allowed to access this page")
%>
Welcome, authenticated user !

See the k_password.py script, in the admin directory, which generates a file with the md5 digests of administrator's login and password