How do cookie consent pop-ups work internally? - javascript

My project is linked with Google Analytics. Now I would like to create a cookie consent pop-up on my website to comply with EU regulations.
Now I see in the EU regulations that the user can select "allow" or "deny". And then you can anonymize Google Analytics. But how does this work internally in my code?
I don't really know how this all works in code, does anyone have examples?
On the internet you will find a lot about how to create the pop-up, but they never go further on how to code everything internally.

Cookies are files at are stored on your computer that the website can access, 3rd party cookies are cookies that other websites can access too. The most basic way of creating a cookie is by using the browsers local storage. Your allow/deny system can be as simple as a true/false value stored globally, use an if statement to check if cookies are allowed or not every time you get or store a value from local storage.
Here are some examples.
// This will store a value/cookie with the id "myKey" and the value "myValue"
Window.localStorage.setItem("myKey", "myValue");
// You can get the value/cookie you stored earlier by using the values ID, in this case it should return "myValue"
Window.localStorage.getItem("myKey");
// To delete a value/cookie do this
Window.localStorage.remove("myKey");
// this is your logic to check if cookies are allowed
let AreCookiesAllowed = true;
if (AreCookiesAllowed === true)
{
// Do things with cookies
Window.localStorage.setItem("theme", "dark");
}
Reference material can be found here.

Related

Google oauth session lost after page reload (javascript)

I recently moved from the deprecated gapi.auth2 to the new Google Identity Services, using the javascript client library, and noticed a big difference: if someone signs in, and then reloads the page, the session is lost, and has to sign in again, every time the page is loaded. This was not the case with the deprecated library.
The problem can be easily reproduced with the Calendar API example.
Is there any configuration option to keep the session persistent? Or do I need to store the access tokens somehow? I could not find anything relevant in the official docs.
UPDATE:
The migration guide states the following:
Previously, Google Sign-In helped you to manage user signed-in status using:
Callback handlers for Monitoring the user's session state.
Listeners for events and changes to signed-in status for a user's Google Account.
You are responsible for managing sign-in state and user sessions to your web app.
However there's absolutely no information on what needs to be done.
UPDATE 2
To be more specific, the actual issue is not making the session persistent. Managing the sign in state and user session is something I can solve.
The real problem is the access token used to call the Google APIs.
As mentioned in the comments, the access tokens are 1) short lived 2) are not stored anywhere, so even if not expired, they do not persist between page reloads.
Google provides the requestAccessToken method for this, however even if I specify prompt: '', it opens the sign-in popup. If I also specify the hint option with the signed in user's email address, than the popup opens, displays a loading animation briefly, and closes without user interaction. I could live with this, however this only works if triggered by a user interaction, otherwise the browser blocks the popup window, meaning that I cannot renew the token without user interaction, e.g. on page load. Any tips to solve this?
I faced all the same issues you described in your question.
In order to help:
Google 3P Authorization JavaScript Library: in this link we can check all the methods the new library has (it does not refresh token, etc..)
This doc says the library won't control the cookies to keep the state anymore.
Solution
Firstly I need to thanks #Sam O'Riil answer.
As Sam described: "you can somehow save access token and use it to speed-up things after page reload."
Given the the Google's exampe, we should call initTokenClient in order to configure the Google Auth and the requestAccessToken to popup the auth:
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: tokenCallback
});
tokenClient.requestAccessToken({prompt: ''})
In your tokenCallback you can save the credentials you get somehow, e.g.:
const tokenCallback(credentials) => {
// save here the credentials using localStorage or cookies or whatever you want to.
}
Finally, when you restart/reload your application and you initialize the gapi.server again, you only need to get the credentials again and set token to gapi, like:
gapi.load('client', function() {
gapi.client.init({}).then(function() {
let credentials = // get your credentials from where you saved it
credentials = JSON.parse(credentials); // parse it if you got it as string
gapi.client.setToken(credentials);
... continue you app ...
}).catch(function(err) {
// do catch...
});
});
Doing it, your application will work after the reload. I know it could not be the best solution, but seeing what you have and the library offers, I think that's you can do.
p.s.: the token expires after 1 hour and there is no refresh token (using the implicit flow) so, you will have to ask the user to sign-in again.

Can you prevent users editing the chrome.storage.local values in a Chrome extension? What is the best way to store persistent values for an extension?

