Skip to content

Instantly share code, notes, and snippets.

Created December 16, 2011 14:46
Show Gist options
  • Save anonymous/1486315 to your computer and use it in GitHub Desktop.
Save anonymous/1486315 to your computer and use it in GitHub Desktop.
# auth plugin config
'Plugin::Authentication' => {
default_realm => 'freestock_internal_account',
realms => {
freestock_force_authenticate => {
credential => {
class => 'Password',
password_type => 'none',
},
store => {
class => 'DBIx::Class',
user_model => 'Schema::User',
},
},
freestock_internal_account => {
credential => {
class => 'Password',
password_type => 'self_check',
password_field => 'password'
},
store => {
class => 'DBIx::Class',
user_model => 'Schema::User',
},
},
freestock_facebook_account => {
credential => {
class => 'Facebook::OAuth2',
application_id => '42',
application_secret => '23',
},
store => {
class => 'Null',
},
},
},
};
# helper methods. those could live in MyApp, or a controller role, or whatever
sub authenticate_locally {
my ($ctx, $auth_info) = @_;
my $email = $auth_info->{email};
my $success = $ctx->authenticate({
password => $auth_info->{password},
# or whatever your authentication scheme is. for me it's a
# "local_identity" relation
dbix_class => {
searchargs => [
{ 'local_identity.email' => $email },
{ join => ['local_identity'] },
],
},
}, 'freestock_internal_account');
if ($success) {
$ctx->user->record_successful_login;
return $success;
}
$ctx->model('Schema::User')->record_failed_login($email);
return $success;
}
sub force_authenticate {
my ($ctx, $user) = @_;
# In order to be able to serialise the user to the session, the user is
# required to be persisted already - in-memory rows won't do. Enforce that.
confess 'Attempting to authenticate an unpersisted user'
unless $user->in_storage;
# the following authenticate call is assumed to never fail, so we can record
# the login that's about to happen in advance
$user->record_forced_login;
return $ctx->authenticate({
dbix_class => { result => $user },
}, 'freestock_force_authenticate');
}
sub authenticate_facebook {
my ($ctx, $auth_info) = @_;
my $result = $ctx->authenticate($auth_info, 'freestock_facebook_account');
return $result;
}
# some controller actions to use the above
sub facebook : ... {
if ($ctx->req->params->{error}) {
$ctx->go('/login/set_redirect_to_authenticate');
}
my $facebook_user = try {
$ctx->authenticate_facebook({
scope => [qw(offline_access publish_stream)],
});
}
catch {
$ctx->log->debug($_);
# Failed retrieve access token - mostly likely someone trying to
# spoof. No need to present a pretty error page
$ctx->response->body("GTFO");
return;
};
# Send out the redirect set up by ->authenticate_facebook. Facebook
# will now do its thing and redirect back here. When it does so,
# $facebook_user will end up being set.
$ctx->detach unless $facebook_user;
# get our facebook token to use later on and log the user out again
# from the facebook realm. we want to always have the same sort of
# logged in user instance. the identity used to sign into it should
# not matter for other code.
my $facebook_token = $facebook_user->token;
$ctx->logout;
my $user = $ctx->model('Schema::User')
->find_user_from_facebook_token($facebook_token);
unless ($user) {
## Need to create, first time login
$user = $ctx->model('Schema::User')
->create_user_from_facebook_token($facebook_token);
my $response = $user->facebook_identity->as_fb_graph->add_post
->set_message('Created an Account On Freestock!')
->publish;
$ctx->log->_dump($response->as_hashref);
}
$ctx->force_authenticate($user);
$ctx->go('/login/postlogin_redirect');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment