Symfony 3.2, authentification and cross-site cookies - symfony

I know that Symfony 3.2 is not maintained for very long time, but it happens that my company use it.
And now we have a problem with authentifacation. We have widget that can be (and is) installed on multiple sites, so user can log in there. But database and backend code in Symfony 3.2 is stored in our site. And for authentification we use standard Symfony cookies, which are in our case cross-site.
But now Google Chrome is restricted access to cross-domain cookies which are not marked as SameSite=None. So authentification in Chrome doesn't work anymore.
I know that in Symfony 4.2 I can solve this problem by setting security parameter in security.yaml. But in Symfony 3.2 it doesn't work.
Is there any way to solve this problem except for upgrade to Symfony 4?

From https://github.com/GoogleChromeLabs/samesite-examples/blob/master/php.md
As of PHP 7.3.0 the
setcookie() method
supports the SameSite attribute in its options and will accept None as a
valid value.
// Set a same-site cookie for first-party contexts
setcookie('cookie1', 'value1', ['samesite' => 'Lax']);
// Set a cross-site cookie for third-party contexts
setcookie('cookie2', 'value2', ['samesite' => 'None', 'secure' => true]);
For earlier versions of PHP, you can also set the
header() directly:
// Set a same-site cookie for first-party contexts
header('Set-Cookie: cookie1=value1; SameSite=Lax', false);
// Set a cross-site cookie for third-party contexts
header('Set-Cookie: cookie2=value2; SameSite=None; Secure', false);
For Session Cookie , you can set into session_set_cookie_params method.
PHP 7.3.0 introduced new attributes for samesite.
if (PHP_VERSION_ID >= 70300) {
session_set_cookie_params([
'lifetime' => $cookie_timeout,
'path' => '/',
'domain' => $cookie_domain,
'secure' => $session_secure,
'httponly' => $cookie_httponly,
'samesite' => 'Lax'
]);
} else {
session_set_cookie_params(
$cookie_timeout,
'/; samesite=Lax',
$cookie_domain,
$session_secure,
$cookie_httponly
);
}
There are third-party packages, such as delight-im/PHP-Cookie, which supports the SameSite attribute and the None value (since v3.2) on PHP 5.4.0+.

Related

DDEV and D8, httpClient used for internal request fails to connect