So I'm working on a Chrome extension for someone else. I don't want to give away specific details about the project, so for I'll use an equivalent example: let's assume it's an extension to run on an image/forum board. Imagine I have variables such as userPoints, isBanned etc. The later being fairly self-explanatory, while the former corresponding to points the user acquires as they perform certain actions, hence unlocking additional features etc
Let's imagine I have code like:
if(accountType !== "banned"){
if(userPoints > 10000) accountType = "gold";
else if(userPoints > 5000) accountType = "silver";
else if(userPoints > 2500) accountType = "bronze";
else if(userPoints <= 0) accountType = "banned";
else accountType = "standard";
}else{
alert("Sorry, you're banned");
stopExtension();
}
Obviously though, it becomes trivial for someone with the knowledge to just browse to the extensions background page and paste chrome.storage.local.set({'userPoints': 99999999}) in the console, hence giving them full access to all the site. And, with the Internet, someone can of course share this 'hack' on Twitter/YouTube/forums or whatever, then suddenly, since all they'd need to do is copy and paste a simple one-liner, you can have 1000s of people, even with no programming experience, all using a compromised version of your extension.
And I realise I could use a database on an external site, but realistically, it would be possible that I would be wanting to get/update these variables such as userPoints 200+ times per hour, if the user was browsing the extentions target site the entire time. So the main issues I have with using an external db are:
efficiency: realistically, I don't want every user to be querying the
db 200+ times per hour
ease-of-getting-started: I want the user to just download the
extension and go. I certainly don't want them to have to sign up. I
realise I could create a non-expiring cookie with for the user's ID
which would be used to access their data in the db, but I don't want
to do that, since users can e.g. clear all cookies etc
by default, I want all features to be disabled (i.e. effectively
being considered like a 'banned' user) - if, for some reason, the
connection with the db on my site fails, then the user wouldn't be
able to use the extension, which I wouldn't want (and just speaking
from experience of my parents being with Internet providers whose
connection could drop 10 times per hour, for some people, failed
connections could be a real issue) - in contrast, accessing data from
the local storage will have like a 99.999% success rate I'd assume,
so, for non-critical extensions like what I'm creating, that's more
than good enough
Still, at least from what I've found searching, I've not found any Chrome storage method that doesn't also allow the user to edit the values too. I would have thought there would be a storage method (or at least option with chrome.storage.local.set(...) to specify that the value could only be accessed from within the extension's context pages, but I've not found that option, at least.
Currently I'm thinking of encrypting the value to increment by, then obfuscating the code using a tool like obfuscator.io. With that, I can make a simple, like 30 character js file such as this
userPoints = userPoints + 1000;
become about 80,000...still, among all the junk, if you have the patience to scroll through the nonsense, it's still possible to find what you're looking for:
...[loads of code](_0x241f5c);}}}});_0x5eacdc(),***u=u+parseInt(decrypt('\u2300\u6340'))***;function _0x34ff36(_0x17398d)[loads more code]...
[note that, since it's an extension and the js files will be stored on the user's pc, things like file size/loading times of getting the js files from a server are irrelevant]
Hence meaning a user wouldn't be able to do something like chrome.storage.local.set({'userPoints': 99999999}), they'd instead have to set it to the encrypted version of a number - say, something like chrome.storage.local.set({'userPoints': "✀ເ찀삌ሀ"}) - this is better, but obviously, by no means secure.
So anyway, back to the original question: is there a way to store persistent values for a Chrome extension without the user being able to edit them?
Thanks

Safari on iOS>=11 block cookies & web storage by default - how to persist (first-party) data?

On our app, we show a very simple "onboarding" message for users on their first visit.
We rely on localStorage and when it is not supported fallback on cookies using github.com/Acanguven/StorageService. This data is first party as it's our cookies and they're set for our website. Nothing like adtech or cross-domain cookies/storage: for example just a simple way to not show onboarding modal to users who already visited the website.
The thing is on my iphone it does not work and we get some javascript "Security Error or Access denied" when we try to create those cookies/local storage.
For example one of our data is like this:
if ( (window.StorageService.localStorage.getItem('user_already_saw_the_message') !== null) ) {
showMessage():
}
// If user never saw the message, show 1st msg almost immediately
else {
//do nothing
}
}
I checked my iphone and indeed it says in Apps>Safari that the line block All cookies is activated/"ON". so it blocks even first party cookies (nothing like cross-domain or some advertising cookies).
So my question has two sub-components:
To assess how large/significant the issue is on the userbase: is it just my iphone or do all iphone users who upgraded to iOS11 and soon will upgrade to iOS12 automatically get the default setting of "all cookies blocked = "ON" ?
If question 1's answer is "yes all users by default get this all cookies blocked setting", that makes the following question even more crucial as it means, given the market share of iOS, that it affects a tremendous number of users: how do you just persist data like "only show this message once" or "only show this modal once every month" if we can't use cookies nor local/session Storage ?
I did some reading and found this:
iOS11 does introduce a cookie storing prevention mechanism called
Intelligent Tracking Prevention but that affects only 3rd party
cookies. On iOs11, the default setting for Managing Cookies is Allow
cookies from current websites i.e. First party cookies.
So your application should not have a problem.
It should work fine. Reference: https://webkit.org/blog/7675/intelligent-tracking-prevention

