I have a react application and currently the user authentication done with Wordpress. So I'm using JWT_AUTH! plugin to manage user login functionality.
So now the requirement has changed and the users should be able to login to both React and the Wordpress websites with one single login attempt. This means if the user login to the React application, he should automatically log in to his Wordpress application as well. Also if the user login on Wordpress application he should automatically log into his react application as well.
I have created a custom REST API endpoint to do this requirement. But it's not working as expected. This endpoint is working when I using this API link with a browser. That because it doesn't have the ability to store cookies with the REST API call.
I also tried to generate auth cookies with the rest API call but it gave me the "500" error.
add_action( 'rest_api_init', function () {
register_rest_route( 'user/v1', '/api-login-check', array(
'methods' => WP_REST_Server::READABLE,
'callback' => 'rest_api_login_user',
'schema' => array(
'type' => 'array'
)
));
});
function rest_api_login_user($object, $request = null) {
$response = array();
$parameters = $request->get_json_params();
$creds = array();
$creds['user_login'] = $object['username'];
$creds['user_password'] = $object['password'];
$creds['remember'] = true;
$user = wp_signon( $creds, false );
if ($user) {
$response['code'] = 200;
$response['message'] = __("User logged in", "wp-rest-user");
return new WP_REST_Response($response, 123);
}else{
$response['code'] = 403;
$response['message'] = __("User not logged in", "wp-rest-user");
}
}
Is there any easy way to do this? Also if there a way to redirect user to different url from a rest api call, that also fine.
Related
I created an web app which it uses laravel default registration(auth), I've tested passport oauth2 client access token from taylor tutorial. My web app uses angular js for UI and laravel for backend , so I need to create user, when create user request is sent from angular and then create a global access token to give it in my response to angular which then in all later request I use it to authenticate requests.
actually I want to implement oauth2 authentication for my web app, but so far I've searched a lot but I couldn't find any useful step by step tutorial for it.
anyone can help me out?
FYI: I'm using laravel 5.3 with passport enabled and angular js 1.5 for frontend.
Use JWT token based authentication here you can learn about jwt https://jwt.io/
I've solved this.
I've Customized laravel auth for login and register and created a method which will send a request to the server to create an access token for registering user or log in.
I've set up passport and test it as taylor did in his toturial.
then in AuthenticatesUsers.php I've changed sendloginResponse method response like :
protected function sendLoginResponse(Request $request)
{
isset($request->token) ? $token = $request->token : $token = null;//Check if login request contain token
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
? $this->StatusCode($token,$this->credentials($request),$status=false) : $this->StatusCode($token,$this->credentials($request),$status=true);
}
And I have added this method to request access token and send it as json response :
public function StatusCode($token,$user,$status){
if( $token != null && $token != ''){
return ($status == true) ? response()->json(GetToken($user),200) : response()->json(['Message' => 'Failed to log in'],403);
}
function GetToken($userobject)
{
$http = new Client;
$response = $http->post('http://localhost/iranAd/public/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => '1',
'client_secret' => 'xKqNbzcXyjySg20nVuVLw5nk5PAMhFQOQwRTeTjd',
'username' => $userobject['email'],
'password' => $userobject['password'],
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
function RefreshToken($token,$userobject)
{
$http = new Client;
$response = $http->post('http://localhost/iranAd/public/oauth/token', [
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => 'refresh_token',
'client_id' => '1',
'client_secret' => 'xKqNbzcXyjySg20nVuVLw5nk5PAMhFQOQwRTeTjd',
'username' => $userobject['email'],
'password' => $userobject['password'],
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
return ($status == true) ? response()->json(GetToken($user),200) : response()->json(['Message' => 'Failed to log in'],403);
}
Same Procedure for register users.
The purpose of this post is not to answer(as already answered) but to give more info to other readers who eventually need more info on topic.
This is very helpfull tutorial just on this issue Implementing Vue.js 2.0 and Laravel 5.3 with CORS problem solution
Check this one and 2 next clips.
Some of this you can find in shorter form here here
I am using CodeIgniter controller functions.
(example)
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Me extends CI_Controller {
public function __construct()
{
parent::__construct();
if (is_logged_in()){if (is_admin()) { redirect('login'); }}
else { redirect('login');}
}
public function change_password()
{
$id=$this->session->userdata['user_data']['id'];
$data = json_decode(file_get_contents("php://input"));
$my_data=array(
'pass'=>$data->pass,
'new_pass'=>$data->new_pass,
);
$result=$this->vanesh_model->change_pass($id,$my_data);
if($result==1)
{
$arr = array('msg' => "Password changed successfuly.", 'error' => '');
$jsn = json_encode($arr);
print_r($jsn);
}
else if($result==2)
{
$arr = array('msg' => "", 'error' => 'Old Password is Invalid');
$jsn = json_encode($arr);
print_r($jsn);
}
else if($result==3)
{
$arr = array('msg' => "", 'error' => 'Sorry, Password change failed');
$jsn = json_encode($arr);
print_r($jsn);
}
}
}
?>
I am afraid of using angular session services, so I want to maintain sessions with only CI. What I am doing in my application is add, update, delete only if he is logged in. And I am using information stored in session. Consider the situation, suppose, I am logged in and doing something, side by side: I destroy the session using browser tools. Now I am continuing with application (doing operations like: change password). I have/had maintained error messages, success messages, its ok. If session OFF, it gives error message. But instead of error messages, I want to redirect to LOGIN page(with page refresh).
Note: For CI Login controller, I didn't used angular js. I have used angularjs only after login.
If by opening new tab I destroy the session, and come back to application's tab: I am able to perform tasks(may be with errors,). If session is OFF I see this in Browser's console: http://localhost/ums/login
This is because of CI constructor(please look over the code).
You should separate angular and CI as much as possible, since both have view-controller it creates a mess. Instead you should have CI in a separate folder, call it api, for example, after that anything you will need from CI should be acessed from angular with ajax calls.
I made a small webapp a while ago and this seemed to be the best way to organize code.
Few updates have been made to angular since then so if there's a better way please let me know
Solved.
Used javascript function. Checking session by http request everytime. If response comes "1". Means redirect to login as:
/* function for checking logged-in and role */
function check_session()
{
$.get("servercontroller/check_session", function(data, status){
if(data=="1") /* error 1 => un-athorized user */
{
window.location.href="/login-page-url";
}
});
}
How do I get the page that was denied access by the Auth component using CakePHP 2.x? If I use the referer() function, it gives me the page that linked to the denied action. Here's my code:
public function login() {
//get the current url of the login page (or current controller+action)
$currentLoginUrl = "/login";
if ($this->request->is('post')) {
$this->User->recursive = -1;
$user = $this->User->find(
'first',
array(
'conditions' => array(
'User.username' => $this->request->data['User']['username'],
'User.password' => AuthComponent::password($this->request->data['User']['password'])
)
)
);
if ($user && $this->Auth->login($user['User'])) {
//if the referer page is not from login page,
if( $this->referer() != $currentLoginUrl )
//use $this->referer() right away
$this->redirect($this->referer('/admin', true)); //if referer can't be read, or if its not from local server, use $this->Auth->rediret() instead
else
//if the user lands on login page first, rely on our session
$this->redirect( $this->Session->read('beforeLogin_referer') );
}
else
$this->Session->setFlash('Username or password is incorrect', 'default', array('class' => 'alert-danger'));
}
if( $this->referer() != $currentLoginUrl )
//store this value to use once user is succussfully logged in
$this->Session->write('beforeLogin_referer', $this->referer('/admin', true) ) ; //if referer can't be read, or if its not from local server, use $this->Auth->rediret() instead
}
So basically what happens is I'm not logged in, and I'm at this url:
'http://localhost/hotelguide/hotels/view/17/'
and I click on a link that would take me to
'http://localhost/hotelguide/hotels/review/17/'
but that requires a user to be logged in, so it redirects me to the login page, which, when I debug referrer(), it gives me this:
'http://localhost/hotelguide/hotels/view/17/'
What am I doing wrong?
When you use Auth component in CakePHP and try to access a restricted site, it redirects you to login page and saves the referring page in session. Session key Auth.redirect holds the value you're looking for - the page that you were trying to access.
Look at the __unauthenticated() method of AuthComponent. It includes the code responsible for writing session value to Auth.redirect. If you don't want to use AuthComponent, you can check how it is implemented in the component and write your own solution based on the method I have mentioned.
$this->referer() will not provide you the correct referrer url for you. If you want to get referrer url just use $this->Session->read('Auth.redirect');
You can find exact url you are looking for by $this->Session->read('Auth.redirect');
$this->referer() value update every time when you reload the page.
I am using webtechnick facebook plugin, i have everything set and its FB login works perfectly.
I am using $fbc =$this->Connect->User(); to fetch FB details of logged in user
And using
<?php
echo $facebook->login(array('perms' => 'email,publish_stream','size'=>'small'));
?>
<?php
echo $this->Facebook->logout();
?>
for login,logout respectively. i am getting details of user after login, but it will not unset after performing a logout();
I am using webtechnick fb plugin version 3.1.1 . Please help me
My help isn't much help because I haven't really found a solution. The good news is that you are not alone:
https://github.com/webtechnick/CakePHP-Facebook-Plugin/issues/43
What I can tell you is that the facebook cookie (fbsr_{facebook_app_id}) is either not deleting or is being recreated and that is the root of the problem.
EDIT
I may have found out what's going on here. Until the other night I had not bothered to setup my .htaccess files and both http:/www.example.com and http:/example.com were valid.
In my facebook app, I had set up example.com as a domain and pointed the site URL to www.example.com.
With the fbsr_{app id} cookie, I noticed that it was sometimes on the http://example.com while my cakephp cookies were on www.
I played around with changing the URL in my facebook app (adding www, removing www) and then also started doing the rewrite rules in .htaccess to add or remove www. I just removed the appdomain entirely from my facebook app, forced www. to the domain, and now everything is kosher.
So I think the trick is to
Not have the app domain in the facebook app
Fix canonicalization of www via .htaccess
This ensures that both the cakephp and the facebook cookies are being saved to the identical domain, and when you logout they are removed from said domain.
Hope this makes sense...
I know it is too late for some suggestion for this post. Still feel it might help some one who later reading this post.
I too was facing the logout issue with the plugin , I have modified a function in ConnectComponent in the plugin to clear its session details if the action is "logout". Below is the modified function :
private function __syncFacebookUser(){
if($this->Controller->params['action'] == 'logout')
{
$this->Controller->Session->delete('FB');
$this->uid = null;
$this->Controller->Session->delete('Auth.User');
}
else
{
if(!isset($this->Controller->Auth)){
return false;
}
$Auth = $this->Controller->Auth;
if (!$this->__initUserModel()) {
return false;
}
// if you don't have a facebook_id field in your user table, throw an error
if(!$this->User->hasField('facebook_id')){
$this->__error("Facebook.Connect handleFacebookUser Error. facebook_id not found in {$Auth->userModel} table.");
return false;
}
// check if the user already has an account
// User is logged in but doesn't have a
if($Auth->user('id')){
$this->hasAccount = true;
$this->User->id = $Auth->user($this->User->primaryKey);
if (!$this->User->field('facebook_id')) {
$this->User->saveField('facebook_id', $this->uid);
}
return true;
}
else {
// attempt to find the user by their facebook id
$this->authUser = $this->User->findByFacebookId($this->uid);
//if we have a user, set hasAccount
if(!empty($this->authUser)){
$this->hasAccount = true;
}
//create the user if we don't have one
elseif(empty($this->authUser) && $this->createUser) {
$this->authUser[$this->User->alias]['facebook_id'] = $this->uid;
$this->authUser[$this->User->alias][$this->modelFields['password']] = $Auth->password(FacebookInfo::randPass());
if($this->__runCallback('beforeFacebookSave')){
$this->hasAccount = ($this->User->save($this->authUser, array('validate' => false)));
}
else {
$this->authUser = null;
}
}
//Login user if we have one
if($this->authUser){
$this->__runCallback('beforeFacebookLogin', $this->authUser);
$Auth->authenticate = array(
'Form' => array(
'fields' => array('username' => 'facebook_id', 'password' => $this->modelFields['password'])
)
);
if($Auth->login($this->authUser[$this->model])){
$this->__runCallback('afterFacebookLogin');
}
}
return true;
}
}
}
For me now the facebook plugin is working fine for facebook connect.
I am trying to implement facebook Connect to my cakephp Application. i am using Nick's Facebook Plugin.
I wanna implement it this way
When a user Visits the Site he should be able to login via Registration on the site or Facebook Connect
Existing users should be able to connect their account to their FB account
People who first time login to the site using FB Connect and dont have an account on the site. should be redirected to a page where they have to enter details to complete the profile.
What i have done -
I have followed the instruction of Nick to implement it and when i click Login - it connects to my app. but i dont understand how to create a username and password associated with the Fb Connect Id. and user it against the FB token.
Apparently I'm doing the same thing a little before you... ;-)
Here's a method for Facebook login I'm using (slightly redacted and annotated):
public function facebook($authorize = null) {
App::import('Lib', 'Facebook.FB');
$Fb = new FB();
$session = $Fb->getSession();
// not logged into Facebook and not a callback either,
// sending user over to Facebook to log in
if (!$session && !$authorize) {
$params = array(
'req_perms' => /* the permissions you require */,
'next' => Router::url(array('action' => 'facebook', 'authorize'), true),
'cancel_url' => Router::url(array('action' => 'login'), true)
);
$this->redirect($Fb->getLoginUrl($params));
}
// user is coming back from Facebook login,
// assume we have a valid Facebook session
$userInfo = $Fb->api('/me');
if (!$userInfo) {
// nope, login failed or something went wrong, aborting
$this->Session->setFlash('Facebook login failed');
$this->redirect(array('action' => 'login'));
}
$user = array(
'User' => array(
'firstname' => $userInfo['first_name'],
'lastname' => $userInfo['last_name'],
'username' => trim(parse_url($userInfo['link'], PHP_URL_PATH), '/'),
'email' => $userInfo['email'],
'email_validated' => $userInfo['verified']
),
'Oauth' => array(
'provider' => 'facebook',
'provider_uid' => $userInfo['id']
)
);
$this->oauthLogin($user);
}
This gives me an array with all the user details I could grab from Facebook and invokes ::oauthLogin, which either logs the user in with the given information or asks the user to fill in missing details and/or creates a new user record in the database. The most important part you get from the Facebook API is the $userInfo['id'] and/or email address, either of which you can use to identify the user in your database. If you're using the AuthComponent, you can "manually" log in the user using $this->Auth->login($user_id), where $user_id is the id of the user in your own database.
private function oauthLogin($data) {
$this->User->create();
// do we already know about these credentials?
$oauth = $this->User->Oauth->find('first', array('conditions' => $data['Oauth']));
if ($oauth) {
// yes we do, let's try to log this user in
if (empty($oauth['User']['id']) || !$this->Auth->login($oauth['User']['id'])) {
$this->Session->setFlash('Login failed');
}
$this->redirect('/');
}
// no we don't, let's see if we know this email address already
if (!empty($data['User']['email'])) {
$user = $this->User->find('first', array('conditions' => array('email' => $data['User']['email'])));
if ($user) {
// yes we do! let's store all data in the session
// and ask the user to associate his accounts
$data['User'] = array_merge($data['User'], $user['User']);
$data['Oauth']['user_id'] = $user['User']['id'];
$this->Session->write('Oauth.associate_accounts', $data);
$this->redirect(array('action' => 'oauth_associate_accounts'));
}
}
// no, this is a new user, let's ask him to register
$this->Session->write('Oauth.register', $data);
$this->redirect(array('action' => 'oauth_register'));
}
Look no further. Here is an excellent article that'll guide you all the way through (minus any readymade plugins):
Integrating Facebook Connect with CakePHP's Auth component
Simply follow the approach described in there.
Cheers,
m^e