I've a multisite installation of Drupal 8, the "main" website expose some REST webservices, locally i've some troubles on testing them, because there's no way for the various sites to see each other, when i try to do something like that
try {
$response = $this->httpClient->get($this->baseUri . '/myendpoint', [
'headers' => [
'Accept' => 'application/json',
'Content-type' => 'application/hal+json',
],
'query' => [
'_format' => 'json',
'myparameters' => 'value'
],
]);
$results = $this->serializer->decode($response->getBody(), 'json');
}
catch (RequestException $e) {
$this->logger->warning($e->getMessage());
}
return $results;
I always receive a timeout and there's no way i can make it work, i've my main website with the usual url project.ddev.site (and $this->baseUri is https://myproject.ddev.site ) and all the other websites are in the form subsite.ddev.local
If i ssh in the project and run ping myproject.ddev.site i see 172.19.0.6
I don't understand why they cannot see each other...
Just for other people who can have a similar problem: my issue was with xdebug i have it with the autoconnect, so when the request from the subsite to the main site was made, it get stuck somewhere (phpstorm didn't stop anywhere by the way) so it made the request time out.
By disabling, or configuring only for the subdomain, and avoiding it to accept the external connenction from unconfigured servers (in phpstorm) it started working, still have to do some work as i need to debug "both sides" of the request, but in this way i can work with that...
I've not thought before to try disabling xdebug because actually it didn't came into my mind...

How to set SameSite=none in drupal setcookie function

If there any hook or alter that which is used to add "SameSite=none" parameter in set cookies in drupal 7.
This one is kind of tricky, since PHP 5 does not have a flag for SameSite:None; Secure; when using setcookie() or setrawcookie(). PHP 7 does, however since these functions don't escape semicolons, we can add it to the 'domain' flag and it will get set...
Important: this hack WILL BREAK in PHP 7.3. If you're going to use it, at least wrap it in a PHP version check like if (PHP_VERSION_ID < 70300) { ... } else { ... }
setrawcookie('cookie_name', 'cookie_value', time() + 7700, '/', 'example.com; SameSite=none;');
For earlier versions of PHP, you can set the header() directly:
header('Set-Cookie: cookie_name=cookie_value; SameSite=None;');
As of PHP 7.3.0 the setcookie() method supports the SameSite attribute in its options and will accept None as a valid value. See https://www.php.net/manual/en/function.setcookie.php
setcookie($name, $value, [
'expires' => time() + 86400,
'path' => '/',
'secure' => true,
'samesite' => 'None',
]);

How to get Google refresh token with knpuniversity/oauth2-client-bundle?

I use knpuniversity/oauth2-client-bundle and league/oauth2-google to connect users in my Symfony 4 web app using a "Sign in with Google" feature. I followed this tuto. I registered my app in Google.
I set access_type: offline in the knpu.oauth2.client.google configuration (config/packages/knpu_oauth2_client.yaml file)
I try to get the user refresh token in my GoogleAuthenticator::getUser(League\OAuth2\Client\Token\AccessToken $credentials) method (which extends KnpU\OAuth2ClientBundle\Security\Authenticator\SocialAuthenticator).
Unfortunately, $credentials->getRefreshToken() always returns null.
Why don't I get the user refresh token ?
As per documentation, "Refresh tokens are only provided to applications which request offline access". So, when instantiating the provider you need to set the accessType.
use League\OAuth2\Client\Provider\Google;
$provider = new Google([
'clientId' => '{google-client-id}',
'clientSecret' => '{google-client-secret}',
'redirectUri' => 'https://example.com/callback-url',
'accessType' => 'offline',
]);
In knpu_oauth2_client configuration, you can do:
google:
type: google
client_id: '%env(OAUTH_GOOGLE_CLIENT_ID)%'
client_secret: '%env(OAUTH_GOOGLE_CLIENT_SECRET)%'
redirect_params: {}
access_type: offline

Using a single Cloudflare account in Wordpress with WP Super Cache with visible API key

We are starting to use Cloudflare on a few Wordpress client accounts and notice in the CDN settings that my email address and API key are visible to the client.
Is this a potential security issues where others can see my Cloudlflare email address and API key? Should I be using 1 Cloudflare account per client account?
Here is a screenshot (i have blurred the API key and deleted the email input box in the console) but both these values are visible to the customer.
What is the worse thing they could do with these 2 pieces of data?
you have to use tokens instead of global api key. you strict token to certain zone only
This only will NOT solve the problem, you have to manually modify wp fastest cache plugin to modify the request to match API tokens usage.
the requests can be found in inc\cdn.php
The modified file:
https://gist.github.com/ahmed-abdelazim/7c8170f7fc4e821c6b015d770fcbf14a
so
$header = array("method" => "DELETE",
'headers' => array(
"X-Auth-Email" => $email,
"X-Auth-Key" => $key,
"Content-Type" => "application/json"
),
"body" => '{"purge_everything":true}'
);
is converted to
$header = array("method" => "DELETE",
'headers' => array(
//"X-Auth-Email" => $email,
"Authorization" => "Bearer ".$key,
"Content-Type" => "application/json"
),
"body" => '{"purge_everything":true}'
);
and this occured five times in the plugin in the cdn.php file
simply creating API Token worked for me. There are some pre made template. There was for wordpress one as well. Just selected and created and added it to wp fastest cache and that worked.

Silex translation stops working when validation is registered

I registered TranslationServiceProvider with YAML and it works fine:
$app->register(new TranslationServiceProvider(), array(
'locale_fallback' => 'ru',
));
$app['translator'] = $app->share($app->extend('translator', function($translator, $app) {
$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource('yaml', CONTENT_PATH . '/locales/en.yml', 'en');
return $translator;
}));
Then I register ValidationServiceProvider like this:
$app->register(new Silex\Provider\ValidatorServiceProvider());
When I register Validation, Translation stops working. All strings that should be translated don't get translated with no errors.
I am changing locale in the countroller, so it might have something to do with it:
$en->get('/{slug}', function (Silex\Application $app, $slug) {
$app['locale'] = 'en';
So, all services (from service providers) get locales in runtime, before request, in create process. And, if real locale not presented, translator gets the fallback locale.
Problem: you can not change locale in runtime, because locale is a variable and not presented as link (if locale will be object, you can change locale).
Solution: Change/Set locale on request subscriber.

Resources