Browser addon to automatically opt-in for cookies - EU cookie law

In EU we have this law that requires web pages to request permission to store cookies. Most of us know about cookies and agree to them but still are forced to accept them explicitly everywhere. So I plan to write this add on (ff & chrome) that will automatically add session cookie with standard name that would mean agreement. Just wondering about few things:
1) What should be the name of the cookie? What should be the value? Should I cover only user agreement option? My proposition is
_cookieok=1
the benefit is that it is short, yet descriptive.
2) Should I add only single cookie - the one I suggested above? Many pages do it in different ways already. They use different cookie names and check for different values. I thought maybe use names and values from popular scripts like http://cookiecuttr.com/ but I don't want to increase upload traffic with a number of mostly not needed cookies.
3) Should I differentiate between types of cookies? I have seen here http://demo.cookieconsent.silktide.com/ there are multiple cookie types you can opt-in/opt-out?
4) Does this have chances to become popular or is it better to use something like point 2 - adding multiple values manually?
5) I could probably also remove those cookies after some event (like after all js onload functions have finished) but I could not find proper hook in firefox addons. Plus maybe some people would like to do filtering out of the script on server side so maybe it is better to keep sending the cookie.
Is there something I have not thought about? My suggested code is in case of FF:
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "*",
contentScriptWhen: 'start',
contentScript: 'document.cookie="_cookieok=1;path=/";'
});
Update
To explain how does it work
1) Most sites already compliant to cookie law do something like this:
if ($.cookie('_cookieok') == null) {
$('#cookie-close').on('click', function (evt) {
$.cookie('cookieok', 1, 300);
});
$('.cookie-prompt').show();
}
so if we agree on same name existance of such ff plugin would be possible. If someone does not plugin - site will prompt him. If has site would recognize addon added cookie as their own.
Not too sure what the point of this really is to be honest?
If you're looking to build something that would be used across a portfolio of sites you manage, then you're probably pushing your luck to force a user to install an extension simply to show they accept your cookies. If it's aimed at a wider audience, i.e. potentially anyone using any website, then the other issue you'll have is getting both users to see the benefit of installing another extension and secondly website operators to write the code necessary to detect your cookie and act accordingly.
Most sites seem to be striving to make cookies and the associated obligations under the legislation as unintrusive as possible - requiring installation of an extension & changes to website code seems to be heading in the opposite direction..

Unique flash ID per computer

I have created an online multiplayer card game using Adobe flash Professional. In this game multiple clients/account is not allowed, hence I need to detect whether the users are joining game from different devices or not. I can't simply do a server sided check for the IP-address because I still want e.g. people in the same office to be able to play together.
I have found some solution like reading the MAC address (Here) but the problem is that NetworkInfo.networkInfo.findInterfaces() works only on Adobe air, which is not my case.
Another solution could be using browser cookies, but the problem of this solution is that, the users can use e.g. Chrome and Firefox on the same computer.
As this a web game, using js could be also a solution, so I tag this question as js as well.
UPDATE
Using SharedObject does not work in this case, since google chrome uses its own storage.
Any suggestion will be appreciated.
Instead browser cookies you can use "flash cookies" - SharedObject. It is really simple and have mechanic similar to browser cookies, but stored in flash local storage.
UPDATE
Example:
var mySo:SharedObject = SharedObject.getLocal("host"); // get saved SO with name "host" if exists or create new if doesn't exist
mySo.data = {someProperty: "someData"}; // writing some data
var flushResult:Object = mySo.flush(); // saving data in local storage
...
var savedSO:SharedObject = SharedObject.getLocal("host");
trace(savedSO.data.someProperty); // output: someData

Categories

Resources