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

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