Symfony2 Cookies not being set in controller - php

I can't seem to get cookies set from my controller.
code:
/**
* #Route("", name="wx_exchange_default_index")
* #Template("WXExchangeBundle:Default:index.html.twig")
* #Method({"GET"})
*/
public function indexAction(Request $request)
{
$returnArray['parents'] = self::getCategories();
$cookieLocationSession = $request->cookies->get('locationidsession', 0);
$cookieLocation = $request->cookies->get('locationid', 0);
$securityContext = $this->container->get('security.context');
$hashids = $this->get("wxexchange_hashids_service");
if ($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED'))
{
$user = $securityContext->getToken()->getUser();
$returnArray['user'] = $user;
$location = $user->getTblProfile()->getTblLocation();
if(!$cookieLocation || $cookieLocation != $hashids->encrypt($location->getId()))
{
$cookieLocation = $hashids->encrypt($location->getId());
//TODO: cookies are not being set figure out whys
$response = new Response();
$response->headers->setCookie(new Cookie("locationid", $cookieLocation, 365, '/', null, false, false));
$response->sendHeaders();
}
}
if (!$cookieLocation && !$cookieLocationSession)
{
return $returnArray;
}
if ($cookieLocationSession)
{
$cookieLocation = $cookieLocationSession;
}
if (!isset($location) || $cookieLocationSession)
{
$locationService = $this->get("wxexchange_location_service");
$locationId = $hashids->decrypt($cookieLocation);
if(count($locationId) >= 1)
$location = $locationService->getLocationById($locationId[0]);
}
if(isset($location))
return $this->redirect($this->generateUrl('wx_exchange_location', array('slug' => $location->getSlug(), 'locationid' => $cookieLocation)));
return $returnArray;
}
Do I have to return the response? If I do how do I keep processing (I have a redirect further down in my code)?
Edit: Interestingly enough if the same cookie is already set (via JQuery) running the code above deletes it, but it won't set it.
Edit: Action code posted.

The cookie object has httpOnly set to true by default, http://api.symfony.com/2.0/Symfony/Component/HttpFoundation/Cookie.html
This means that the browser should not make the cookie visible to client-side scripts. If you need to see the cookie in your scripts you can pass the 7th parameter as false when you create the cookie.
$response->headers->setCookie(new Cookie('foo', 'bar',time() + 60, '/', null, false, false));
If you just need to view the cookie for debugging purposes you can use Chrome Dev tools. They are available under the 'Resources' tab.
Edit : Try $response->sendHeaders();

Oops, Sorry everyone.
It's my error.
In my javascript I'm using a Jquery cookie plugin and when you set a new cookie you tell it the number of days before expiry:
$.cookie('locationid', value, { expires: 365, path: '/' });
Unfortunately I used a part of this syntax in my controller:
$cookie = new Cookie("locationid", $cookieLocation, 365, '/', null, false, false);
The problem is the third parameter is supposed to be a DateTime so while I thought I was telling it to expire in 365 days I probably created a cookie that expired almost instantly after creation.
Thanks for all the answers and time spent on your part, this is why I love SO.

Related

Session getting destroyed after cashfree payment gateway redirecting in laravel 8 (Mozilla browser)

I am trying to integrate the Cashfree payment gateway in my Laravel 8 project. The only issue I face is in the callback URL, where an active session is automatically destroyed after getting the post data from Payment Gateway. I have also added the CSRF exception to Middleware. I have added 'secure' => env('SESSION_SECURE_COOKIE', false) & 'same_site' => null.
I have tried with a redirect()->away($payment_link), iFrame tag, and form submits directly to payment link but still getting the same issue.
The session is getting destroyed in the Mozilla browser, but it works fine in the chrome browser.
Controller (Generate Payment Request, URL, and Process Callback)
class PaymentController extends Controller
{
public function credits_add()
{
AuthCheck();
$this->data['page_name'] = 'Add Credits';
return view('merchant.payment.add_credits', $this->data);
}
public function credits_save(Request $request)
{
$request->validate([
'credit_amount' => 'required',
'credit_transaction_type' => 'required'
]);
if (!empty($request->input('credit_transaction_type')) && $request->input('credit_transaction_type') == 'Cashfree') {
$cashfreeDetails = $this->pay_with_cashfree($request);
if (!empty($cashfreeDetails) && !empty($cashfreeDetails['paymentLink'])) {
return Redirect::to($cashfreeDetails['paymentLink']);
} else {
return redirect('credits/add')->with('errorMessage', 'Sorry! Your transaction has failed.');
}
}
return redirect('credits/add');
}
public function pay_with_cashfree($request)
{
$order = new Order();
$od["orderId"] = "ORDER-84984941";
$od["orderAmount"] = 10000;
$od["orderNote"] = "Subscription";
$od["customerPhone"] = "9000012345";
$od["customerName"] = "Test Name";
$od["customerEmail"] = "test#cashfree.com";
$od["returnUrl"] = route('CreditsSuccess');
$od["notifyUrl"] = route('CreditsSuccess');
$order->create($od);
$linkArray = $order->getLink($od['orderId']);
$detailsArray = $order->getDetails($od['orderId']);
if (!empty($order) && !empty($linkArray) && !empty($linkArray->status) && $linkArray->status == 'OK') {
return array(
'paymentLink' => $linkArray->paymentLink,
'paymentDetails' => $detailsArray
);
} else {
return array();
}
}
public function credits_success(Request $request)
{
$orderId = $request->orderId;
$orderAmount = $request->orderAmount;
$referenceId = $request->referenceId;
$txStatus = $request->txStatus;
$paymentMode = $request->paymentMode;
$txMsg = $request->txMsg;
$txTime = $request->txTime;
$signature = $request->signature;
if ($txStatus == 'SUCCESS') {
return redirect('credits/add')->with('successMessage', $txMsg);
} else {
return redirect('credits/add')->with('errorMessage', $txMsg);
}
}
}
OK I figured out the problem for myself.
The new versions of the browsers might be logging you out because of the new cookie policy.
References https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
Whenever the cookie is required to be sent to server, the browser sees the SameSite attribute to decide if the cookie to be sent to server or blocked. For user actions, it is sent to the server but for auto-redirects, it doesn't if SameSite is set to 'Strict' or 'Lax' (Lax is going to be the default value now).
Solution: The cookie attribute SameSite can be set to 'None' along with specifying the 'Secure' attribute to 'true'. Setting 'Secure' attribute to 'true' would require your site to run on https. Sites running with http:// protocol will not be able to set 'Secure' cookie. Please set the 'HttpOnly' attribute to 'true' for making it accessible for http requests to the server only.
You can consider the following configuration for cookie:
SESSION_SECURE_COOKIE=true
SAME_SITE=none
You can also refer below tutorial that explains the cashfree integration in laravel:
https://www.w3techpoint.com/laravel/laravel-9-cashfree-payment-gateway-integration

Drupal 8 set cookie on every page load using event subscriber

I am trying to set a cookie on every page load. I did some research and found that event subscribers are the way to go.
I created a custom module with event. It starts the event on every page load but the problem is with the cookies.
The $event object has property called response but it is always null.
Therefore i cannot set any cookies.
class LanguageCookieSubscriber implements EventSubscriberInterface
{
protected $event;
protected $cookieValue;
public function init(GetResponseEvent $event) {
$this->event = $event;
$cookie = new Cookie("client_language_cookie", $this->cookieValue, 0, '/', NULL, FALSE);
$this->event->getResponse()->headers->setCookie($cookie);
}
}
I also tried to set the response object. Then I can set the cookie but the page will come blank.
$response = new Response();
$this->event->setResponse($response);
$cookie = new Cookie("client_language_cookie", $this->cookieValue, 0, '/', NULL, FALSE);
$this->event->getResponse()->headers->setCookie($cookie);
Any ideas how can i solve this? I need to display the page user has requested and only set cookie.
Thanks in advance.
Example:
public function onKernelResponse(ResponseEvent $event) {
$response = $event->getResponse();
$cookie = new Cookie('cookie name', 'my_cookie value', time() + 60 * 60 * 24 * 7);
$response->headers->setCookie($cookie);
$event->setResponse($response);
}

Symfony cookie not sent (but in Response Header)

I can't understand why my cookie isn't sent.
I've check all the thread about it and it seems that I'm doing it right.
I can't see the cookies in the Symfony debug, but not on my browser.
public function indexAction(Request $request)
{
$response = new Response();
$userID = $request->cookies->get('myCookie123');
if (empty($userID)) {
$uniqueID = $this->generateIDUtil();
$response->headers->setCookie(new Cookie('myCookie123', $uniqueID, 2147483647));
$response->sendHeaders();
}else{
var_dump('USER ALREADY KNOW <br>' );
}
var_dump($response->headers->getCookies()); //GIVES CORRECT COOKIE OBJECT
var_dump('<br>');
var_dump($request->cookies->all()); //GIVES ONLY PHPSESSID, BUT NOT THE ONE CREATED
var_dump('<br>');
var_dump($request->cookies->get('myCookie123')); //GIVES NULL
return $response->setContent($this->render('MyBundle:Core:index.html.twig'));
}
So here a working piece of code for anyone that want to get a userId from a cookie. With all the use statement and the twig rendering template.
The problem with the solution above is that it will give you a blank page as you send the header without rendering the view.
As it's really badly documented, here is a working solution.
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class tempController extends Controller
{
public function indexAction(Request $request)
{
$user = $request->cookies->get('myCookie'); // $user is a string (the userID) or null if there is no cookie.
if (!empty($user)) {
//Fetch user data in the DB
}
// some code ...
$response = new Response();
if ($user instanceof User) {
// do some stuff like pre fill a form
}else{
// We don't know the user we send a cookie.
$cookie = new Cookie('myCookie', $this->generateIDUtil(), time() + (365 * 24 * 60 * 60)); // Expires 1 years
$response->headers->setCookie($cookie);
$response->sendHeaders();
}
//Render the view WITH the response (It's very important to put $response as 3rd parameter)
return $this->render('MyBundle:Core:index.html.twig', array(/* view param */), $response);
}
}
Here is how you properly create a cookie and send as a Response to a client:
$res = new Response();
$cookie = new Cookie(
'my_cookie',
$student->getStuId(),
time() + ( 2 * 365 * 24 * 60 * 60) // Expires 2 years.
);
$res->headers->setCookie( $cookie );
$res->send();
I use it all the time, so please let us know if you still have problems.

how to destroy cookie after 1 minute in cakephp?

I am new in cakephp 3.0. i have successfull created a cookie but i want to destroy that cookie after one minute. i have done so far:-
public function register_cookie(){
$data = "Hello world!";
$this->Cookie->write('dataFetch', $data, true, time() + (60 * 1));
}
public function getcookie() {
$cookiedata = $this->Cookie->read('dataFetch');
echo $cookiedata;
}
but when i come after one minute in getCookie function it still prints i.e. "Hello World"
i want after one minute cookie is expired.
Thanks in advance :)
In cakephp 3.x as the document says you can have these paramenters
CookieComponent::write(mixed $key, mixed $value = null)
But in cakephp 2.x it use to take these parameters
CookieComponent::write(mixed $key, mixed $value = null, boolean $encrypt = true, mixed $expires = null)
To set expiry time you have to set the configuration like this
$this->Cookie->config([
'expires' => '+10 days',
]);
So you code will be like this
public function register_cookie(){
$this->Cookie->config([
'expires' => '+1 minute',
]);
$this->Cookie->configKey('dataFetch', 'encryption', false);
$data = "Hello world!";
$this->Cookie->write('dataFetch', $data);
}
First, you should check if the cookie expiration date was set correctly. For example, in Chrome (after inspect element triggers the console bar), go to Application\Storage\Cookies\Localhost and check the cookie.
In cakephp you can delete a cookie with
$this->Cookie->delete('bar');
Also you can destroy a cookie by setting the expiration date into the past with time()-1

