view release on metacpan or search on metacpan
lib/MojoX/Authentication.pm view on Meta::CPAN
};
sub app_startup ($self, $app = undef) {
$self->_set_app($app) if defined($app);
$app = $self->app;
my $authn = $self->model;
# add Mojolicious::Plugin::Authentication with the "right" callbacks
$app->plugin( Authentication => {
load_user => sub (@args) { $authn->load_user(@args) },
validate_user => sub (@args) { $authn->validate_user(@args) },
});
# set a hook to set the user's data in the stash, associated to the
# requested user_stash_key. This stash key is always set anyway, to
# avoid errors in the templates in case it's missing
my $key = $self->user_stash_key;
$app->hook(
before_render => sub ($c, $args) {
my $user = $c->is_user_authenticated ? $c->current_user : undef;
$c->stash($key => $user);
lib/MojoX/Authentication.pm view on Meta::CPAN
(my $saml_id = $c->signed_cookie('saml-id'))
or ouch 400, 'Not expecting anything SAML-related', 'no id';
defined(my $saml_response = $c->param('SAMLResponse'))
or ouch 400, 'No SAMLResponse';
my $saml2 = $self->_get_provider($c);
my $user = $saml2->parse_assertion($saml_id, $saml_response);
my $uid = $user->{$saml2->user_key};
# we're not using credentials here, so "username" and "password" do
# not make sense. We use "auto_validate" instead and skip
# validate_user altogether
$c->authenticate(undef, undef, { auto_validate => $uid });
$c->log->info("login successful (SAML2): $uid");
$c->flash(message => [ info => "Welcome, $user->{fullname}" ]);
$c->redirect_to($self->_route_for($route_for, 'ok'));
}
catch {
my $message = bleep() || 'Error: invalid credentials';
$message .= ' ' . Dumper($_->data) if eval { $_->isa('Ouch') };
$c->log->error('authentication error (SAML2): ' . $message);
$c->flash(message => [ error => 'Authentication error' ]);
$c->redirect_to($self->_route_for($route_for, 'not_ok'));
lib/MojoX/Authentication/Model.pm view on Meta::CPAN
sub load_user ($self, $app, $uid) {
my ($user, $provider_name) = $self->_iterate(undef, $app, $uid);
return {
provider => $provider_name,
uid => $uid,
data => $user,
};
}
sub validate_user ($self, $ctr, $username, $secret, $extra) {
my ($uid) = $self->_iterate(undef, $ctr, $username, $secret, $extra);
return $uid if defined($uid);
return;
}
1;
lib/MojoX/Authentication/Model.pod view on Meta::CPAN
},
],
);
my $provider = $am->provider_named('local-db');
# mostly used with Mojolicious::Plugin::Authentication
$app->plugin(Authentication => {
...
load_user => sub (@args) { $am->load_user(@args) },
validate_user => sub (@args) { $am->validate_user(@args) },
});
=head1 DESCRIPTION
This module provides a model that acts as an entry point for several
competing <identity providers> of different nature.
As an example, you might want to support holding users in a hash
(possibly configured in a development environment) as well as in a
database or externally in a SAML 2.0 identity provider. This module lets
lib/MojoX/Authentication/Model.pod view on Meta::CPAN
{
class => 'MojoX::Authentication::Model::SAML2',
name => 'external-idp',
args => { ... },
},
],
);
$app->plugin(Authentication => {
...
load_user => sub (@args) { $am->load_user(@args) },
validate_user => sub (@args) { $am->validate_user(@args) },
});
The constructor for this module is fed with three providers.
The first one takes a definition from a reference with hardcoded
values and cleartext passwords, which is of course B<NOT> secure at all.
Anyway, we only use C<$development_users> if the environment variable
C<DEVEL> is true, otherwise it's the empty array to win. This means that
in the development environment we get users C<foo> and C<bar> with their
simple password, while elsewhere we don't get them (at least not from
lib/MojoX/Authentication/Model.pod view on Meta::CPAN
=head3 B<< provider_name_for >>
my $name = $am->provider_name_for($controller, $username);
Retrieve the name of the provider that is capable of handling the user
identified by C<$username>.
=head3 B<< validate_user >>
my $uid = $am->validate_user($controller, $username, $secret, $extra);
Perform validation of credentials for C<$username>.
The interface is compatible with L<Mojolicious::Plugin::Authentication>
like this:
my $am = ...;
$app->plugin(Authentication => {
...
validate_user => sub (@args) { $am->validate_user(@args) },
});
=head1 ANYTHING ELSE (INCLUDING AUTHOR, COPYRIGHT AND LICENSE)
See documentation for L<MojoX::Authentication>.
=cut
lib/MojoX/Authentication/Model/Role/Local.pm view on Meta::CPAN
sub handles_username ($self, $controller, $name) {
return unless defined($name);
return 'yep' if $self->load_user_by_name($controller, $name);
return undef;
}
sub hash_secret ($self, $secret) {
$self->crypt_passphrase->hash_password($secret);
}
sub validate_user ($self, $controller, $name, $secret, $extra) {
return unless defined($name);
my $user = $self->load_user_by_name($controller, $name) or return;
# use Data::Dumper;
# $controller->log->trace("local validate user <$name>, loaded: "
# . Dumper($user));
my $cp = $self->crypt_passphrase;
my $check = $cp->verify_password($secret, $user->{secret});
return $check ? $name : undef; # externally visible id is $name
}
1;
lib/MojoX/Authentication/Model/Role/Local.pod view on Meta::CPAN
Returns a true value if the provider handles the provided username,
false otherwise. Useful to figure out what provider supports a username.
=head2 B<< hash_secret >>
my $hashed = $provider->hash_secret($secret);
Wrapper for C<< $provider->crypt_passphrase->hash_password($secret) >>.
=head2 B<< validate_user >>
my $uid = $provider->validate_user($controller, $name, $secret, $extra);
Validate the user identified by C<$name> against the provided
C<$secret>. Parameter C<$extra> is ignored and only present to support
the right signature.
This method calls method C<load_user_by_name> that must be provided by
the class compositing the role.
=head1 ANYTHING ELSE (INCLUDING AUTHOR, COPYRIGHT AND LICENSE)
lib/MojoX/Authentication/Model/SAML2.pm view on Meta::CPAN
or ouch 400, 'Invalid SAMLResponse';
my $uid = $assertion->nameid;
my $user = $self->_normalize_user(
{ $assertion->attributes->%*, $self->user_key => $uid, });
$self->_cache_user($user);
return $user;
}
# this should never (arguably) be called if "auto_validate" in
# Mojolicious::Plugin::Authentication is used. Anyway...
sub validate_user ($self, $controller, $name, $secret, $extra) {
...;
return defined($self->load_user($name)) ? $name : undef;
}
sub wipe_user ($self, $user) { $self->cache->wipe(__key(user => $user)) }
1;
lib/MojoX/Authentication/Model/SAML2.pod view on Meta::CPAN
=head2 B<< username_validator >>
my $sub = $provider->username_validator;
Accessor for the username validation function. This is wrapped by
L</handles_username> behind the scenes, so it should be set to some
validation mechanism that allows figuring out if the specific SAML2
Identity Provider is the right one for the username.
=head2 B<< validate_user >>
my $uid = $provider->validate_user($ctr, $user, $secret, $extra);
Do the user validation, compatibly with
L<Mojolicious::Plugin::Authentication>.
=head2 B<< wipe_user >>
$provider->wipe_user($user);
Remove the user from the cache.