| Developers' Guide | ODP::Passport |
| Introduction: |
ODP::Passport provides a centralised editor authentication system for non-official ODP tools.
It allows tool developers to restrict tools to active editors, or further by privilege level, without needing to implement their own authentication system, provide users with another password, and check whether or not editors are active.
Whilst this document covers use of the system assuming a Perl environment, one can implement the client side in any language they choose.
If this document looks long and complicated, don't worry, to implement the basics is straightforward. If you have any questions about the system, or any difficulties setting it up, please don't hesitate to get in touch with editor rpfuller.
| Basics: |
To implement an ODP::Passport client first you will need to install the relevant modules on your system. You can find the code at http://research.dmoz.org/~rpfuller/src/
In order for the system to work, your client and the ODP::Passport server must share a 'secret'. You should choose a complex secret (up to 255 characters)
You will then need a login.cgi and a logout.cgi.
Sample code:
#!/usr/bin/perl
use CGI qw(:standard);
use ODP::Passport;
my $client = new ODP::Passport ();
$client -> login('your secret',param('user'),param('key'),param('issued'),param('privs'));
my %tools=(
'Test'=>'http://rpfuller.org/odp/spell/test.cgi',
'Another'=>'http://rpfuller.org/odp/spell/another.cgi'
);
if (substr(param('tool'),0,9) eq 'ppstatic:')
{
my $url = substr(param('tool'),9);
print <<END_HTML;
<head>
<meta http-equiv="refresh" content="0;URL=$url">
</head>
<body></body>
END_HTML
}
elsif ($tools{param('tool')})
{
my $params;
foreach my $param (param())
{
if ($param =~ /^pp_p_(.*)$/)
{
if ($params){$params.='&'}
$params.="$1=".param($param);
}
}
if ($params){$params="?$params"}
print <<END_HTML;
<head>
<meta http-equiv="refresh" content="0;URL=$tools{param('tool')}$params">
</head>
<body></body>
END_HTML
}
else
{
print 'Available tools:';
print '<li><a href="http://rpfuller.org/odp/spell/test.cgi">test.cgi</a></li>';
print '<li><a href="http://rpfuller.org/odp/spell/another.cgi">another.cgi</a></li>';
print '<hr><a href="logout.cgi">Logout</a>';
}
#!/usr/bin/perl use CGI qw(:standard); use ODP::Passport; my $client = new ODP::Passport; $client -> logout();
Your entire collection of tools needs a name. You can use the hostname of your server, or some other suitable descriptor.
Each tool requires a name unique within the collection. You are free to control this namespace as you wish, although for obvious reasons tool names should not be excessively long or offensive. You should also note that ppstatic: is a reserved prefix.
#!/usr/bin/perl
use ODP::Passport;
my $client = new ODP::Passport;
$client -> checklogin('your secret','your tool collection name','tool name');
Sometimes you don't want an entire tool to be restricted to ODP editors, just parts. ODP::Passport allows you to do this.
Instead of using $client -> checklogin use $client -> checklogin_nohalt instead.
Passport will no longer halt or redirect the user, but return. If the user is logged in with ODP::Passport, appropriate environment variables will be set. You can then test if the user is logged in by using, for example, the PP_ISSUED environment variable.
Example code:
#!/usr/bin/perl
use ODP::Passport;
my $client = new ODP::Passport;
$client -> checklogin_nohalt('your secret','your tool collection name','tool name');
print "Content-type: text/html\n\n";
if ($ENV{'PP_ISSUED'})
{
print "Hello $ENV{'REMOTE_USER'}.";
}
else
{
print "Hello guest.";
}
For the entire collection, you need to send:
Once you have a secret in the system you can create/modify tools using the web interface. For each tool you'll need to enter:
| Customising login.cgi: |
If you use the standard login.cgi outlined above you'll need to add an entry for each tool you want direct forwarding for. To set this up you need to change the my %tools= block. Example:
my %tools=( 'Test'=>'http://rpfuller.org/odp/spell/test.cgi', 'Another'=>'http://rpfuller.org/odp/spell/another.cgi' );
In this example Test and Another are the names of tools.
If you have a lot of CGIs and want to direct-forward them all, you should put your CGIs in one folder, and use their filename for the tool name. Then you can use this variation of login.cgi:
#!/usr/bin/perl
use CGI qw(:standard);
use ODP::Passport;
my $client = new ODP::Passport ();
$client -> login('your secret',param('user'),param('key'),param('issued'),param('privs'));
if (substr(param('tool'),0,9) eq 'ppstatic:')
{
my $url = substr(param('tool'),9);
print <<END_HTML;
<head>
<meta http-equiv="refresh" content="0;URL=$url">
</head>
<body></body>
END_HTML
exit;
}
my $params;
foreach my $param (param())
{
if ($param =~ /^pp_p_(.*)$/)
{
if ($params){$params.='&'}
$params.="$1=".param($param);
}
}
if ($params){$params="?$params"}
my $tool = param('tool');
print <<END_HTML;
<head>
<meta http-equiv="refresh" content="0;URL=http://pathwhereyour/cgis/are/$tool$params">
</head>
<body></body>
END_HTML
You just need to set http://pathwhereyour/cgis/are/ to the correct location, rather than adding an entry for every tool.
| Restricting Scripts by Privileges: |
To protect an entire script you can supply a code along with your checklogin call.
Example:
$client -> checklogin('your secret','your tool collection name','tool name',1,'j');
In this example the j indicates that the script requires the user to have jmeta privileges. (They are a root editor, meta, kmeta, catmod, or kcatmod.)
The list of possible privilege codes is as follows:
| Code | Description | Allowed Access |
| ce | PEditall Readers | kcateditall, cateditall, keditall, editall, kcatmod, catmod, kmeta, meta, admin, root |
| e | Editall/Catmod+ | keditall, editall, kcatmod, catmod, kmeta, meta, admin, root |
| j | JMeta Readers | kcatmod, catmod, kmeta, meta, admin, root |
| k|m | KMetas/Metas | kmeta, meta, admin, root |
| k | KMetas | kmeta, admin, root |
| m | Metas | meta, admin, root |
| a | Admins | admin, root |
Note: The 1 in the example is not related to privileges, see 'godirect' under the 'Other Functions' section for more information about this option.
If you want your tool to show on the ODP::Passport index only for people with the required privileges to use it, you can set a privilege level on the 'Manage my Tools' screen.
| Privilege Handling Within Scripts: |
For finer granularity, there are two options.
ODP::Passport provides a collection of functions for analysing a user's privileges:
canreadpeditall() - User can read peditall, equivalent to code 'ce'iseditallplus() - User is editall/catmod+, equivalent to code 'e'canreadjmeta() - User can read jmeta, equivalent to code 'j'canreadkmeta() - User can read kmeta, equivalent to code 'k'canreadpmeta() - User can read pmeta, equivalent to code 'p'issomekindofmeta() - User is some kind of meta, equivalent to code 'k|m'isadmin() - User is an ODP administrator, equivalent to code 'a'You can read the raw privilege string either from the privileges() function, or the environment variable 'PP_PRIVS'.
Example privilege strings:
| Other Functions, Functionality and Environment Variables Provided: |
This is provided by the currentuser() function and the environment variable 'REMOTE_USER' (for compatability with Apache's basic authentication)
The time (in seconds since the epoch) the key was issued is available from the 'PP_ISSUED' environment variable.
This is provided by the language() function and the environment variable 'PP_LANGUAGE'.
When a user tries to access your tool, and doesn't have a valid cookie key, there are two options:
To redirect the user straight to the ODP::Passport server to get a key:
$client -> checklogin('your secret','your tool collection name','tool name',1);
To display a message telling them they need to go to the ODP::Passport server to get a key:
$client -> checklogin('your secret','your tool collection name','tool name',0);
| The Blocklist Extension: |
Passport, in the nature of its design, allows editors whose accounts have expired access for up to 48 hours. Very, very occasionally, it may be desirable to revoke all Passport access immediately.
By supporting the blocklist extension, when an editor's Passport account is specially revoked, your tools will become inaccessible, immediately, to that editor.
To support the blocklist extension, all you need is to specify a location to store a blocklist, for the login, checklogin, and checklogin_nohalt calls. In the examples it is called pp_config as it is possible additional configuration values may be stored here in the future. Examples:
In login.cgi:
$client -> login('your secret',param('user'),param('key'),param('issued'),param('privs'),'','/home/user/data/pp_config');
In all tools that require Passport:
$client -> checklogin('your secret','your tool collection name','tool name',1,'j','/home/user/data/pp_config');
In all tools that optionally use Passport:
$client -> checklogin_nohalt('your secret','your tool collection name','tool name','/home/user/data/pp_config');
Once you have this setup, you will need to ask rpfuller to enable your collection for the blocklist extension, in order to receive updates.
| Protecting Static HTML Pages and Other Files: |
If you're using Apache, and have a sufficient level of access, you can install the passport-static wrapper, and configure Apache to use it, in order to protect static pages and files.
First you'll need to copy passport-static to a folder on your web server, for example your cgi-bin folder.
Next you should modify this file to insert the correct values of 'your secret', 'your tool collection', the path to your mime.types file, and whether you want go direct or not. e.g.
my $global_secret = 'mysecret'; my $global_toolcollection = 'mytoolcollection'; my $global_mimetypespath = '/etc/apache/mime.types'; my $global_godirect = 1; my $ppconfig = '/home/user/data/ppconfig';
The value of ppconfig is optional, see the section on the blocklist extension for more information.
Now you'll need to tell Apache that this script is the correct handler.
You can do this by adding directives to your httpd.conf file:
AddHandler passport-static .phtml Action passport-static /cgi-bin/passport-staticwhere /cgi-bin/passport-static is the webserver relative location you placed passport-static.
If you really want to do this:
AddHandler passport-static .html AddHandler passport-static .phtml Action passport-static /cgi-bin/passport-static
To the .htaccess file add:
SetHandler passport-static Action passport-static /cgi-bin/passport-static
Note this will break CGIs/PHP scripts/etc. so only use it in a folder containing only static files. Also note that it will not protect directory indexes, so you should turn these off or use appropriate index.html pages.
For example to protect .html, .phtml, .jpg, .jpeg and .png files within a folder add to .htaccess:
AddHandler passport-static .html AddHandler passport-static .phtml AddHandler passport-static .jpg AddHandler passport-static .jpeg AddHandler passport-static .png Action passport-static /cgi-bin/passport-static
| Mailing List: |
If you are using ODP::Passport authentication on your site, plan to do so, or are just generally interested in the system, you may wish to sign up to the mailing list, where updates to the system will be announced. Contact rpfuller to join or leave.
| Future Developments: |
Clearly passport-static is a hack. Clearly I should write a proper Apache module. Clearly I need more hours in a day.
| Last Updated: 21st October, 2004 | Copyright © 2002-2004 Richard P. Fuller |