neptuneray has asked for the wisdom of the Perl Monks concerning the following question:

I just recently started using CGI:App and so far, really like what I see. It is well documented, and handles most of the low-level CGI stuff that has made web programming so tedious for me (without having to learn Moose!). Most of my web app is working (I use Template Toolkit for the forms), and today I decided to add User Authentication to protect some of the runmodes. That's when the trouble began ...

I don't have any fancy needs regarding Authent. Just a simple user=>password hash will work fine. So I loaded the Generic driver. I wrote my own HTML form for the login, and call it from a "login_user()" runmode. But I can't figure out HOW to actually DO the Authentication. I try calling "verify_credentials()", but it can't find it.

I know this must be very simple and basic, but I have combed through the docs and can't find a simple explanation.

Here is my config:

package ePlan::AppBase; use strict; use warnings; use base qw(CGI::Application); use CGI::Application::Plugin::ConfigAuto (qw/cfg cfg_file/); use CGI::Application::Plugin::DBIC::Schema (qw/dbic_config schema resu +ltset rs/); use CGI::Application::Plugin::Session; use CGI::Application::Plugin::Authentication; use CGI::Application::Plugin::Authentication::Driver::Generic; my %users = ( ray => '123', jeff => '456', ); __PACKAGE__->authen->config( DRIVER => [ 'Generic', \%users ], STORE => 'Session', POST_LOGIN_URL => 'http://cgiapp.site/dash.pl', LOGIN_RUNMODE => 'login_user', LOGOUT_RUNMODE => 'logout_user', CREDENTIALS => ['authen_username','authen_password'], ); sub setup { my $self = shift; $self->start_mode('owner'); $self->run_modes('owner' => 'lookup_owner', 'user' => 'login_user', ); } sub login_user { ...... my $q = $self->query(); my $user = $q->param('authen_username'); my $pswd = $q->param('authen_password'); (now, what??) my @crednames=@{$self->authen->credentials}; # this fails --> my $go_nogo = $authen->verify_credentials();

Anyway, now whenever I get to an "authen->protected_runmode", it doesn't know I've been Authenticated, and pops up the form.

Thanks!

Replies are listed 'Best First'.
Re: cgi::application authentication
by leocharre (Priest) on Sep 20, 2009 at 00:49 UTC

    You set the authentication by stating what runmodes are protected, that is, require login, this is one way to do it, works great for me.

    You do it in setup(), or you could do it in a callback- deal with that later.

    Check this.. about protected runmodes

    You must keep in mind that the examples on that doc, are setting the authen protected runmodes class wide, instead of instance wide. Personally I preffer to do it in the setup() phase or in a callback. Here is a convoluted example..

    sub setup { my $self = shift; $self->start_mode('home'); $self->mode_param('rm'); $self->my_authen_config; } # 2 sub my_authen_config { my $self = shift; $self->authen->config( DRIVER => [ 'Generic', sub { $self->my_verify_credentials(@_) }, + ], LOGIN_SESSION_TIMEOUT => $LOGIN_SESSION_TIMEOUT, CREDENTIALS => ['authen_username', 'authen_password' ], STORE => 'Session', LOGIN_RUNMODE => 'login', ); $self->authen->protected_runmodes(qr/^(?!_?log)/); $self->authen; } sub my_verify_credentials { my $self = shift; my ($username,$password)= @_; ($username and $password ) or $self->feedback("Missing username or password.") and return; $self->my_method_for_password_test( $username, $password) or $self->feedback("Wrong username or password.") and return; return $username; }

    (keep in mind this code is not fully functional by itself)

      Okay, thanks .... maybe I'm reading more into this than I should be.

      The doc you pointed me to on protected runmodes says "they will be redirected to a login page unless they are properly logged in".

      I've been getting redirected to my login page allright, ... I'm just trying to tell the darn subsystem, "Yes, I'm already logged in!"

      I think by your example of "my_verify_credentials()" you are telling me that the "secret" of the DRIVER config parameter is that the second argument must return a valid Username (by whatever my definition of that is). If it returns Undef, I am telling the subsystem that the login attempt failed. Am I correct? Or am I still missing the "big picture" here?

        I should point out that the argument to authen->protected_runmodes() in this example is a regex, but it could be.. a list of the names of the runmodes that should be protected.

        What this plugin does is.. In setup, you define that for example 'home' is the starting point. You set up that 'home' is also a protected runmode, so when a request comes in, they are automatically redirected to runmode login (that you can choose not to code, there's one put in there for you by the beautiful Authentication plugin).

        The answer to your question is in the docs, I know they are tedious to read, print it out and look it over, it may help (that's what I do from time to time). There are examples of using Authen I believe on cpan also.

        Don't give up on using this module if you are having troubles, it took me a little bit to figure out too, and it's been a real time saver.

        Thanks again. I think I've got it now.

        My problem was that I thought that somewhere in my mainline code I had to call a "verify_credentials()" sub in order to tell the authent subsystem that "All is okay".

        Now I realize that I don't. As long as I successfully return from the second argument of the DRIVER config parameter, it will remember (in the Session) that this User is logged in, and will stop calling the login_user() runmode before it allows access to a "protected" runmode.

        I knew this had to be straightforward ... I guess I was just expecting that I had to write a bunch of code. Actually, since I'm using Generic with a simple "user=>password" hash, I don't have to write anything!

        All of the cgi::app contributors have done a really great job with this system. There is a LOT of good quality stuff here that will save the web application writer a ton of headaches!

Re: cgi::application authentication
by scorpio17 (Canon) on Sep 20, 2009 at 15:23 UTC
    Some time ago I started a tutorial on how to use CGI::Application to create a simple login page. It never made it past the "request for comments" stage, but you can still find it here.
      Good job, Scorpio. I wish that I had read your doc first! Would've saved me a nice Sunday afternoon ...

      Anyway, today I am beginning to integrate HTML::FormFu into my CGI::App. I am currently using the Template Toolkit, but I have hand-coded all the templates, store them in one big subdirectory, and have a lot of logic to tell which one to call.

      I would prefer to streamline this and "objectify" it. I looked at Mark's Data::FormValidator, but it seemed to me that FormFu did more of what I wanted (comments, anyone?).

      The only problem I see now is an absence of any examples in FormFu about a good CGI::App integration policy (or plugin), but instead, lots of references to Catalyst integration. I am just a little leery of the learning curve to approach Catalyst. I found CGI::App to be simple to grok, as long as you know "regular" Perl (not Moose-extended Perl) and how CGI works.