http://www.perlmonks.org?node_id=498733


in reply to User authorization and design of larger web/intranet applications.

On the conceptual side, look into role based authorization, and make sure authorization and authentication are not too tightly connected. This is an easy distinction to make, and will keep things more more flexible in the future.

Here's how role based authz works: each user is a member of any number of groups, each representing a role that the user can take part in (administrator, regular user, moose hugger), and each page or area in the app simply has guards before each action (the way you manage that is dependent on your web app framework - i don't know CGI::Application) which require a certain role. (under more complicated schemes groups could contain or inherit from each other).

The session info contains the ID of the logged in user, and the check for roles should be dynamic (so that the session doesn't have to be fried if the user's role changes).

The code that actually requires authentication should say something like

$authorization_obj->assert_role($user_id, "role_name"); # note that th +is object knows nothing about usernames/passwords - it assumes the us +er is a known user
and then an exception should be thrown, going to an error handler instead of the normal code.

An error handler around the actions should check to see if there is a login error, and redirect the user to the login page.

If you want finer granularity, you can add exception handlers with higher locality to your application areas, but try very hard to keep things simple - if too much complexity finds it's way into the authentication system people will be sad.

After you've made sure parts are locked out to users who shouldn't be touching them, you can start hiding irrelevant parts from the user in order to keep the interface cleaner. For this you should have a check_role method in addition to an assert_role method that doesn't throw exceptions, but just returns a true/false value.

On the authentication side - your login handler should just check credentials and mark the logged in ID in the session. But this should have no implication whatsoever on what the user can do!

In your code you are on the right track on making sure authorization happens all the time, but return $self->session->param('logged-in'); is just not an abstract enough check. In addition, throwing an exception will assure that the code after the exception will not occur, up to the caller's closest eval boundry - this is an easy way to be sure you're not accidentally running code that shouldn't be run.

-nuffin
zz zZ Z Z #!perl