Slim 3 Framework + Cookies

I've been using Slim Framework 2 for a while but want to switch to the newest version 3. When reading the upgrade guide, I was a bit bummed about them simply stating that "cookies has been removed from the core" and referring to the FIG Cookies github repo that contains code snippets that simply don't work with Slim.
Could anyone share some working code snippets that set and get some dummy cookies using Slim 3? Thanks.
If you don't want to use the tested PSR-7 library FIG Cookies you can use this:
namespace Your\App;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
class Cookie
{
/**
* #param Response $response
* #param string $key
* #param string $value
* #return Response
*/
public function deleteCookie(Response $response, $key)
{
$cookie = urlencode($key).'='.
urlencode('deleted').'; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; secure; httponly';
$response = $response->withAddedHeader('Set-Cookie', $cookie);
return $response;
}
/**
* #param Response $response
* #param string $cookieName
* #param string $cookieValue
* #return Response
*/
public function addCookie(Response $response, $cookieName, $cookieValue)
{
$expirationMinutes = 10;
$expiry = new \DateTimeImmutable('now + '.$expirationMinutes.'minutes');
$cookie = urlencode($cookieName).'='.
urlencode($cookieValue).'; expires='.$expiry->format(\DateTime::COOKIE).'; Max-Age=' .
$expirationMinutes * 60 . '; path=/; secure; httponly';
$response = $response->withAddedHeader('Set-Cookie', $cookie);
return $response;
}
/**
* #param Request $request
* #param string $cookieName
* #return string
*/
public function getCookieValue(Request $request, $cookieName)
{
$cookies = $request->getCookieParams();
return isset($cookies[$cookieName]) ? $cookies[$cookieName] : null;
}
}
Slim 3 has Cookies class. you are not forced to use external library for setting cookie:
$setcookies = new Slim\Http\Cookies();
$setcookies->set('auth',['value' => $jwt, 'expires' => time() + $expire, 'path' => '/','domain' => 'example.com','httponly' => true,'hostonly' => false,'secure' => true,'samesite' => 'lax']);
$setcookies->set('tracking', "$value");
$response = $response->withHeader('Set-Cookie', $setcookies->toHeaders());
And for getting cookie :
$jwt = $request->getCookieParam('auth');
I'was experiencing the same problem but, after a few tries, i figured out!
First you need to use :
$cookies = Dflydev\FigCookies\Cookies::fromRequest($request);
To get all the cookies sent by the client.
Or:
$cookie = FigRequestCookies::get($request, $cookiename);
To get a single cookie.
But the 'strange' part is how to set a cookie, so here's a little example:
function setCookie($response, $name, $value){
$response = FigResponseCookies::set($response, SetCookie::create($name)
->withValue($value)
->rememberForever()
);
return $response;
}
With :
$response = FigResponseCookies::set($response, SetCookie::create($name)
->withValue($value)
->rememberForever()
);
You'll add a new cookie to the request, this method returns a new request object with the new cookie in it.
So for all the other operations, you need to use the new request not the old one.
I hope this will help.
if you want post your code and we'll try to debug it.
I know I was asked to answer for cookies on slim 3, but since I could not find anywhere how to do this on slim 4, I was telling how to do it in case it could be useful to someone else.
If you are using Slim 4 with slim/psr7 you can set cookies from inside a middleware or a router, in this way:
To SET a cookie (put a cookie on a browser):
$cookies = new \Slim\Psr7\Cookies();
$cookies->setDefaults(['hostonly' => true, 'secure' => true, 'httponly' => true, 'samesite' => 'Lax']);
$cookies->set('MyCookieName', ['value' => '', 'samesite' => 'Strict']); // this way I can ovveride the samesite attribute for this cookie only
$response=$response->withHeader('Set-Cookie', $cookies->toHeaders());
unset($cookies);
To unset a cookie (delete a cookie from a browser)
$cookies = new \Slim\Psr7\Cookies();
$cookies->setDefaults(['hostonly' => true, 'secure' => true, 'httponly' => true, 'samesite' => 'Lax']);
$cookies->set('MyCookieName', ['value' => '', 'expires' => 1); // this way I can delete this cookie, setting it already expired the first sec in 1970
$response=$response->withHeader('Set-Cookie', $cookies->toHeaders());
unset($cookies);
To get the cookie (get the cookie sent from the browser)
$cookies = new \Slim\Psr7\Cookies($request->getCookieParams());
echo "cookie value is: " . $cookies->get('MyCookieName');
The easiest way I found to do this is as follows.
use Dflydev\FigCookies\SetCookie;
use Dflydev\FigCookies\FigResponseCookies;
$app->post('/login', function ($request, $response, $args) {
// Here you may check request data
$token = '123'; // Here you may use something like JWT::encode
return $this->response = FigResponseCookies::set($response, SetCookie::create('token')
->withValue($token)
->withDomain($_SERVER['HTTP_HOST'])
->withPath('/')
)->withJson([
'description' => 'Here goes your Json Body'
]);
});
Install vendor solution:
composer require sunrise/http-header-kit
Set the session cookie:
use Sunrise\Http\Header\HeaderSetCookie;
$header = new HeaderSetCookie('name', 'value', new \DateTime('+1 day'), [
'path' => '/',
'secure' => true,
'httponly' => true,
]);
$response = $header->addToMessage($response);
See the source code to learn more:
HTTP Header Kit for PHP 7.2+ based on PSR-7
I would recommend NOT using dflydev/dflydev-fig-cookies. It's broken and the documentation is either wrong or missing.
Based on LUXS's and Norman's answers, here's a working example with comments, for Slim 3:
/**
* Fig-cookies.
*
* Mind the required classes; mind the fact that (because PSR-7) this sets the
* cookie by modifying the response before returning it.
*
* Kudos to https://stackoverflow.com/a/55288070/1717535 and
* https://stackoverflow.com/a/42065030/1717535 for providing working examples.
*
* Memo about cookines in general:
* - if you don't set an expire date, it'll be a session cookie.
* - dot or no dot before the domain?
* - if no domain is specified, the cookie will be set without a dot.
* - if a domain is specified, it'll be the dotted version.
* - if both are set, seems the one set more recently will be used on read.
* - Seems the dotted/sub-domains version comes recommended.
* - But it forces to turn https://example.org into example.org, for all
* of local dev, ngrok, production, for no obvious benefit. So screw it.
* - Reconsider the day we'll use subdomains.
* - See https://stackoverflow.com/a/39708227/1717535
*
* Can use `->withDomain` to set the domain, without URL scheme and without
* trailing slash. e.g.: `->withDomain('clickandspeak.localhost')`
*/
use Dflydev\FigCookies\FigResponseCookies;
use Dflydev\FigCookies\SetCookie;
use Dflydev\FigCookies\FigRequestCookies;
$app->get('/tests/fig-cookies/set/', function ($request, $response, $args) {
$response = FigResponseCookies::set(
$response,
SetCookie::create('foo')
->withValue('bar')
->rememberForever()
->withPath('/')
);
// Do whatever else you need to do in your route…
// Then return the response.
return $response;
});
$app->get('/tests/fig-cookies/get/', function ($request, $response, $args) {
$cookie = FigRequestCookies::get($request, 'foo');
// but this is long and ugly and I would recommend Slim's (undocumented) built-in function instead:
// $request->getCookieParam('foo')
echo $cookie->getValue();
});
As for deleting/removing a cookie… Well:
$app->get('/tests/fig-cookies/delete/', function ($request, $response, $args) {
// $request = FigRequestCookies::remove($request, 'foo');
// $response = FigResponseCookies::expire($response, 'foo');
// Works. The cookie gets deleted.
// $response = FigResponseCookies::set(
// $response,
// SetCookie::create('foo')
// ->withExpires(new DateTime('-5 years'))
// ->withPath('/') // MUST use the same path as that used when creating the cookie.
// );
/**
* This is the example given in the README. But it does NOT work.
* It won't work because the path is missing; there's no option to set it!
* See https://github.com/dflydev/dflydev-fig-cookies/issues/23
*/
// $response = FigResponseCookies::expire($response, 'foo');
return $response;
});
I don't know if it will help anyone 4 years later but...
You can use the FIG Cookies library, turning it into a class with static functions. Like this:
namespace YourApp\Cookies;
use Dflydev\FigCookies\FigResponseCookies;
use Dflydev\FigCookies\SetCookie;
use Dflydev\FigCookies\FigRequestCookies;
use Dflydev\FigCookies\Modifier\SameSite;
use Carbon\Carbon; // I used Carbon as well
class Cookie
{
static function get(&$req, $key, $default = null)
{
$cookie = FigRequestCookies::get($req, $key, $default);
if (!$cookie->getValue()) {
return null;
}
return $cookie->getValue();
}
static function set(&$res, $key, $val, $expire_val, $expire_unit)
{
$now = Carbon::now();
$offset = Carbon::now()->add($expire_val, $expire_unit);
$res = FigResponseCookies::set($res, SetCookie::create($key)
->withValue($val)
->withExpires($offset->toCookieString())
->withMaxAge($offset->diffInSeconds($now))
->withPath('/')
->withDomain('appdomain.com')
->withSecure(false)
->withHttpOnly(true)
->withSameSite(SameSite::lax())
// You can learn more about the available options on the official GitHub page
);
return $res;
}
static function remove(&$res, $key)
{
$offset = Carbon::now()->sub(10, 'years');
$res = FigResponseCookies::set($res, SetCookie::create($key)
->withExpires($offset->toCookieString())
->withMaxAge(0)
->withPath('/')
->withDomain('appdomain.com')
);
return $res;
}
}
This way, it becomes really easy to deal with cookies.
You can use it like this:
use YourApp\Cookies\Cookie;
Cookie::set($response, 'name', 'value', 1, 'month') // To create a cookie
Cookie::get($request, 'name') // To get the value of a cookie
Cookie::remove($response, 'name') // To remove it
Or, if you prefer, like this:
\YourApp\Cookies\Cookie::set($response, 'name', 'value', 1, 'month')
\YourApp\Cookies\Cookie::get($request, 'name')
\YourApp\Cookies\Cookie::remove($response, 'name')
That's the way I use it.

Categories