The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Apache2::Controller::Auth::OpenID - OpenID for Apache2::Controller

VERSION

Version 1.000.001 - FIRST RELEASE

UNIMPLEMENTED

UNIMPLEMENTED! Peril! Pitfalls! Pernicious knids!

SYNOPSIS

 PerlLoadModule Apache2::Controller::Directives

 <Location /myapp>
     SetHandler modperl

     # uri to your login controller:
     A2C_Auth_OpenID_Login          login

     # uri to your logout controller:
     A2C_Auth_OpenID_Logout         logout

     # uri to your registration controller:
     A2C_Auth_OpenID_Register       register
     # you might want to put this outside the protected area, 
     # i.e. /other/register - you can use leading '/' for absolute uri

     # idle timeout in seconds, +2m, +3h, +4D, +6M, +7Y, or 'no timeout'
     # default is 1 hour.  a month is actually 30 days, a year 365.
     A2C_Auth_OpenID_Timeout        +1h

     # name of the openid table in database:
     A2C_Auth_OpenID_Table          openid
     
     # key of the username field in table:
     A2C_Auth_OpenID_User_Field     uname

     # key of the openid url field in table:
     A2C_Auth_OpenID_URL_Field      openid_url

     # if you use multiple DBI handles, name the one in pnotes
     # that you should use for reading the openid table:
     A2C_Auth_OpenID_DBI_Name       dbh

     # by default trust_root is the result of $r->construct_url(''),
     # i.e. the top of the site (see Apache::URI)
     A2C_Auth_OpenID_Trust_Root     http://myapp.tld/somewhere

     # set a random string used as salt with time() to sha secret
     A2C_Auth_OpenID_Consumer_Secret

     # but that random salt will be reset if you restart server,
     # which may cause current logins to die, so you can specify
     # your own constant salt of arbitrary length
     A2C_Auth_OpenID_Consumer_Secret    abcdefg1234567

     # PerlHeaderParserHandlers must be invoked in order
     # to set up the session and dbi handle before checking auth
     # In this example,
     # MyApp::DBI::Connector is an Apache2::Controller::DBI::Connector
     # and MyApp::Session is an Apache2::Controller::Session::Cookie...
     # see those modules for more info.

     PerlInitHandler            MyApp::Dispatch 
     PerlHeaderParserHandler    MyApp::DBI::Connector
     PerlHeaderParserHandler    MyApp::Session
     PerlHeaderParserHandler    Apache2::Controller::Auth::OpenID
 </Location>

DESCRIPTION

Implements an authentication mechanism for Apache2::Controller that uses OpenID.

This is NOT an AuthenPerlHandler. This is an implementation of a simple cookie-based session mechanism that shows the browser a login page, where your controller should present and process an HTML form for logging in.

If you want an authentication handler that uses browser-based auth (the pop-up dialog implemented by HTTP auth protocol) use Apache::Authen::OpenID, which is not a part of Apache2::Controller but should work for you anyway.

Natively this depends on Apache2::Controller::Session::Cookie and Apache2::Controller::DBI::Connector being configured correctly, but you could always subclass this and overload the methods below to get information from other sources.

If no claimed ID is detected, the user is shown the login page. If an error occured, you'll find the Net::OpenID::Consumer error details in the session under {a2c}{openid}{errtext} and {a2c}{openid}{errcode}.

REDIRECTION OR REDISPATCH?

Whether redirecting or redispatching, stuff has to be saved in the session, so $r->notes->{a2c_session_force_save will be set.

INTERNAL LOGIN, LOGOUT AND REGISTER PAGES

RELATIVE URIS - REDISPATCH

If the uris for these pages are relative, not absolute, i.e. they are handled by the same controller that we're going to anyway, then it tries setting the uri and re-dispatching by grabbing the dispatch class name out of $r->notes->{a2c_dispatch_class} and instantiating a new dispatch handler object.

(Dispatch can't keep the handler subref around in pnotes due to circular references, or reliably assume that we know at what location in the PerlInitHandler stack the dispatch handler coderef was stored by Apache, so we just create a new one - this is assured to be faster than creating an entire new request, which would do that anyway.)

So in this case, the content for the login, logout, or register pages will appear even though the browser uri still displays the requested protected URI.

ABSOLUTE URIS - REDIRECT

If the uris for the internal pages are absolute, i.e. they might be handled by a different controller than the one that was dispatched, a redirect using Location HTTP header is used.

EXTERNAL OPENID PAGES

Any time the browser needs to go to an external page (the openid server), a redirect using a Location: HTTP header is used.

PRESERVATION OF INITIAL REQUEST

REQUESTED URI

When it goes to your login, or register page, it stashes the user's uri into the session as {a2c}{openid}{previous_uri} and should preserve this for the return url. It uses $r->construct_url() as the trusted root.

When the user passes the authentication process ($csr->verified_identity), it sets $r->notes->{a2c_openid_logged_in} for this request to let your handler know if you want to display a message like "You have successfully logged in" or something.

POST VARS

not yet...

If redirected, it also stashes the POST body into the session as {a2c}{openid}{redirect_post} but if you use this, you probably want to put some kind of form id and a unique value for every post so you're sure you're doing the right thing. I don't know if this will work, but it might be useful.

DIRECTIVES

"Apache2::Controller::Auth::OpenID" in Apache2::Controller::Directives

CACHING

If you want to provide a cache for Net::OpenID::Consumer to pass onto URI::Fetch, subclass this module and implement a method cache() that returns the appropriate cache object.

CAVEATS

I have heard there are trickier things one can do to ensure the security of a session based cookie. This module just implements a simple association of a user with a session key by storing a flag and a last-accessed time value in the session hash, nothing fancier.

This calls $r->connection->get_remote_host and saves it in the {a2c}{openid} section of the session hash. So if you don't want it to do DNS lookups, set directive HostNameLookups off.

METHODS

"These aren't the methods you're looking for."

"These aren't the methods we're looking for."

"He can go about his business."

"You can go about your business."

"Move along."

"Move along. Move along."

You don't access these methods. This is internal documentation.

default_directives

Calculate and return the hash of directive defaults. (Some of these are based on the current <Location> of the handler.)

openid_url_normalize

Correct trailing double /'s etc. in the openid url.

process

Make sure the config directives are assigned or use defaults.

If uri = login uri, process accordingly.

If uri = logout uri, delete session hash login flags and return OK.

qualify_uri

If the uri is relative, qualifies it by prepending current location. Otherwise just returns the uri.

redirect_to

 return $self->redirect_to($uri);

If one of the three internal URIs, use redispatch().

Otherwise, use location_redirect.

location_redirect

 return $self->location_redirect($uri);

Set the Location header and return REDIRECT.

Forces the session to be saved in the cleanup handler.

redispatch

 return $self->redispatch($uri);

For the internal pages (login, logout, register), if they are relative, re-dispatch them and return OK, else if absolute, set location and return redirect.

If where == register or login, and the current uri is not register or login, stash the current uri in session->{a2c}{openid}{previous_uri}.

is_logged_in

Check the fields in the session hash to make sure they're logged in. Apply the directive timeout to make sure. Don't change anything though. Just return if not logged in, or return 1 if logged in.

logout

Log the user out by clearing the relevant fields in the session hash.

SEE ALSO

Apache2::Controller::Directives

Apache2::Controller

Apache2::Controller::NonResponseRequest

Apache2::URI

Net::OpenID::Consumer

AUTHOR

Mark Hedges, <hedges at scriptdolphin.org>

COPYRIGHT & LICENSE

Copyright 2008 Mark Hedges, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.