Dancer-Plugin-Auth-Extensible
view release on metacpan or search on metacpan
lib/Dancer/Plugin/Auth/Extensible.pm view on Meta::CPAN
# succeeded and the response.
# Note: all provider class methods return a single value; if any need to return
# a list in future, this will need changing)
sub _try_realms {
my ($method, @args);
for my $realm (keys %{ $settings->{realms} }) {
my $provider = auth_provider($realm);
if (!$provider->can($method)) {
die "Provider $provider does not provide a $method method!";
}
if (defined(my $result = $provider->$method(@args))) {
return $result;
}
}
return;
}
# Set up routes to serve default pages, if desired
if ( !$settings->{no_default_pages} ) {
get $loginpage => sub {
if(logged_in_user()) {
redirect params->{return_url} || $userhomepage;
}
status 401;
my $_default_login_page =
$settings->{login_page_handler} || '_default_login_page';
no strict 'refs';
return &{$_default_login_page}();
};
get $deniedpage => sub {
status 403;
my $_default_permission_denied_page =
$settings->{permission_denied_page_handler}
|| '_default_permission_denied_page';
no strict 'refs';
return &{$_default_permission_denied_page}();
};
}
# If no_login_handler is set, let the user do the login/logout herself
if (!$settings->{no_login_handler}) {
# Handle logging in...
post $loginpage => sub {
# For security, ensure the username and password are straight scalars; if
# the app is using a serializer and we were sent a blob of JSON, they could
# have come from that JSON, and thus could be hashrefs (JSON SQL injection)
# - for database providers, feeding a carefully crafted hashref to the SQL
# builder could result in different SQL to what we'd expect.
# For instance, if we pass password => params->{password} to an SQL builder,
# we'd expect the query to include e.g. "WHERE password = '...'" (likely
# with paremeterisation) - but if params->{password} was something
# different, e.g. { 'like' => '%' }, we might end up with some SQL like
# WHERE password LIKE '%' instead - which would not be a Good Thing.
my ($username, $password) = @{ params() }{qw(username password)};
for ($username, $password) {
if (ref $_) {
# TODO: handle more cleanly
die "Attempt to pass a reference as username/password blocked";
}
}
if(logged_in_user()) {
redirect params->{return_url} || $userhomepage;
}
my ($success, $realm) = authenticate_user(
$username, $password
);
if ($success) {
session logged_in_user => $username;
session logged_in_user_realm => $realm;
redirect params->{return_url} || $userhomepage;
} else {
vars->{login_failed}++;
forward $loginpage, { login_failed => 1 }, { method => 'GET' };
}
};
# ... and logging out.
any ['get','post'] => $logoutpage => sub {
session->destroy;
if (params->{return_url}) {
redirect params->{return_url};
} elsif ($exitpage) {
redirect $exitpage;
} else {
# TODO: perhaps make this more configurable, perhaps by attempting to
# render a template first.
return "OK, logged out successfully.";
}
};
}
sub _default_permission_denied_page {
return <<PAGE
<h1>Permission Denied</h1>
<p>
Sorry, you're not allowed to access that page.
</p>
PAGE
}
sub _default_login_page {
my $login_fail_message = vars->{login_failed}
? "<p>LOGIN FAILED</p>"
: "";
my $return_url = params->{return_url} || '';
return <<PAGE;
<h1>Login Required</h1>
<p>
You need to log in to continue.
</p>
$login_fail_message
( run in 2.007 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )