How to keep session data using Codeigniter and Tank Auth - codeigniter

I'm using Codeigniter and Tank Auth for a e-commerce website. I'm finding that if a customer puts items into the cart (using the Codeigniter built in cart class) and then registers on the site the session is lost along with their cart (I'm presuming it generates a new session for some reason instead of keeping the same session).
Has anyone come across this problem before? and is there a simply solution that I have overlooked.
Thanks

As far as the most recent code looks like, the only place the hole session is deleted is in the logout() function, Tank_auth.php Line 118:
https://github.com/ilkon/Tank-Auth/blob/master/application/libraries/Tank_auth.php#L118
The example usage of Tank Auth uses logout() in activate() and reset_email() - check your code for those methods. You could also change the Tank Auth logout function to something like this:
function logout($keep_session = false)
{
$this->delete_autologin();
// See http://codeigniter.com/forums/viewreply/662369/ as the reason for the next line
$this->ci->session->set_userdata(array('user_id' => '', 'username' => '', 'status' => ''));
if(!$keep_session)
$this->ci->session->sess_destroy();
}
... and the use it like this: $this->tankauth->logout(true);

Related

Registering users in Laravel as Admin

My current project is a school management system, and I'm using Laravel 5.6 (it's my first Laravel project). I've been trying to register a user from a small form I have inside the Administrator area of my application.
I've set up the routes for the Admin area (view names are not in English, sorry for that):
// Admin
Route::middleware(['auth'])->group(function () {
Route::view('/admin', 'profiles.admin.admin_gerencia_cadastro');
Route::view('/admin/gerencia/cadastro', 'profiles.admin.admin_gerencia_cadastro');
Route::post('/admin/gerencia/cadastro', 'RegController#store');
Route::view('/admin/gerencia/relatorios', 'profiles.admin.admin_gerencia_relatorios');
Route::view('/admin/ped/', 'profiles.admin.admin_ped');
});
The post route (third from the top) was supposed to handle registration of users and leads to RegController and the following method:
public function store()
{
$this->validate(request(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
]);
$user = User::create(request(['name', 'email', 'password']));
return redirect()->to('/admin/gerencia/cadastro');
}
It should store the new user data and redirect the Admin back to /admin/gerencia/cadastro. However, when the form is submitted data is not stored on the database and I'm redirected to the homepage instead. I've tried different things, consulted the documentation, but no success so far.
Any help will be much appreciated.
Edit:
Came here to post the form, as requested below, but I found my own mistake - a rookie one: the form action was wrong. Sorry guys, I'll close the question :)
Is your request reaching in store() method?
try to write
print_r($_REQUEST);exit;
on first line of method. If it's not reaching there, then put below route before all other routes of your route group:
Route::post('/admin/gerencia/cadastro', 'RegController#store');
check out this link for better understanding of routing in laravel.

Laravel 5: Sessions not working the way they should

