Skip to content

Commit

Permalink
Merge pull request #14 from carragom/master
Browse files Browse the repository at this point in the history
Implements new parameter to control response from routing via condition
  • Loading branch information
benvanstaveren committed Oct 28, 2015
2 parents 474f17e + 6627419 commit b33a559
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 18 deletions.
23 changes: 15 additions & 8 deletions README.pod
Expand Up @@ -15,7 +15,7 @@ Mojolicious::Plugin::Authentication - A plugin to make authentication a bit easi
});

if ($self->authenticate('username', 'password', { optional => 'extra data stuff' })) {
...
...
}


Expand Down Expand Up @@ -63,7 +63,9 @@ The following options can be set for the plugin:

=item current_user_fn (optional) Set the name for the current_user() helper function

=back
=item fail_render (optional) The hashref passed to L<Mojolicious::Controller/render> function used when routing L</"ROUTING VIA CONDITION"> fails.

=back

In order to set the session expiry time, use the following in your startup routine:

Expand All @@ -75,7 +77,7 @@ In order to set the session expiry time, use the following in your startup routi

The coderef you pass to the load_user configuration key has the following signature:

sub {
sub {
my ($app, $uid) = @_;
...
return $user;
Expand All @@ -93,7 +95,7 @@ User validation is what happens when we need to authenticate someone. The codere
return $uid;
}

You must return either a user id or undef. The user id can be numerical or a string. Do not return hashrefs, arrayrefs or objects, since the behaviour of this plugin could get a little bit on the odd side of weird if you do that.
You must return either a user id or undef. The user id can be numerical or a string. Do not return hashrefs, arrayrefs or objects, since the behaviour of this plugin could get a little bit on the odd side of weird if you do that.

=head1 EXAMPLES

Expand All @@ -108,14 +110,19 @@ This plugin also exports a routing condition you can use in order to limit acces
my $authenticated_only = $r->route('/members')->over(authenticated => 1)->to('members#index');
$authenticated_only->route('online')->to('members#online');

If someone is not authenticated, these routes will not be considered by the dispatcher and unless you have set up a catch-all route, a 404 Not Found will be generated instead.
If someone is not authenticated, these routes will not be considered by the dispatcher and unless you have set up a catch-all route, a 404 Not Found will be generated instead.

And another condition for fast and unsecured checking for users, having a signature (without validating it). This method just checks client cookies for uid data existing.

$r->route('/foo')->over(signed => 1)->to('mycontroller#foo');

This behavior is similar to the "authenticated" condition.

If you want to control what's sent to the client when the condition fails, you can use the C<fail_render> parameter with a value similar to this:

fail_render => { status => 401, json => { message => 'Unauthorized' } }


=head1 ROUTING VIA CALLBACK

If you want to be able to send people to a login page, you will have to use the following:
Expand Down Expand Up @@ -202,10 +209,10 @@ L<http://search.cpan.org/dist/Mojolicious-Plugin-Authentication/>

=head1 ACKNOWLEDGEMENTS

Andrew Parker
Andrew Parker
- For pointing out some bugs that crept in; a silent reminder not to code while sleepy

Mirko Westermeier (memowe)
Mirko Westermeier (memowe)
- For doing some (much needed) code cleanup

Terrence Brannon (metaperl)
Expand All @@ -223,7 +230,7 @@ Ed W
a bit more sane.

SailingYYC (Github)
- For reporting an issue with routing conditions; I really should not code while sleepy, brainfarts imminent!
- For reporting an issue with routing conditions; I really should not code while sleepy, brainfarts imminent!

carragom (Github)
- For fixing the bug that'd consider an uid of 0 or "0" to be a problem
Expand Down
21 changes: 12 additions & 9 deletions lib/Mojolicious/Plugin/Authentication.pm
Expand Up @@ -24,6 +24,7 @@ sub register {
my $load_user_cb = $args->{load_user};
my $validate_user_cb = $args->{validate_user};
my $current_user_fn = $args->{current_user_fn} || 'current_user';
my $fail_render = $args->{fail_render};

# Unconditionally load the user based on uid in session
my $user_loader_sub = sub {
Expand Down Expand Up @@ -67,7 +68,9 @@ sub register {

$app->routes->add_condition(authenticated => sub {
my ($r, $c, $captures, $required) = @_;
return (!$required || $c->is_user_authenticated) ? 1 : 0;
my $res = (!$required || $c->is_user_authenticated) ? 1 : 0;
$c->render(%$fail_render) if $fail_render && !$res;
return $res;
});

$app->routes->add_condition(signed => sub {
Expand Down Expand Up @@ -158,7 +161,7 @@ Mojolicious::Plugin::Authentication - A plugin to make authentication a bit easi
});
if ($self->authenticate('username', 'password', { optional => 'extra data stuff' })) {
...
...
}
Expand Down Expand Up @@ -206,7 +209,7 @@ The following options can be set for the plugin:
=item current_user_fn (optional) Set the name for the current_user() helper function
=back
=back
In order to set the session expiry time, use the following in your startup routine:
Expand All @@ -218,7 +221,7 @@ In order to set the session expiry time, use the following in your startup routi
The coderef you pass to the load_user configuration key has the following signature:
sub {
sub {
my ($app, $uid) = @_;
...
return $user;
Expand All @@ -236,7 +239,7 @@ User validation is what happens when we need to authenticate someone. The codere
return $uid;
}
You must return either a user id or undef. The user id can be numerical or a string. Do not return hashrefs, arrayrefs or objects, since the behaviour of this plugin could get a little bit on the odd side of weird if you do that.
You must return either a user id or undef. The user id can be numerical or a string. Do not return hashrefs, arrayrefs or objects, since the behaviour of this plugin could get a little bit on the odd side of weird if you do that.
=head1 EXAMPLES
Expand All @@ -251,7 +254,7 @@ This plugin also exports a routing condition you can use in order to limit acces
my $authenticated_only = $r->route('/members')->over(authenticated => 1)->to('members#index');
$authenticated_only->route('online')->to('members#online');
If someone is not authenticated, these routes will not be considered by the dispatcher and unless you have set up a catch-all route, a 404 Not Found will be generated instead.
If someone is not authenticated, these routes will not be considered by the dispatcher and unless you have set up a catch-all route, a 404 Not Found will be generated instead.
And another condition for fast and unsecured checking for users, having a signature (without validating it). This method just checks client cookies for uid data existing.
Expand Down Expand Up @@ -345,10 +348,10 @@ L<http://search.cpan.org/dist/Mojolicious-Plugin-Authentication/>
=head1 ACKNOWLEDGEMENTS
Andrew Parker
Andrew Parker
- For pointing out some bugs that crept in; a silent reminder not to code while sleepy
Mirko Westermeier (memowe)
Mirko Westermeier (memowe)
- For doing some (much needed) code cleanup
Terrence Brannon (metaperl)
Expand All @@ -366,7 +369,7 @@ Ed W
a bit more sane.
SailingYYC (Github)
- For reporting an issue with routing conditions; I really should not code while sleepy, brainfarts imminent!
- For reporting an issue with routing conditions; I really should not code while sleepy, brainfarts imminent!
carragom (Github)
- For fixing the bug that'd consider an uid of 0 or "0" to be a problem
Expand Down
39 changes: 38 additions & 1 deletion t/01-functional.t
Expand Up @@ -6,7 +6,7 @@ use warnings;
BEGIN { $ENV{MOJO_NO_IPV6} = $ENV{MOJO_POLL} = 1 }

use Test::More;
plan tests => 38;
plan tests => 41;

# testing code starts here
use Mojolicious::Lite;
Expand Down Expand Up @@ -95,3 +95,40 @@ $t->get_ok('/authonly')->status_is(200)->content_is('not authenticated');
$t->post_ok('/login2' => form => { u => 'foo', p => 'bar' })->status_is(200)->content_is('ok');
$t->get_ok('/authonly')->status_is(200)->content_is('authenticated');
$t->get_ok('/condition/authonly')->status_is(200)->content_is('authenticated condition');

plugin 'authentication', {
autoload_user => 1,
fail_render => { status => 401, json => { message => 'Unauthorized' } },
load_user => sub {
my $self = shift;
my $uid = shift;

return {
'username' => 'foo',
'password' => 'bar',
'name' => 'Foo'
} if($uid eq 'userid' || $uid eq 'useridwithextradata');
return undef;
},
validate_user => sub {
my $self = shift;
my $username = shift || '';
my $password = shift || '';
my $extradata = shift || {};

return 'useridwithextradata' if($username eq 'foo' && $password eq 'bar' && ( $extradata->{'ohnoes'} || '' ) eq 'itsameme');
return 'userid' if($username eq 'foo' && $password eq 'bar');
return undef;
},
};

get '/condition/authonly' => (authenticated => 1) => sub {
my $self = shift;
$self->render(text => 'authenticated condition');
};

$t = Test::Mojo->new;

$t->get_ok('/condition/authonly')
->status_is(401)
->json_is('/message' => 'Unauthorized');

0 comments on commit b33a559

Please sign in to comment.