Yii2 $session->setId() not working - session

I'm using Ajax to log in a user from subdomain. The Yii2 app is on another subdomain. Both subdomains are configured to use same cookie and session domains and save paths. I'm including session ID with Ajax call to write the user information to the same session used by non-app subdomain like this:
$session = Yii::$app->session;
$session->open();
$session->setId($post["session"]);
$session["user.id"] = $user->id;
echo $session->id; // This does not return the same ID originating from post!
Unfortunately the user information IS NOT written to the session already existing, but a new one. Is there a session involved somewhere in the middle of login process or why isn't it working? I've also tried session_id($post["session"]), but nothing.
This was actually working on previous domain, so I must be missing something. All of the AJAX posted info is correct and checked, the user is logged in properly (checked the logs) but into wrong session.
Thanks in advance!

yii\web\Session::setId() is a wrapper for session_id(), you should read PHP documentation about this function :
string session_id([ string $id ])
If id is specified, it will replace the current session id. session_id() needs to be called before session_start() for that purpose.
So you should simply try :
$session = Yii::$app->session;
$session->setId($customId);
$session->open();

I Don't think you are following the correct way to SET & GET session.
Try This:
$session = Yii::$app->session;
$session->open();
$session->set('id', $post["session"]);
echo $session->get('id');
For more info, please click Session Management - Yii2

Related

Laravel: share session data over multiple domains

I'm building a multi-domain/multi-store ecommerce application in Laravel and would like to keep the user logged in when he or she changes from store to store.
But for as far as I know Laravel's Auth service saves the logged in user in the session and the sessions can't be accessed by other domains.
Is there a way (maybe a package) to achieve this, without leaving my application prone to possible security problems?
Thanks in advance!
Capture the session id Session::getId() in Domain A
send the captured session id via HTTP POST to Domain B
Access the sent session id in domain B $sessionid_from_domainA = $_POST['session_from_A']
Set session in domain B Session::setId($sessionid_from_domainA)
Start Session in domain B Session::start()
If you want to share the session between multiple subdomains in that case you have to set the domain name config/session.php has set the domain name.
Example: if you have new.example.com and test.example.com so you have to set the domain name as example.com
'domain' => env('SESSION_DOMAIN_URL','.example.com')
Solutions there worked for me, specifically setting the domain and then clearing my browser cookies & cache.
On domain A create an image like so <img src="https://DOMAINB.com/setcookie?id={{ Session::getId() }}" style="display:none;" />
On Domain B create a Route like so:
.
Route::get('setcookie', function(){
Session::setId($_GET['id']);
Session::start();
return 'Cookie created';
});`
Done, Now you should be able to get your user by $user = Auth::User;
I know this is not exactly what was asked for, but, for development and testing purposes, I did this:
In config/session.php, try changing this line
'path' => '/',
Into this
'path' => '/;SameSite=None; secure',
allowed me to authenticate from different domains.
Now, you should be able to write a simple middleware to prevent unwanted hosts. Something like this.
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Closure;
class TrustedHosts{
public function handle($request, Closure $next){
//$host = $request->getHost();
$host = $request->headers->get('origin');
$enviroment = env('APP_ENV');
if ( $enviroment == 'development' ) {
$trustedHosts = array('localhost', 'dev.mydomain.com');
}
else {
$trustedHosts = array('anotherdomain.com', 'mydomain.com');
}
$isHostTrusted = in_array($host, $trustedHosts);
if ( !$isHostTrusted ) return response("I'm a teapot", 418); //Or any other code and message that you prefer.
return $next($request);
}
}
And group it in the middleware group that includes the session stuff.
I am working on something like that too a single sign-on system, still working to find a solution, but here is a start http://laravel.io/forum/03-14-2014-multiple-domains-how-to-share-login
On laravel you can change the /app/config/session.php driver to cookie
Edit:
This is what I have done.
You can share cookie accross domains using pixel images.
For example when you login on domain1.com you want to create a cookie on domain2.com, right after login on domain1.com you need to have something like this
<img src="http://www.domain2.com/create-cookie?param=hash">
on domain2.com the route above:
will check first if a user is logged in
if its not logged in will read the hash (for example email address), check if there is a user with that email, and login it there, also set a cookie
You can manually set which domain the session cookies will be registered, and thus have them persist across different sites. Just edit config/session.php, in the following section:
<?php
/*
|--------------------------------------------------------------------------
| Session Cookie Domain
|--------------------------------------------------------------------------
|
| Here you may change the domain of the cookie used to identify a session
| in your application. This will determine which domains the cookie is
| available to in your application. A sensible default has been set.
|
*/
'domain' => null,
?>
You're still restricted to a single top-level domain, though. So you can have store1.shops.com and store2.shops.com sharing sessions, but not myshop.com and shopsmart.com.
If you need something in this format, you'll probably fare better by creating an authentication service, and using access tokens to validate the credentials. You might also give a look at services like OneLogin.
Based on this answer of Chirag Prajapati. Yo could use $_SERVER['HTTP_HOST'] in the env entry:
From /config/session.php
'domain' => env('SESSION_DOMAIN', $_SERVER['HTTP_HOST']),
Then from the app root: php artisan config:clear and don't keep attention to warning messages, just be sure at the end you have gotten Configuration cache cleared! By this way your app session will work fine on whatever domain you have.

What should I do when users log out?

I am setting Mixpanel up, and I found out that if I log in with a user (and identify that user), log out and then re-register as a new user, the new user's details overwrite the previously logged in user (presumably when I call alias). How can I tell mixpanel that a user has logged out and to reset the identity token (make it anonymous again)?
I ran into the same issue, and after some sleuthing I discovered that you can manually clear the mixpanel cookies with mixpanel.cookie.clear().
However, you need to make sure that the mixpanel library has loaded, so I ended up putting it in a stupid timeout:
var id = window.setInterval(function() {
if (mixpanel.cookie && mixpanel.cookie.clear) {
mixpanel.cookie.clear();
window.clearInterval(id);
}
}, 50);
And then, since I didn't want to do this on every page, I added a query string parameter onto my logout redirect URL. So after visiting /logout it would redirect them to /home?_ref=logout, at which point I would clear the mixpanel cookie only if that query string parameter existed.
It was pretty annoying, but it seemed to work.
It was released on Mixpanel Javascript version v2.8.0 the mixpanel.reset() function, so that's officially what should be called on user logout. See https://github.com/mixpanel/mixpanel-js/issues/67 .
for android
on logout you can use this MixpanelAPI.reset()
Call clearSuperProperties() to remove any Super Properties in local
storage.
Set new_distinct_id = UUID.randomUUID().toString());
Call .identify(new_distinct_id) and .getPeople().identify(new_distinct_id)
This should wipe the device clean for a fresh user that can then register and be aliased to another distinct_id.
The best way to do this with javascript is to delete the cookie. The name of the cookie is mp_{mixpanel_token_id}_mixpanel

cakephp, session not working unless allow a cookie in browser

Using latest version of cakephp v2.3.3
I have a problem with my session variables when a browser doesn't allow cookies.
I pass variables from one controller to the other and this works perfect as long as the browser has cookies enabled. I have tried it with the Session helper in the controllers, but no effort, same problem.
How to fix this, is there a work around???
Cookies are required to keep track of the session ID, but you can manually get or set the session ID using $this->Session->id(). By adding the code below to the App Controllers' before filter you can set the session ID as a URL paramter like http://example.com/posts/view/1?session=qkv108c2pqeubcpeos1q7ekds3, for example.
if (!empty($this->request->query['session'])) {
$this->Session->id($this->request->query['session']);
}
The session ID is required for every request which means you have to include it in every link. I would suggest extending the HTML helpers' url and link methods to automatically add it.
Edit:
You should verify that $this->Session->read('Config.userAgent'); or $this->request->clientIp(); has not changed since the user was authenticated to prevent session hijacking. Thanks to thaJeztah for pointing this out.

Magento external login will not create session cookie

I am trying to replace a rather clumpsy ajax-login of Magento from an external site. The site uses Magento as a shop. Both the site and the magento-shop has their own logins, therefor when a user logs in it is important that both are synchronized. This was done with an ajax-call each page reload, keeping the user logged into Magento. I want to remove this so I created a check on each page reload which will do everything server-side.
My problem is, the following code does not work properly:
//Get Magento session-object
Mage::getSingleton("core/session", array("name"=>"frontend"));
$session = Mage::getSingleton("customer/session", array("name"=>"frontend"));
//Check if logged in
if(!$session->isLoggedIn()){
//Not logged in, therefor log in
$mpassword = $this->getMagentoPassword();
$musername = $this->getAddress();
try
{
$session->login($musername, $mpassword);
}catch(Exception $e){
echo $e->getMessage();
}
}
Looking at cookies, there aren't any created, the ajax-login actually made a "frontend"-cookie. I know the code above actually logs in a user, but there aren't any session cookies created. Any suggestions?
Magento only initializes the session with your code if the $_SESSION variable isn't set, i.e. session_start() wasn't called before the core session is instantiated.
Reference Mage_Core_Model_Session_Abstract_Varien::start() for details.
As a solution, the easiest way would be to start the Magento session during a request before the other session of your site is started.
Otherwise you will have to duplicate the code that sets the session name to frontend and initializes the Magento session cookie.

PHP session login different for url with www and without www?

I am debugging on session login, when i am login to www.domainname.com the session will be only set for with www.
When i am going to url domain.com, session login is ignored, and i will be prompted to login form again.
I have set session cookie_domain also, but not working.
Any one can help me? why?
I know this question is as old as "Who came first? The egg or the chicken?"
I had a lot of trouble about this issue.
But... if you're using php I've found a solution:
In your login script insert in the first line
<?php
session_set_cookie_params(0, '/', 'www.yourdomain.com');
session_start()
?>
or you can try yoursubdomain.yourdomain.com instead www.yourdomain.com.
It works for me. Hope it help other users too.
I highly recommend redirecting users to the canonical version of the site (probably the www.example.com domain). Look around, you'll notice that most sites do exactly this for consistency (including SO; see what happens when you go to www.stackoverflow.com).
Have you tried setting the session domain to ".example.com"?:
$lifetime = 0;
$path = '/';
$domain = '.yourdomain.com';
session_set_cookie_params($lifetime, $path, $domain);
Note the dot in the beginning of the $domain string variable.
Check the reference of the function here.

Resources