On top of every controller and routes.php I used:
use Illuminate\Support\Facades\Session;
In routes.php I set the session using:
Session::put('key', 'value');
In a controller I want to call the session value of key using:
echo Session::get('key');
But once I set a new value to key in routes.php and call it in a controller, I still get the first value and not the new one. If I echo the the session using Session::all() in routes.php after setting it, I see the new value, but in a controller it flips back to the first value. I even tried using below in routes.php before setting the new value, but without success.
Session::forget('key');
Am I forgetting something here?
Using regular PHP $_SESSION my routes.php looks like this:
$slug = $_SERVER['REQUEST_URI'];
$slug = explode('/', $slug[0]);
if(in_array($slug[1], Language::all()->lists('iso'))) {
$_SESSION['language'] = $slug[1];
if(!$slug[2]) {
$_SESSION['slug'] = 'home';
Route::any('/{slug}', ['as' => 'pages.page', 'uses' => 'PagesController#page']);
} else {
if($slug[2] != 'dashboard' && $slug[2] != 'migrate' && $slug[2] != 'form-send') {
if (in_array($slug[2], ElementValue::where('element_field_id', 2)->lists('value_char')) && !isset($slug[3])) {
$_SESSION['slug'] = $slug[2];
Route::any('/{slug}', ['as' => 'pages.page', 'uses' => 'PagesController#page']);
} else {
$_SESSION['slug'] = 'home';
Route::any('/{slug}', ['as' => 'pages.page', 'uses' => 'PagesController#page']);
}
}
}
}
Where in routes.php are you setting the session value? It sounds like you're doing something like this:
Session::put('key', 'value');
Route::get('my-route', 'MyController#doSomething');
and then doing this:
class MyController {
public function doSomething()
{
Session::get('key');
}
}
Is that correct? If so, read on...
I'm no expert on the Laravel request lifecycle (for more, see the documentation), but it doesn't surprise me that this doesn't work. The way I think about it is this: the routes.php file is loaded and executed early in the life cycle - probably first - since it tells the application what code to execute next (ie. what do when a particular request is received). And when I say "early in the life cycle", I mean early - like before sessions are initialized. I believe that the Session::put call is simply being ignored, since at the time when you're setting the value, the session does not exist.
You may want expand your question with a little more detail about what you're trying to accomplish - there has got to be a better way to do it.
EDIT - in response to the comments below...
I am not saying you should touch the $_SESSION superglobal - that's a bad idea because I'm not even sure that Laravel uses the native PHP session facility and you have no guarantee that whatever you do will continue to work in the future.
It's not clear what you're trying to do, but to me this sounds like a value that does not belong in the session.
By placing the Session::put in the routes.php file, it sounds like you have some value that's important and should be set for every session and every request
If that's the case, and it's a static value, then it's not a session value, it's a configuration value.
If, instead, it's a dynamic value and/or it changes depending on which user is associated with a session, then you can set it in one of several places:
if you're using controller-based routing, you could set this in the controller constructor, although I wouldn't recommend it, because you will probably have to do it for several controllers, leading to code duplication
if you're using closures in your routes, set it there. E.g.
Route::get('some/route', function () {
Session::put('key', 'value');
// this works, because the closure isn't executed until after
// the application is initialized
});
you could also do it in middleware
or in a service provider (although I'm not certain that sessions would be available when the service providers are executed).
The best option is probably middleware - this would allow you to set (or calculate) the session value in one place in your code and also associate it with particular routes, if you don't need it for all routes.
Don't use $_SESSION in laravel. Uses the laravel Session class. See the following post How to access the globals $_SESSION and $_COOKIE from a laravel app?
Also, all your if logic should not be living in routes.php. You should add that to middleware to filter your routes.
Also, you are really making this hard for yourself. Laravel provides most of what you need in convenient helper classes e.g. Request::url(), Request::getHost(), Request::getLocale(). Have a read through the docs and get familiar with "The Laravel Way" it will be much easier and things will then work as you expect.
I moved the logic to the controller and now my routes are this simple:
Route::pattern('slug', '[a-zA-Z0-9\-_\/]+');
$slug = Request::path();
if(isset($slug)) {
Route::any('/{slug}', 'PagesController#index')->where('slug', '[a-zA-Z0-9\-_\/]+');
}
The session is stored in the PagesController and used further in the application. Thanks for your help guys.

Laravel 5 and Socialite - New Redirect After Login

Another newb question here, but hopefully someone can shed some light:
I am using Socialite with Laravel 5, and I want to be able to redirect the user to a page on the site after they have logged in. The problem is that using
return redirect('any-path-I-put-here');
simply redirects back to 'social-site/login?code=afkjadfkjdslkfjdlkfj...' (where 'social-site' is whatever site is being used i.e. facebook, twitter, google, etc.)
So, what appears to me to be happening is that the redirect() function in the Socialite/Contracts/Provider interface is overriding any redirect that I attempt after the fact.
Just for clarification, my routes are set up properly. I have tried every version of 'redirect' you can imagine ('to', 'back', 'intended', Redirect::, etc.), and the method is being called from my Auth Controller (though I have tried it elsewhere as well).
The question is, how do I override that redirect() once I am done storing and logging in the user with socialite? Any help is appreciated! Thank you in advance.
The code that contains the redirect in question is:
public function socialRedirect( $route, $status, $greeting, $user )
{
$this->auth->login( $user, true );
if( $status == 'new_user' ) {
// This is a new member. Make sure they see the welcome modal on redirect
\Session::flash( 'new_registration', true );
return redirect()->to( $route );// This is just the most recent attempt. It originated with return redirect($route);, and has been attempted every other way you can imagine as well (as mentioned above). Hardcoding (i.e., 'home') returns the exact same result. The socialite redirect always overrides anything that is put here.
}
else {
return redirect()->to( $route )->with( [ 'greeting' => $greeting ] );
}
}
... The SocialAuth class that runs before this, however, is about 500 lines long, as it has to determine if the user exists, register new users if necessary, show forms for different scenarios, etc. Meanwhile, here is the function that sends the information through from the Social Auth class:
private function socialLogin( $socialUser, $goto, $provider, $status, $controller )
{
if( is_null( $goto ) ) {
$goto = 'backlot/' . $socialUser->profile->custom_url;
}
if( $status == 'new_user' ) {
return $controller->socialRedirect($goto, $status, null, $socialUser);
}
else {
// This is an existing member. Show them the welcome back status message.
$message = 'You have successfully logged in with your ' .
ucfirst( $provider ) . ' credentials.';
$greeting =
flash()->success( 'Welcome back, ' . $socialUser->username . '. ' . $message );
return $controller->socialRedirect($goto, $status, $greeting, $socialUser);
}
}
I managed to workaround this problem, but I am unsure if this is the best way to fix it. Similar to what is stated in question, I got authenticated callback from the social media, but I was unable to redirect current response to another url.
Based on the callback request params, I was able to create and authenticate the user within my Laravel app. It worked good so far but the problems occured after this step when I tried to do a return redirect()->route('dashboard');. I tried all the flavours of redirect() helper and Redirect facade but nothing helped.
The blank page just stared at my face for over 2 days, before I checked this question. The behaviour was very similar. I got redirect from social-media to my app but could not further redirect in the same response cycle.
At this moment (when the callback was recieved by the app and user was authenticated), if I refreshed the page manually (F5), I got redirected to the intended page. My interpretation is similar to what's stated in this question earlier. The redirect from social-media callback was dominating the redirects I was triggering in my controller (May be redirect within Laravel app got suppressed because the redirect from social-media was still not complete). It's just my interpretation. Experts can throw more light if they think otherwise or have a better explaination.
To fix this I issued a raw http redirect using header("Location /dashboard"); and applied auth middleware to this route. This way I could mock the refresh functionality ,redirect to dashboard (or intended url) and check for authentication in my DashboardController.
Once again, this is not a perfect solution and I am investigating the actual root of the problem, but this might help you to move ahead if you are facing similar problem.
I believe you are overthinking this. Using Socialite is pretty straight forward:
Set up config/services.php. For facebook I have this:
'facebook' => [
'client_id' => 'your_fb_id',
'client_secret' => 'your_fb_secret',
'redirect' => '>ABSOLUTE< url to redirect after login', //like: 'http://stuff'
],
Then set up two routes, one for login and one for callback (after login).
In the login controller method:
return \Socialize::with('facebook')->redirect();
Then in the callback function
$fb_user = \Socialize::with('facebook')->user();
// check if user exists, create it and whatnot
//dd($fb_user);
return redirect()->route('some.route');
It should be pretty much similar for all other providers.
We are using the Socialite login in our UserController as a trait. We simply overrode the AuthenticatesSocialiteLogin::loginSuccess() in our controller.
use Broco\SocialiteLogin\Auth\AuthenticatesSocialiteLogin;
class UserController extends BaseController
{
use AuthenticatesSocialiteLogin;
public function loginSuccess($user)
{
return redirect()->intended(url('/#login-success'));
}
....

How to forward argument for redirect::route->with when hitting an auth filter using Laravel?

I have the following problem:
After a user is created and the user has confirmed her email.
I would like the user to login,
I use the following code to do that:
Redirect::route('login-forward')->with('alert_message', ...)
the alert messages simply states that everything went well, and I would like her to login.
login-forward is protected with an before filter, that runs the actual login form,
When the user then logs in sucesfully, she is brought back to login-forward, whic then puts the user at her personal landing page.
the code for the route 'login-forward is:
Route::get('my-login', array(
'as' => 'login-forward',
'before' => 'auth',
function ()
{
$user = Auth::user();
switch ($user->role)
{
case 'Administrator':
return Redirect::route('admin_dashboard');
case 'FreeUser':
return Redirect::route('cs-dashboard');
default:
return Redirect::route('/');
}}));
the problem is, the ->with('alert_message',...) is not seen by the real login route called by the before filter.
How do I solve this?
The best approach is to let the user logs in automatically when the email is confirmed, if the user confirms the account creation then when you find that user is valid then you may log in that user using something like:
// $user = Get the user object
Auth::login($user);
Also you may use:
Session::put('alert_message', ...);
Redirect::route('login-forward');
Then when the user logs in for the first time, just get the message from Session using:
// Get and show the alert_message
// from session and forget it
#if (Session::has('alert_message'))
{{ Session::pull('alert_message') }}
#endif
So, when you pull the message from the Session to show it, the message will no longer be available in the Session or you may use Session::reflash() to flash the flashed session data for another subsequent request until you get in the page where you want to show the message.
The best choice is - you can make forward to login form without redirect from method of controller for url of personal page.
return Route::dispatch(Request::create('login'))->getOriginalContent();

Magento - Customer Not Logged in After Redirect From External Page

I'm having a lot of trouble getting a customer to stay logged in after I have created a new account. I'm creating them an account and adding products to a cart from an external site, and then sending them to Magento store. What I want to have happen is:
A customer goes to a signup page and enters relevant information.
They go to a new page where they can choose to add free samples to their cart.
After picking samples. their account is created and they are redirected to the Magento store with the samples in their cart.
The problem I'm having is between steps 2 and 3. I create an account using the Magento's SOAP API with the following:
$customerInfo = array('firstname' => $custFirstname, 'lastname' => $custLastname, 'email' => $email, 'password_hash' => md5( $new_password ), 'store_id' => 34, 'website_id' => 25,'group_id' => 9);
// Call API method customer.create
$newCustomerId = $client->call( $session, 'customer.create', array( $customerInfo ) );
I then return their customer ID, which I pass to another function which actually logs them in and adds products to their cart:
public static function _addSamplesToCart($customer_id, $sample_one, $sample_two, $sample_three){
Mage::getSingleton("core/session", array("name" => "frontend"));
$customerSession = Mage::getSingleton('customer/session', array("name" => "frontend"));
$customerSession->init("customer_bn_us");
$customerSession->loginById($customer_id);
$cart = Mage::getSingleton('checkout/cart');
$cart->addProductsByIds($idArray);
$cart->save();
$cart->getCheckoutSession()->setCartWasUpdated(true);
}
These functions are actually called from AJAX post requests, so when I get a successful return value from _addSamplesToCart, I do a simple javascript redirect (window.location ="http://www.myhostname.net/welcome") and it correctly takes me there, but I'm not logged in.
I've been looking around all afternoon and trying a few different things and nothing has worked. I've also tried doing a hidden form submit to /customer/account/loginPost and it still doesn't work. I have verified that it's correctly creating an account in Magento. My only hunch is that I'm doing this with a mix of AJAX and PHP so somehow the cookies or sessions are getting mixed up?
If you are trying to login from an hostname different from the one used by the Magento store, it cannot work. You can verify this by checking if a frontend cookie is created after the AJAX call.
I suggest you to create a new controller in Magento that receives the id of the customer just created and executes the code you wrote in your function:
www.myhostname.net/autologin/myaction/13 (where 13 is the id of the customer just created).
Obviously you should add something else to avoid security issues.

Resources