Skip to content

Instantly share code, notes, and snippets.

@adamtaylor
Created August 17, 2015 22:15
Show Gist options
  • Save adamtaylor/9143f40ccd188c7920e3 to your computer and use it in GitHub Desktop.
Save adamtaylor/9143f40ccd188c7920e3 to your computer and use it in GitHub Desktop.
Catalyst OAuth Configuration
package MyApp;
...
__PACKAGE__->config(
# Catalyst::Plugin::Authentication configuration
'Plugin::Authentication' => {
# If $c->authenticate() is called in the app without a
# realm argument, Strava will be checked.
default_realm => 'strava',
# `strava` realm confiuration
strava => {
# If the user can't be found, create them
auto_create_user => 1,
# Update the user everytime they log in
auto_update_user => 1,
# Enable Catalyst::Authentication::Realm::Adaptor
class => 'Adaptor',
credential => {
# Use Catalyst::Authentication::Credential::Strava
class => 'Strava',
# Provided by Strava
client_id => $client_id,
client_secret => $client_secret,
},
store => {
class => 'DBIx::Class',
user_model => 'Schema::User',
# These fields are all returned by our Adaptor customisation
# but we don't want to use them when we look up the user, we
# want to pass them in when we create or update the user.
ignore_fields_in_find => ['strava_access_token','picture','first_name','last_name','city','coutry'],
},
# Catalyst::Authentication::Realm::Adaptor configuration.
# We're hooking into the authentication code just before it looks
# for the user in our user store.
store_adaptor => {
# There are various methods you can use but we want quite a bit
# of customisation so opt for a code block.
method => 'code',
code => sub {
my ($realmname, $original_authinfo, $hashref_to_config) = @_;
# Here we setup a client to talk to the Strava API
# and make another call to retrieve all the user data.
#
# The default behaviour of the Strava authorisation realm
# (and most other OAuth realms) is to return the authorisation
# token only.
use LWP::Authen::OAuth2;
use JSON::XS;
my $strava = LWP::Authen::OAuth2->new(
service_provider => 'Strava',
client_id => $client_id,
client_secret => $client_secret,
token_string => encode_json {
access_token => $original_authinfo->{strava_access_token},
_class => 'LWP::Authen::OAuth2::AccessToken::Bearer',
},
);
my $athlete = decode_json $strava->get('https://www.strava.com/api/v3/athlete')->content;
# Here we construct a new data structure that will be passed
# to the authentication methods to find and create or update
# the user.
#
# Note that with our `ignore_fields_in_find` block above, we're
# ignoring everything but the email when looking up the user. The
# rest of the fields are used when creating or updating the user.
return {
email => $athlete->{email},
strava_access_token => $original_authinfo->{strava_access_token},
picture => $athlete->{profile_medium},
first_name => $athlete->{firstname},
last_name => $athlete->{lastname},
city => $athlete->{city},
country => $athlete->{country},
};
},
}
},
# `facebook` realm confiuration
facebook => {
# If the user can't be found, create them
auto_create_user => 1,
# Update the user everytime they log in
auto_update_user => 1,
# Enable Catalyst::Authentication::Realm::Adaptor
class => 'Adaptor',
credential => {
# Use Catalyst::Authentication::Credential::Facebook::OAuth2
class => 'Facebook::OAuth2',
# These are provided by Facebook
application_id => $application_id,
application_secret => $application_secret,
},
store => {
class => 'DBIx::Class',
user_model => 'Schema::User',
# Like the Strava configuration above, we want to ignore some
# of the fields in the user look up and only use them for
# creating and updating users.
ignore_fields_in_find => ['facebook_access_token','country','city','first_name','last_name'],
},
# Catalyst::Authentication::Realm::Adaptor configuration.
store_adaptor => {
method => 'code',
# This is very similar to our customisation for Strava.
# We build a Facebook client and make another request to
# the Facebook Graph API to return more information about
# the authorised user to save in our database.
code => sub {
my ($realmname, $original_authinfo, $hashref_to_config) = @_;
use Facebook::Graph;
my $fb = Facebook::Graph->new(
app_id => $application_id,
secret => $application_secret,
);
$fb->access_token( $original_authinfo->{token} );
my $user = $fb->fetch('me');
my $auth_info = {
email => $user->{email},
# Using these customisations also allows us to rename
# the key used to lookup the user in the storage.
facebook_access_token => $original_authinfo->{token},
first_name => $user->{first_name},
last_name => $user->{last_name},
};
return $auth_info;
},
},
},
},
);
@zsan
Copy link

zsan commented Dec 11, 2019

Hi,

Did you ever try to integrate google oauth2 ?

@adamtaylor
Copy link
Author

@zsan I did not try it but the principle should be similar.

@adamtaylor
Copy link
Author

@zsan not sure if this helps but I wrote a bit more about this here http://ajct.info/2015/08/16/oauth-and-catalyst.html

@zsan
Copy link

zsan commented Dec 11, 2019

Yes, should be similiar, i am trying since yesterday :=), still cant get it work, i can get the access token, i am bit confused with Realm and Adaptor thing

@zsan
Copy link

zsan commented Dec 11, 2019

Yes i've read about your article

@zsan
Copy link

zsan commented Dec 12, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment