I am working on Laravel 5.4.30.
Imagine that we have a domain example.com and a subdomain of dev.example.com. The main domain is for master branch and the dev subdomain is for develop branch. We have cookie notice system that will be hidden after clicking on Hide Cookie Notice button. This works by setting a cookie forever.
We have set the SESSION_DOMAIN configs to each domain for each environment.
For main domain:
SESSION_DOMAIN=example.com
For dev subdomain:
SESSION_DOMAIN=dev.example.com
Now the issue comes from here. If we go to the example.com and click on hiding the cookie notice, a cookie will be set forever for main domain. After that we go to the dev.example.com and do the same. So a cookie will be set for subdomain as well. But this cookie has been set after previous one. (The order is important)
Now if we refresh the subdomain, we will see that notice again! (not hidden) The browser has read the main cookie because of .example.com set in domain parameter of cookie in the browser, so every subdomain will be affected. But the view still shows the notice because it cannot read any cookie for hiding.
Anyway I don't want to share that cookie across all subdomains. How can I achieve that? I think I should add a prefix for cookie name. But I don't know how to do it, that laravel automatically adds prefix to cookie name.
Any solutions?
You need to implement your own "retrieving" and "setting" a cookie.
Retrieving (has, get) cookies
Create yourself new class (anywhere you like, but I would do app/Foundation/Facades/) with name Cookie.
use \Illuminate\Support\Facades\Cookie as CookieStock;
class Cookie extends CookieStock {
//implement your own has(...);
public static function has($key)
{
return ! is_null(static::$app['request']->cookie(PREFIX . $key, null)); //get the prefix from .env file for your case APP_ENV
}
//implement your own get(...);
public static function get($key = null, $default = null) {...}
}
Now open up config/app.php and change corresponding alias (cookie).
Setting (make) cookies
Create yourself new provider (use artisan), and copy-paste code from Illuminate\Cookie\CookieServiceProvider.php and change namespaces.
Again open up config/app.php and change corresponding service provider with the new one.
Create yourself new class (anywhere you like, but I would do app/Foundation/Cookie/) with name CookieJar.
use \Illuminate\Cookie\CookieJar as CookieJarStock;
class CookieJar extends CookieJarStock {
//Override any method you think is relevant (my guess is make(), I am not sure at the moment about queue related methods)
public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true)
{
// check before applying the PREFIX
if (!empty($name)) {
$name = PREFIX . $name; // get the PREFIX same way as before
}
return parent::make($name, $value, $minutes, $path, $domain, $secure, $httpOnly);
}
}
Update the code in your own cookie service provider to use your implementation of CookieJar (line 19).
Run $ composer dump-autoload, and you should be done.
Update
Since BorisD.Teoharov brought up, that if framework changes signature of CookieJarStocks make() (or any other cookie related function) in between the major versions, I made a example repository, that includes a test that can be used as is and it will fail if signature change happens.
It is as simple as this:
public function test_custom_cookie_jar_can_be_resolved()
{
resolve(\App\Foundation\Cookie\CookieJar::class);
$this->assertTrue(true);
}
Detailed how to can be inspected in the corresponding commit diff.
I've setup test environments to make sure, I'm not missing any details.
As in my former answer, I thought invalidating cookies will be sufficient for that case, but as #BorisD suggested it is not, and I've confirmed that on my tests.
So there are a few important notes, coming from my experiences...
Don't mix Laravel versions in subdomains - If using SESSION_DOMAIN you need to make sure your Laravel version matches (between root and subdomains), cause I've experimented with 5.4 under example.com domain and 5.6 under dev.example.com. This showed me some inconsistency in dealing with Cookies, so some important changes have been done, between these versions, and you can be sure it will not work correctly if you mix versions. I finally ended up with Laravel 5.6 on both domains, so I'm not 100% sure if that works on Laravel 5.4, but I think it should.
Make sure all your subdomains use the same APP_KEY - otherwise, Laravel will be unable to decrypt the Cookie, returning null value, cause all encryption/decryption in Laravel uses this app key...
SESSION_DOMAIN. In SESSION_DOMAIN I've pointed the same root domain like example.com for both domains. With this setting, I can create a cookie on root domain, and retrieve it correctly on both domains. After that setting, creating a cookie on subdomain forces root domain to receive new value from subdomains cookie also, and they are overridden. So I guess everything works here as requested in the original question.
Cookie make parameters - In case you want to use a subdomain in SESSION_DOMAIN, you can safely do that also. However, you need to make sure, important let's call them global cookies are defined in a bit different way. Cookie make syntax:
Cookie make(string $name, string $value, int $minutes, string $path = null, string $domain = null, bool $secure = false, bool $httpOnly = true)
So what's important here, you need to put your root domain for this particular cookie on creation like this for example:
return response($content)->cookie('name','value',10,null,'example.com')
Conclusions:
With this config, you should be able to access your Cookies properly under subdomains and your root domain.
You may probably need to update your Laravel installations to 5.6, which will force you to upgrade to PHP 7.1 at least (there were some changes to cookies in php also)
And finally, in your code, don't rely on Cookie existence, but on its values only (I don't know if that's in your case).
You could set a prefix for the cookie name depending on the environment.
First, add COOKIE_PREFIX to your env file.
COOKIE_PREFIX=dev
Then, use it when setting your cookie
$cookie = cookie(env('COOKIE_PREFIX', 'prod') . '_name', 'value', $minutes);
Then, retrieve it like so
$value = $request->cookie(env('COOKIE_PREFIX', 'prod') . '_name');
One of reason for that is for both app
APP_KEY and APP_NAME
should same in .env file,
that worked for me after 2 days of tries, I checked each library internally to get this solution.
I have a problem regarding sessions in Laravel. I try to redirect the page and at the same time sending some session variables using the with() method:
return Redirect::To('/')->with('foo','bar');
But when the page comes up, the only session variables set are _token and locale, 'foo' and 'bar' do not appear. Running {!! var_dump(Session::all()); !!} gives:
array(2) { ["_token"]=> string(40) "l5NawtJdHJtanTErsya440UvPQIgqNExiryJIkIO" ["locale"]=> string(2) "se" }
The session stored in storage/framework/sessions strangely has other variables set, such as url and PHPDEBUGBAR_STACK_DATA that don't show up when redirecting.
Now, here's the real twist: It works perfectly when run on a different computer.
We tested with the same repository, same code, a fresh installation of laravel, same web browser, same OS (Mac) and same program for running the server locally (MAMP). On another computer it works fine, and on a third computer, but not on mine.
The application is in debug mode and I have tried clearing all caches in Laravel and in the browser nothing changed.
Does anyone have a clue on how this can be resolved?
with() method use to pass data to a view. If you want to add something to session use session()->flash->('foo', 'bar');(automatically erase after next request) or session()->put('foo', 'bar');
Apparently in config/session.php the variable domain was set to the production domain. So when using localhost on my computer, the cookie laravel_session couldn't be read or written.
It worked by using:
'domain' => null,
session::set and session::get is not working in laravel
Session is working in local machine. But when I test in live server, it is not working.
Scenario: While logging into an application Auth::attempt returns true. But again it redirected to login page. This is an exact issue.
Auth::check method return true under the auth::attempt condition.
But in login page and filter.php, Auth::check method return false.
I don't know why :(
I tested it with a laravel session variable. I assigned a value in a session variable and redirected the page to another page where I have echoed the session. It return empty.
Additional Detail: It does not retain the session flash message in server. It is working in local.
Please advice.
If your session driver is file, then make sure your (storage) path is writable by PHP. Look for this in your session.php file:
'driver' => 'file',
....
'files' => storage_path().'/sessions',
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.
i have some strange behaviour in IE on my magento shop with loosing the frontend (session) cookie. does anybody has a clue, where in the magento code the frontend cookie gets set?
Thanks!
Afaik, the 'frontend' cookie gets set right before the current action is being dispatched.
Have a look at Mage_Core_Controller_Varien_Action::preDispatch().
Session start
Looking into preDispatch(), find the line which starts the session:
Mage::getSingleton('core/session', array('name' => $namespace))->start();
Which usually (if not overridden) finally maps to
Mage_Core_Model_Session_Abstract_Varien::start()
This is the place where all the standard session stuff gets initialized, including cookie settings by using session_set_cookie_params.
Revalidation
Be aware though, that once the cookie already exists, first cookie mangling may already happen while the core session gets instantiated, i.e. before start() is called. That's because the constructor calls revalidateCookie() while instantiating the core session. See:
Mage_Core_Model_Session_Abstract_Varien::init()