diff options
author | Thomas Steur <tsteur@users.noreply.github.com> | 2020-11-17 23:48:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-17 23:48:06 +0300 |
commit | cd6708f25006a00b20073a918d8dc2253dbd376f (patch) | |
tree | 5b1bef147bff9f1d736056893eadf3cc19095cdc /js/piwik.js | |
parent | 4556360d90e6d5d3e5b6898e14604082a0ee13f4 (diff) |
SameSite cookie attribute can be configured for JS tracker (#16733)
Diffstat (limited to 'js/piwik.js')
-rw-r--r-- | js/piwik.js | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/js/piwik.js b/js/piwik.js index 6de86493a1..806d5fa460 100644 --- a/js/piwik.js +++ b/js/piwik.js @@ -107,6 +107,7 @@ isNodeAuthorizedToTriggerInteraction, getConfigDownloadExtensions, disableLinkTracking, substr, setAnyAttribute, max, abs, childNodes, compareDocumentPosition, body, getConfigVisitorCookieTimeout, getRemainingVisitorCookieTimeout, getDomains, getConfigCookiePath, + getConfigCookieSameSite, setCookieSameSite, getConfigIdPageView, newVisitor, uuid, createTs, currentVisitTs, "", "\b", "\t", "\n", "\f", "\r", "\"", "\\", apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, lastIndex, length, parse, prototype, push, replace, @@ -2268,6 +2269,9 @@ if (typeof window.Matomo !== 'object') { // Whether to use "Secure" cookies that only work over SSL configCookieIsSecure = false, + // Set SameSite attribute for cookies + configCookieSameSite = 'Lax', + // First-party cookies are disabled configCookiesDisabled = false, @@ -2397,7 +2401,7 @@ if (typeof window.Matomo !== 'object') { /* * Set cookie value */ - function setCookie(cookieName, value, msToExpire, path, domain, isSecure) { + function setCookie(cookieName, value, msToExpire, path, domain, isSecure, sameSite) { if (configCookiesDisabled && cookieName !== CONSENT_REMOVED_COOKIE_NAME) { return; } @@ -2410,12 +2414,16 @@ if (typeof window.Matomo !== 'object') { expiryDate.setTime(expiryDate.getTime() + msToExpire); } + if (!sameSite) { + sameSite = 'Lax'; + } + documentAlias.cookie = cookieName + '=' + encodeWrapper(value) + (msToExpire ? ';expires=' + expiryDate.toGMTString() : '') + ';path=' + (path || '/') + (domain ? ';domain=' + domain : '') + (isSecure ? ';secure' : '') + - ';SameSite=Lax'; + ';SameSite=' + sameSite; } /* @@ -3033,7 +3041,7 @@ if (typeof window.Matomo !== 'object') { // for IE we want to actually set the cookie to avoid trigger a warning eg in IE see #11507 var testCookieName = configCookieNamePrefix + 'testcookie'; - setCookie(testCookieName, '1', undefined, configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(testCookieName, '1', undefined, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); var hasCookie = getCookie(testCookieName) === '1' ? '1' : '0'; deleteCookie(testCookieName); @@ -3334,7 +3342,7 @@ if (typeof window.Matomo !== 'object') { var cookieValue = visitorIdCookieValues.uuid + '.' + visitorIdCookieValues.createTs + '.'; - setCookie(getCookieName('id'), cookieValue, getRemainingVisitorCookieTimeout(), configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(getCookieName('id'), cookieValue, getRemainingVisitorCookieTimeout(), configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); } /* @@ -3374,7 +3382,7 @@ if (typeof window.Matomo !== 'object') { function isPossibleToSetCookieOnDomain(domainToTest) { var valueToSet = 'testvalue'; - setCookie('test', valueToSet, 10000, null, domainToTest); + setCookie('test', valueToSet, 10000, null, domainToTest, configCookieIsSecure, configCookieSameSite); if (getCookie('test') === valueToSet) { deleteCookie('test', null, domainToTest); @@ -3438,7 +3446,7 @@ if (typeof window.Matomo !== 'object') { * Creates the session cookie */ function setSessionCookie() { - setCookie(getCookieName('ses'), '1', configSessionCookieTimeout, configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(getCookieName('ses'), '1', configSessionCookieTimeout, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); } function generateUniqueId() { @@ -3624,7 +3632,7 @@ if (typeof window.Matomo !== 'object') { purify(referralUrl.slice(0, referralUrlMaxLength)) ]; - setCookie(cookieReferrerName, windowAlias.JSON.stringify(attributionCookie), configReferralCookieTimeout, configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(cookieReferrerName, windowAlias.JSON.stringify(attributionCookie), configReferralCookieTimeout, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); } } @@ -3725,7 +3733,7 @@ if (typeof window.Matomo !== 'object') { } if (configStoreCustomVariablesInCookie) { - setCookie(cookieCustomVariablesName, windowAlias.JSON.stringify(customVariables), configSessionCookieTimeout, configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(cookieCustomVariablesName, windowAlias.JSON.stringify(customVariables), configSessionCookieTimeout, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); } } @@ -4862,6 +4870,9 @@ if (typeof window.Matomo !== 'object') { this.getConfigVisitorCookieTimeout = function () { return configVisitorCookieTimeout; }; + this.getConfigCookieSameSite = function () { + return configCookieSameSite; + }; this.removeAllAsyncTrackersButFirst = function () { var firstTracker = asyncTrackers[0]; asyncTrackers = [firstTracker]; @@ -5665,7 +5676,7 @@ if (typeof window.Matomo !== 'object') { configCookiesToDelete.push(cookieName); - setCookie(getCookieName(cookieName), cookieValue, msToExpire, configCookiePath, configCookieDomain); + setCookie(getCookieName(cookieName), cookieValue, msToExpire, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); }; /** @@ -5756,13 +5767,51 @@ if (typeof window.Matomo !== 'object') { * This should be used when your website is only available under HTTPS * so that all tracking cookies are always sent over secure connection. * + * Warning: If your site is available under http and https, + * setting this might lead to duplicate or incomplete visits. + * * @param bool */ this.setSecureCookie = function (enable) { + if(enable && location.protocol !== 'https:') { + logConsoleError("Error in setSecureCookie: You cannot use `Secure` on http."); + return; + } configCookieIsSecure = enable; }; /** + * Set the SameSite attribute for cookies to a custom value. + * You might want to use this if your site is running in an iframe since + * then it will only be able to access the cookies if SameSite is set to 'None'. + * + * + * Warning: + * Sets CookieIsSecure to true on None, because None will only work with Secure; cookies + * If your site is available under http and https, + * using "None" might lead to duplicate or incomplete visits. + * + * @param string either Lax, None or Strict + */ + this.setCookieSameSite = function (sameSite) { + sameSite = String(sameSite); + sameSite = sameSite.charAt(0).toUpperCase() + sameSite.toLowerCase().slice(1); + if (sameSite !== 'None' && sameSite !== 'Lax' && sameSite !== 'Strict') { + logConsoleError('Ignored value for sameSite. Please use either Lax, None, or Strict.'); + return; + } + if (sameSite === 'None') { + if (location.protocol === 'https:') { + this.setSecureCookie(true); + } else { + logConsoleError('sameSite=None cannot be used on http, reverted to sameSite=Lax.'); + sameSite = 'Lax'; + } + } + configCookieSameSite = sameSite; + }; + + /** * Disables all cookies from being set * * Existing cookies will be deleted on the next call to track @@ -5881,7 +5930,7 @@ if (typeof window.Matomo !== 'object') { } this.setCookieConsentGiven(); var now = new Date().getTime(); - setCookie(COOKIE_CONSENT_COOKIE_NAME, now, hoursToExpire, configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(COOKIE_CONSENT_COOKIE_NAME, now, hoursToExpire, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); }; /** @@ -6764,7 +6813,7 @@ if (typeof window.Matomo !== 'object') { // cookies should be automatically enabled or not. this.setConsentGiven(setCookieConsent); var now = new Date().getTime(); - setCookie(CONSENT_COOKIE_NAME, now, hoursToExpire, configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(CONSENT_COOKIE_NAME, now, hoursToExpire, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); }; /** @@ -6777,7 +6826,7 @@ if (typeof window.Matomo !== 'object') { var thirtyYears = 30 * 365 * 24 * 60 * 60 * 1000; deleteCookie(CONSENT_COOKIE_NAME, configCookiePath, configCookieDomain); - setCookie(CONSENT_REMOVED_COOKIE_NAME, new Date().getTime(), thirtyYears, configCookiePath, configCookieDomain, configCookieIsSecure); + setCookie(CONSENT_REMOVED_COOKIE_NAME, new Date().getTime(), thirtyYears, configCookiePath, configCookieDomain, configCookieIsSecure, configCookieSameSite); this.forgetCookieConsentGiven(); this.requireConsent(); }; @@ -6866,7 +6915,7 @@ if (typeof window.Matomo !== 'object') { * Constructor ************************************************************/ - var applyFirst = ['addTracker', 'forgetCookieConsentGiven', 'requireCookieConsent', 'disableCookies', 'setTrackerUrl', 'setAPIUrl', 'enableCrossDomainLinking', 'setCrossDomainLinkingTimeout', 'setSessionCookieTimeout', 'setVisitorCookieTimeout', 'setCookieNamePrefix', 'setSecureCookie', 'setCookiePath', 'setCookieDomain', 'setDomains', 'setUserId', 'setVisitorId', 'setSiteId', 'alwaysUseSendBeacon', 'enableLinkTracking', 'setCookieConsentGiven', 'requireConsent', 'setConsentGiven']; + var applyFirst = ['addTracker', 'forgetCookieConsentGiven', 'requireCookieConsent', 'disableCookies', 'setTrackerUrl', 'setAPIUrl', 'enableCrossDomainLinking', 'setCrossDomainLinkingTimeout', 'setSessionCookieTimeout', 'setVisitorCookieTimeout', 'setCookieNamePrefix', 'setCookieSameSite', 'setSecureCookie', 'setCookiePath', 'setCookieDomain', 'setDomains', 'setUserId', 'setVisitorId', 'setSiteId', 'alwaysUseSendBeacon', 'enableLinkTracking', 'setCookieConsentGiven', 'requireConsent', 'setConsentGiven']; function createFirstTracker(matomoUrl, siteId) { |