Re: [cgiapp] Q: Authz, but only when user is Authenticated...

2008-03-17 Thread Lee Carmichael
Hello Graham,

I just ran into this same problem last week. I was just crafting an email about 
it but found it hard to explain. You did a great job :)

 So, I load up CAP::Authen and CAP::Authz in my App superclass and the prerun 
 hooks get invoked in order (authen first, then authz).  However... if they 
 both fail (user isn't logged in, so I obviously fail authz), CAP::Authz 
 calls prerun_mode() last and overrides the rm that was set by CAP::Authen 
 to trigger the login screen.

This is a problem with any prerun callbacks. The last one run will be the one 
that sets the 'prerun_mode'. 

I did find that one plugin (Dispatch I think) that was being aware and checking 
to make sure that prerun_mode wasn't set yet. I'm not sure this is a great 
choice since it assumes that plugin authors will be aware of this and code 
around it. It just seems wrong to me...

 I've got a few possible ideas for working around this, but wanted to find out 
 what others are doing...
 
 1) Load CAP::Authz first.  That way, even if Authz fails, CAP::Authen would 
 be 
 the last one to call prerun_mode() and the user would get shown the login 
 page.  This works, but feels counter-intuitive; I'm always thinking that I 
 want Authen to run first so I load that plugin first.

I didn't like this one either.

 2) Add a new REQUIRES_AUTHEN option to CAP::Authz, so that if its unable to 
 even figure out what the username is then it doesn't even bother doing an 
 Authz check.

I like this. 

 What are you guys doing when you want similar behaviour?

I needed a really quick solution, so I added the following to my code until a 
better long term solution could be determined:

(prerun_mode could have been $self-auth-username too)

package My::WebApp;

## ..snip...
my @protected_modes = qw( page1 page2 );

sub cgiapp_prerun {
my $self = shift;

if ( !$self-prerun_mode ) {
## validate user authz stuff
$self-authz-authz_runmodes( map { $_ = 'pxdesk' }
@protected_runmodes );

## this is a bit strange but has to due with calling stuff
## I would expect: $self-authz-prerun_callback too...
$self-CGI::Application::Plugin::Authorization::prerun_callback();
}
}

In my case, I need to have some other prerun code still run so I just excluded 
the authz code. 

Overall, I think CA should handle this a bit better, but I'm not sure how since 
that call_hook code is really well separated and has a clean design. It seems 
wrong to 'mess' it up for this one case.

Maybe it would be good to have the callback throw an exception that would tell 
CA to stop processing other callbacks? But I could envision situations where 
the app may want other callbacks to still be called anyway like mine above :) 
Today the callback code will just die if it sees an exception. Maybe 
'prerun_mode' could only be set once inside the prerun callbacks, first one to 
set it gets it. 

Other ideas?

Take Care,

Lee








#  CGI::Application community mailing list  
####
##  To unsubscribe, or change your message delivery options,  ##
##  visit:  http://www.erlbaum.net/mailman/listinfo/cgiapp##
####
##  Web archive:   http://www.erlbaum.net/pipermail/cgiapp/   ##
##  Wiki:  http://cgiapp.erlbaum.net/ ##
####




[cgiapp] Q: Authz, but only when user is Authenticated...

2008-03-05 Thread Graham TerMarsch
With the recent release of CAP::Authz 0.07, I've started going back through my 
existing apps and updating them to use the authz_runmodes() instead of my 
custom Authz plugins which did something similar.

While doing this, however, I've run into a scenario that I thought I'd ask for 
some input on...

In most of the apps I'm working with right now, Authz is only useful if I've 
got an Authenticated user; if the user hasn't logged in then there's no point 
in even checking for Authz as I really want to show them a login page first.  
My custom Authz plugins used to check this for me, but I'm trying to find a 
simpler way to get this working with the new version of CAP::Authz so I can 
pitch my custom code.

So, I load up CAP::Authen and CAP::Authz in my App superclass and the prerun 
hooks get invoked in order (authen first, then authz).  However... if they 
both fail (user isn't logged in, so I obviously fail authz), CAP::Authz 
calls prerun_mode() last and overrides the rm that was set by CAP::Authen 
to trigger the login screen.

I've got a few possible ideas for working around this, but wanted to find out 
what others are doing...

1) Load CAP::Authz first.  That way, even if Authz fails, CAP::Authen would be 
the last one to call prerun_mode() and the user would get shown the login 
page.  This works, but feels counter-intuitive; I'm always thinking that I 
want Authen to run first so I load that plugin first.

2) Add a new REQUIRES_AUTHEN option to CAP::Authz, so that if its unable to 
even figure out what the username is then it doesn't even bother doing an 
Authz check.

What are you guys doing when you want similar behaviour?

--

FWIW, some minimal code to show my setup would go like this...

  class MY::App;
  use base qw(CGI::Application);
  use CGI::Application::Plugin::Authentication;
  use CGI::Application::Plugin::Authorization;
  sub cgiapp_init {
my $self = shift;
$self-authen-config( ... );
$self-authz-config( ... );
  }

  class MY::DerivedApp;
  use base qw(MY::App);
  sub setup {
my $self = shift;
$self-authen-protected_runmodes( ':all' );
$self-authz-authz_runmodes( ':all' = 'admin' );
  }

Gist of the setup is that the superclass sets up the global Authen/Authz 
config and the drivers, while each derived app then sets up the list of 
Authen protected runmodes and the Authz requirements for the modes.

-- 
Graham TerMarsch

#  CGI::Application community mailing list  
####
##  To unsubscribe, or change your message delivery options,  ##
##  visit:  http://www.erlbaum.net/mailman/listinfo/cgiapp##
####
##  Web archive:   http://www.erlbaum.net/pipermail/cgiapp/   ##
##  Wiki:  http://cgiapp.erlbaum.net/ ##
####