Mojolicious::Plugin::SimpleAuthorization - Simple role-based authorization
# Mojolicious example package SimpleApp; use Mojo::Base 'Mojolicious'; sub startup { my $self = shift; $self->plugin( 'SimpleAuthorization' => { 'on_assert_failure' => sub { # assert failure hook my ($self, $tests) = @_; $self->render(text => 'Permission denied.'); }, } ); # Add route not requiring authentication/authorization my $r = $self->routes; $r->get('/')->to(cb => sub { shift->render(text => "I am public. Hi.") }); # Add authentication under (which populates stash with the user/roles) # # In your under, set the user and user's roles C<HASHREF> every request. # The user can contain any arbitrary data. Roles should contain key/value # pairs, where allocated roles evaluate to true. my $auth = $r->under->to( cb => sub { my $self = shift; #if ($user_is_authenticated) { $self->stash(roles => {'user.delete' => 0, 'user.search' => 1}); $self->stash(user => {username => 'paul', administrator => 0}); #} } ); # Search user controller - success! $auth->get('/user/search')->to( cb => sub { my $self = shift; return unless $self->assert_user_roles([qw/user.search/]); $self->render(text => "Success! Let's do some searching!"); } ); # Delete user controller - oh noes! (Will execute C<on_assert_failure>.) $auth->get('/user/delete')->to( cb => sub { my $self = shift; return unless $self->assert_user_roles([qw/user.delete/]); $self->render(text => "Damn! Not authorized so won't see this!"); } ); } 1;
Mojolicious::Plugin::SimpleAuthorization is a simple role-based authorization plugin for Mojolicious.
It attempts to keep a sane control flow by not croaking or dying if the user does not have the relevant roles/permissions. As such, check_user_roles or assert_user_roles should be called at the beginning of your controllers.
check_user_roles
assert_user_roles
Mojolicious::Plugin::SimpleAuthorization does offer the hook on_assert_failure if you want to render a permission denied response or similar for every request that isn't authorized. (Or if you would prefer to croak/die.)
on_assert_failure
Mojolicious::Plugin::SimpleAuthorization supports the following options.
# Mojolicious::Lite plugin SimpleAuthorization => { on_assert_failure => sub { my ($self, $tests) = @_; $self->render( text => 'You don't have permission to access this resource.'); } };
If assert_user_roles fails to authorize, this code ref is called.
# Mojolicious::Lite plugin SimpleAuthorization => {roles => 'auth_roles'}; # In your under or controller $self->stash(auth_roles => {'user.delete' => 1, 'user.search' => 1});
Name of stash value which holds all the roles for the current user. Must be a HASHREF. Defaults to roles.
HASHREF
roles
# Mojolicious::Lite plugin SimpleAuthorization => {superuser => 'administrator'}; plugin SimpleAuthorization => { 'superuser' => sub { my ($user, $roles) = @_; return 1 if $user->{administrator}; } }; $self->check_user_roles([qw/some_random_role/]); # returns 1 $self->check_user_roles([qw/crazy_role/]); # returns 1
Adds the possibility of a superuser - a user that can assume every role.
The above two examples are the same. If the administrator key exists in the user hash and it evaluates to true, the user will pass every role check. The superuser CODE example performs an equivalent evaluation.
administrator
user
superuser
# Mojolicious::Lite plugin SimpleAuthorization => {user => 'auth_user'}; # In your under or controller $self->stash(auth_user => {username => 'paul.williams', administrator => 0});
Name of stash value which holds the user's information. Must be a HASHREF. Defaults to user.
Mojolicious::Plugin::SimpleAuthorization inherits all methods from Mojolicious::Plugin and implements the following new ones.
Same as check_user_roles, except it calls the hook on_assert_failure if the user isn't authorized. Returns a boolean value.
my $assert = $self->check_user_roles('user.create'); my $assert = $self->check_user_roles([qw/user.editor user.create/]);
Checks the user and returns a boolean value.
my $user_to_delete = 'admin'; my $assert = $self->check_user_roles( ['user.delete'], sub { my ($user, $roles) = @_; return 0 if $user_to_delete eq 'admin'; } );
Optionally pass a callback to apply your own one-off role check. Useful as in the example above, where the user 'admin' cannot be deleted.
If the callback returns a positive value, the user is authorized. 0 and the user is not authorized, undef and the authorization chain continues.
my $message = get_message_to_delete(); my $assert = $self->check_user_roles( ['message.delete'], sub { my ($user, $roles) = @_; $roles->{'message.delete'}++ if $message->{username} eq $user->{username}; return undef; } );
This technique can also be used to give the user a role based on certain criteria. In the example above, a user who cannot delete all messages, can delete their own message.
$plugin->register(Mojolicious->new);
Register plugin in Mojolicious application.
Contributions welcome, though this plugin is pretty basic. I currently only accept GitHub pull requests.
GitHub: https://github.com/kwakwaversal/mojolicious-plugin-simpleauthorization
Copyright (C) 2014-2015, Paul Williams.
This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.
Paul Williams <kwakwa@cpan.org>
Mojolicious, Mojolicious::Plugin::Authorization.
To install Mojolicious::Plugin::SimpleAuthorization, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Mojolicious::Plugin::SimpleAuthorization
CPAN shell
perl -MCPAN -e shell install Mojolicious::Plugin::SimpleAuthorization
For more information on module installation, please visit the detailed CPAN module installation guide.