I've been Googling for quite some time now for some ideas or a guide on how to integrate OAuth (v1.0 & v2.0) alongside the standard Laravel 4 Eloquent authentication driver.
Essentially, I'd like to be able for site visitors to create an account via their existing Google, Facebook, or Twitter accounts, or via the standard email/password authentication. Certain user information such as email, first and last names, and avatar are important for me to have stored in a unified users table.
So far the projects I've looked at seem to support only OAuth and do away with the standard method. These projects include: eloquent-oauth, and oauth-4-laravel.
At this point, I might just roll my own solution, but I'm hoping some of you guys might have better advice for me!
TL;DR: I'm stuck at trying to find a simple and secure way to allow OAuth and standard Eloquent user authentication in Laravel. Halp.
I think the easiest way would be to use this service provider that you mention "artdarek/oauth-4-laravel" and then store the values as usual and log them in.
/**
* Login user with facebook
*
* #return void
*/
public function loginWithFacebook() {
// get data from input
$code = Input::get( 'code' );
// get fb service
$fb = OAuth::consumer( 'Facebook' );
// check if code is valid
// if code is provided get user data and sign in
if ( !empty( $code ) ) {
// This was a callback request from facebook, get the token
$token = $fb->requestAccessToken( $code );
// Send a request with it
$result = json_decode( $fb->request( '/me' ), true );
// store new user or login if user exists
$validator = Validator::make($result, array(
'email'=>'required|email|unique:users'
));
if ($validator->passes()) {
# Save user in DB
$user = new User;
$user->username = $result['name'];
$user->email = $result['email'];
$user->save();
}else {
$user = User::findByUsernameOrFail($result['name']);
}
Auth::login($user);
}
// if not ask for permission first
else {
// get fb authorization
$url = $fb->getAuthorizationUri();
// return to facebook login url
return Redirect::to( (string)$url );
}
}
Related
How can i get user name and surname from facebook authentication. I do login with facebook and i want to do signup. I need Name, Surname and birthday from user. I read about this but cant find concrete information.
my controller is here:
public function oAuthSuccess($client) {
// get user data from client
$userAttributes = $client->getUserAttributes();
$user = User::find()->where(['Email' => $userAttributes['email']])->one();
if (!$user) {
$model = new \frontend\modules\settings\models\ProfileForm();
$model->Name = $userAttributes['name'];
$model->Email = $userAttributes['email'];
if ($model->saveFacebookClient()) {
Yii::$app->user->login($model);
}
return $this->redirect('index.php?r=content/news');
}
Yii::$app->user->login($user);
}
This is the API call:
/me?fields=first_name,last_name,birthday
Of course you need to authorize the user with the user_birthday permission. Information about the login process in general can be found in the docs: https://developers.facebook.com/docs/facebook-login
I suggest using the JavaScript SDK for login, hereĀ“s one tutorial: http://www.devils-heaven.com/facebook-javascript-sdk-login/
If you really want to login with PHP, here are more links:
https://developers.facebook.com/docs/php/howto/example_facebook_login
http://www.devils-heaven.com/facebook-php-sdk-5-tutorial/
I have an issue with my Facebook and Twitter login but only in production (I also have a Google login but it works fine in production). When I run it on localhost I can login without problems. When in production I'm getting a TokenResponseException exception.
I'm using artdarek's oauth-4-laravel but there doesn't seem to be much support in the Issues area.
My code is as follows:.
public function loginWithFacebook() {
// get data from input
$code = Input::get( 'code' );
// $OAuth = new OAuth();
// $OAuth::setHttpClient('CurlClient');
// get fb service
$fb = OAuth::consumer( 'Facebook','http://fisicloud.com/facebook/' );
// check if code is valid
// if code is provided get user data and sign in
if ( !empty( $code ) ) {
// This was a callback request from facebook, get the token
$token = $fb->requestAccessToken( $code );
Below is the error I'm seeing. How can I fix this?
I created an Android App that communicates with an API I set up using PHP and am going to attempt to rewrite the PHP stuff using Laravel. One of the big changes I want to make is to allow OAuth login into my app that is associated with a user account on my local servers and I am confused about the application flow involved to do this.
Should I do my OAuth authentication on my Android app before registering, then store some sort of credential along with user information when I call my API to create my local user account?
Also, when logging a user in using OAuth, how do I know that the person who is authenticated by the provider, say Facebook, Is associated with a local user account on my servers? Is there some sort of token I can store?
Thanks for any overview information you can provide.
I did the same (without OAuth provider from my site) with HybridAuth There is also a composer package at packagist.org.
I have two tables for that:
users with columns id, email, password (table with my normal users and user infos)
authentications with columns: id, user_id, provider, provider_uid (authentication table with the stuff for OAuth.)
The Code I have in my AuthController (for the route /login/social Route::controller('login','AuthController');)
<?php
class AuthController extends BaseController {
//#see http://www.mrcasual.com/on/coding/laravel4-package-management-with-composer/
public function getSocial($action = '')
{
// check URL segment
if ($action == 'auth') {
// process authentication
try {
Hybrid_Endpoint::process();
}
catch (Exception $e) {
// redirect back to http://URL/social/
return Redirect::to('login/social');
}
return;
}
try {
// create a HybridAuth object
$socialAuth = new Hybrid_Auth(app_path() . '/config/hybridauth.php');
// authenticate with provider
if($action != ''){
// only allow facebook and google
if(in_array($action,array('google','facebook'))){
$provider = $socialAuth->authenticate($action);
}else{
// catch this form_error in the login form
return Redirect::to('login')->withErrors(array('form_errors'=>'The url was invalid'));
}
}else{
return Redirect::to('login');
}
// fetch user profile
$userProfile = $provider->getUserProfile();
}
catch(Exception $e) {
// exception codes can be found on HybBridAuth's web site
return Redirect::to('login')->withErrors(array('form_errors'=>'Error on Login: #'.$e->getCode().': '.$e->getMessage()));
}
/*access user profile data
echo "Connected with: <b>{$provider->id}</b><br />";
echo "As: <b>{$userProfile->displayName}</b><br />";
echo "<pre>" . print_r( $userProfile, true ) . "</pre><br />";
die();*/
//check if User exists
if($user_id = DB::table('authentications')->where('provider', $provider->id)->where('provider_uid',$userProfile->identifier)->pluck('user_id')){
//login user
Auth::loginUsingId($user_id);
//update user details (eg photo, name, etc)
//Here you can update the user details
return Redirect::to('dashboard');
}else{
//lets see if we already know this email -> connect it with the registered account
if($user = User::where('email',$userProfile->email)->first()){
$user->authentications()->save(new Authentication(array('provider'=>$provider->id, 'provider_uid'=>$userProfile->identifier)));
Auth::login($user);
//here you can update the user details
return Redirect::to('dashboard')->with('user_social_linked',$provider->id);
}else{
//register user
$user = $this->createUser(array('email'=>$userProfile->email,'password'=>''));
$user->authentications()->save(new Authentication(array('provider'=>$provider->id, 'provider_uid'=>$userProfile->identifier)));
Auth::login($user);
//here you can set/update the user details
return Redirect::to('dashboard')->with('user_created',true);
}
}
}
private function createUser($credentials)
{
$user = new User();
$user->email = $credentials['email'];
$user->password = $credentials['password'];
$user->save();
Auth::login($user);
return $user;
}
}
The User model has also the following function
<?php
public function setPasswordAttribute($password){
//disable blank passwords => disables account login (eg login only with third party aka social providers)
if($password != ''){
$this->attributes['password'] = Hash::make($password);
}else{
$this->attributes['password'] = $password;
}
}
Now you can treat your own OAuth provider just as any other OAuth provider, eg by adding / configuring a hybridauth provider.
To your questions:
Should I do my OAuth authentication on my Android app before registering, then store some sort of credential along with user information when I call my API to create my local user account?
I would handle it the same as with any other OAuth provider: like in the example above one function to call (I only use login via the Laravel Auth, so I do not have the issues with expiring provider sessions and the user does not have to create another account).
Also, when logging a user in using OAuth, how do I know that the person who is authenticated by the provider, say Facebook, Is associated with a local user account on my servers? Is there some sort of token I can store?
This is done by the user_id column in the authentications table.
Hope that helps.
I have twitter username and password. What I want is, when a client adds any new article from the admin side I want its url be auto twit. I dont want to bother client to login to twitter each time he adds an article. Is there any way to auto login using Abraham twitteroauth library. Thankyou
Twitter requires first to Authorize a client app, then you'll able to auto-tweet on certain occasions (i.e. publishing new article). For a detailed depiction you may take a look at this Twitter module for Chyrp that I've created. It uses the Abraham's Twitter oAuth library. There's also a clear example inside the abraham's library archive that may clear this up a bit.
On the other hand, the CMS/Blog you're using for your client's site, should provide hooks (callbacks) in order to know when a post is being created, in order to call the Tweet method accordingly.
Example from the linked Twitter module for Chyrp:
1) Authorize with Twitter:
static function admin_chweet_auth($admin) {
if (!Visitor::current()->group->can("change_settings"))
show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings."));
# If the oauth_token is old redirect
if (isset($_REQUEST['oauth_token']) && $_SESSION['oauth_token'] !== $_REQUEST['oauth_token'])
Flash::warning(__("Old token. Please refresh the page and try again."), "/admin/?action=chweet_settings");
# New TwitteroAuth object with app key/secret and token key/secret from SESSION
$tOAuth = new TwitterOAuth(C_KEY, C_SECRET, $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
$access_token = $tOAuth->getAccessToken($_REQUEST['oauth_verifier']);
# Save access tokens locally for future tweeting.
$config = Config::current();
$config->set("chweet_oauth_token", $access_token["oauth_token"]);
$config->set("chweet_oauth_secret", $access_token["oauth_token_secret"]);
$config->set("chweet_user_id", $access_token["user_id"]);
$config->set("chweet_username", $access_token["screen_name"]);
unset($_SESSION['oauth_token']);
unset($_SESSION['oauth_token_secret']);
if (200 == $tOAuth->http_code)
Flash::notice(__("Chweet was successfully Authorized to Twitter."), "/admin/?action=chweet_settings");
else
Flash::warning(__("Chweet couldn't be authorized."), "/admin/?action=chweet_settings");
}
2) add_post (trigger)
public function add_post($post) {
fallback($chweet, (int) !empty($_POST['chweet']));
SQL::current()->insert("post_attributes",
array("name" => "tweeted",
"value" => $chweet,
"post_id" => $post->id));
if ($chweet and $post->status == "public")
$this->tweet_post($post);
}
3) Tweet-it method (truncated).
public function tweet_post($post) {
$tOAuth = new TwitterOAuth(C_KEY, C_SECRET, $config->chweet_oauth_token, $config->chweet_oauth_secret);
$user = $tOAuth->get("account/verify_credentials");
$response = $tOAuth->post("statuses/update", array("status" => $status));
return $response;
}
Could anybody brief about user_token functionality in Auth module? What is a use and how this incorporates in Auth module?
It is used when a user checks the 'Remember me' box on your site. A token is generated for the user and stored in the user_tokens table.
If you look at the Kohana_Auth_ORM class in the _login function, you can see how it is created:
if ($remember === TRUE)
{
// Create a new autologin token
$token = ORM::factory('user_token');
// Set token data
$token->user_id = $user->id;
$token->expires = time() + $this->config['lifetime'];
$token->save();
// Set the autologin cookie
cookie::set('authautologin', $token->token, $this->config['lifetime']);
}
It is used by the auto_login() function also in the Kohana_Auth_ORM class:
/**
* Logs a user in, based on the authautologin cookie.
*
* #return boolean
*/
public function auto_login()
{
if ($token = cookie::get('authautologin'))
{
// Load the token and user
$token = ORM::factory('user_token', array('token' => $token));
if ($token->loaded() AND $token->user->loaded())
{
if ($token->user_agent === sha1(Request::$user_agent))
{
// Save the token to create a new unique token
$token->save();
// Set the new token
cookie::set('authautologin', $token->token, $token->expires - time());
// Complete the login with the found data
$this->complete_login($token->user);
// Automatic login was successful
return TRUE;
}
// Token is invalid
$token->delete();
}
}
return FALSE;
}
It is up to you to correctly use this capability within your authorization controller. I'm relatively new to Kohana, but I perform a simple check to redirect a user if they go to the login form and are already logged in or can automatically login:
if (Auth::instance()->logged_in() || Auth::instance()->auto_login())
Request::instance()->redirect('auth/');
The code for the Auth module isn't too difficult to understand. If you're new to Kohana, it's a good starting point to see how the ORM module works.