Skip to content

Commit

Permalink
Third party cookie check (SAP#970)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesDoberer authored Nov 28, 2019
1 parent 8088cb7 commit 664cba0
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 19 deletions.
37 changes: 36 additions & 1 deletion client/src/lifecycleManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ class LifecycleManager extends LuigiClientBase {
this._notifyUpdate();
helpers.sendPostMessageToLuigiCore({ msg: 'luigi.navigate.ok' });
});

/**
* Get context once initially
* @private
Expand All @@ -101,6 +100,42 @@ class LifecycleManager extends LuigiClientBase {
},
'*'
);
let tpc = 'enabled';
let cookies = document.cookie;
let luigiCookie;
let luigiCookieKey;
if (cookies) {
luigiCookie = cookies
.split(';')
.map(cookie => cookie.trim())
.find(cookie => cookie == 'luigiCookie=true');
}
if (luigiCookie === 'luigiCookie=true') {
luigiCookieKey = luigiCookie.split('=')[0];
document.cookie = luigiCookieKey + '=; Max-Age=-99999999;';
}
document.cookie = 'luigiCookie=true';
cookies = document.cookie;
if (cookies) {
luigiCookie = cookies
.split(';')
.map(cookie => cookie.trim())
.find(cookie => cookie == 'luigiCookie=true');
}
if (luigiCookie === 'luigiCookie=true') {
window.parent.postMessage(
{ msg: 'luigi.third-party-cookie', tpc },
'*'
);
document.cookie = luigiCookieKey + '=; Max-Age=-99999999;';
} else {
tpc = 'disabled';
window.parent.postMessage(
{ msg: 'luigi.third-party-cookie', tpc },
'*'
);
console.warn('Third party cookies are not supported!');
}
};

luigiClientInit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ class Settings {
};
responsiveNavigation = 'simpleMobileOnly'; // Options: simple | simpleMobileOnly | semiCollapsible
sideNavFooterText = `Luigi Client: ${version || 'unknown'}`;
thirdPartyCookieCheck = {
thirdPartyCookieDetection: true,
// thirdPartyCookieScriptLocation: 'https://domain/init.html',
thirdPartyCookieErrorHandling: () => {
const alert = {
text:
'Third Party Cookies are not enabled. Please check your browser settings.',
type: 'warning'
};
Luigi.ux().showAlert(alert);
}
};
// allowRules = ['microphone'];
// iframeCreationInterceptor = (iframe, viewGroup, navigationNode, microFrontendType) => { };
// hideNavigation = true
Expand Down
51 changes: 48 additions & 3 deletions core/src/App.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
import { SplitViewSvc } from './services/split-view';
import { ViewGroupPreloading } from './services/preloading';
import { MessagesListeners } from './services/messages-listeners';
import { thirdPartyCookiesStatus } from './utilities/third-party-cookies-check.js';

const dispatch = createEventDispatcher();

Expand Down Expand Up @@ -143,6 +144,7 @@
let responsiveNavSetting;
let tabNav;
let resizeTabNavToggle = false;
let thirdPartyCookiesCheck;

const prepareInternalData = config => {
const internalData = {
Expand Down Expand Up @@ -504,9 +506,7 @@
getAlertWithId(currentAlerts, settings.id)
) {
console.error(
`The alert with id '${
settings.id
}' already exists in a queue, therefore it won't be displayed `
`The alert with id '${settings.id}' already exists in a queue, therefore it won't be displayed `
);
return Promise.reject();
}
Expand Down Expand Up @@ -960,6 +960,15 @@
);
}
}
if (
thirdPartyCookiesCheck &&
!thirdPartyCookiesCheck.thirdPartyCookieScriptLocation &&
'luigi.third-party-cookie' === e.data.msg
) {
if (e.data.tpc === 'disabled') {
tpcErrorHandling(thirdPartyCookiesCheck);
}
}
});

// listeners are not automatically removed — cancel
Expand All @@ -971,6 +980,18 @@
setContext('store', store);
setContext('getTranslation', getTranslation);

const tpcErrorHandling = thirdpartycookiecheck => {
if (
thirdPartyCookiesCheck &&
thirdPartyCookiesCheck.thirdPartyCookieErrorHandling &&
GenericHelpers.isFunction(
thirdPartyCookiesCheck.thirdPartyCookieErrorHandling
)
) {
thirdPartyCookiesCheck.thirdPartyCookieErrorHandling();
}
};

onMount(() => {
responsiveNavSetting = LuigiConfig.getConfigValue(
'settings.responsiveNavigation'
Expand All @@ -985,6 +1006,30 @@
} else if (responsiveNavSetting === 'semiCollapsible') {
document.body.classList.add('lui-semiCollapsible');
}
thirdPartyCookiesCheck = LuigiConfig.getConfigValue(
'settings.thirdPartyCookieCheck'
);
if (
thirdPartyCookiesCheck &&
thirdPartyCookiesCheck.thirdPartyCookieScriptLocation
) {
setTimeout(() => {
let thirdPartyCookieCheckIframe = document.createElement('iframe');
thirdPartyCookieCheckIframe.width = '0px';
thirdPartyCookieCheckIframe.height = '0px';
thirdPartyCookieCheckIframe.src =
thirdPartyCookiesCheck.thirdPartyCookieScriptLocation;
document.body.appendChild(thirdPartyCookieCheckIframe);
thirdPartyCookieCheckIframe.onload = function() {
setTimeout(() => {
if (thirdPartyCookiesStatus() === 'disabled') {
tpcErrorHandling(thirdPartyCookiesCheck);
}
});
document.body.removeChild(thirdPartyCookieCheckIframe);
};
});
}
});

afterUpdate(() => {});
Expand Down
10 changes: 0 additions & 10 deletions core/third-party-cookies/complete.html

This file was deleted.

34 changes: 30 additions & 4 deletions core/third-party-cookies/init.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
<body>
<script>
document.cookie = 'luigiCookie=true';
document.location = 'complete.html';
</script>
<script>
let cookies = document.cookie;
let luigiCookie;
let luigiCookieKey;
if (cookies) {
luigiCookie = cookies
.split(';')
.map(cookie => cookie.trim())
.find(cookie => cookie == 'luigiCookie=true');
}
if (luigiCookie === 'luigiCookie=true') {
luigiCookieKey = luigiCookie.split('=')[0];
document.cookie = luigiCookieKey + '=; Max-Age=-99999999;';
}
document.cookie = 'luigiCookie=true';
cookies = document.cookie;
if (cookies) {
luigiCookie = cookies
.split(';')
.map(cookie => cookie.trim())
.find(cookie => cookie == 'luigiCookie=true');
}
if (luigiCookie === 'luigiCookie=true') {
window.parent.postMessage('luigi.tpcEnabled', '*');
document.cookie = luigiCookieKey + '=; Max-Age=-99999999;';
} else {
window.parent.postMessage('luigi.tpcDisabled', '*');
console.warn('Third party cookies are not supported!');
}
</script>
</body>
2 changes: 1 addition & 1 deletion docs/authorization-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ auth: {

The OpenID Connect configuration allows you to specify the **automaticSilentRenew** option. When set to `true`, Luigi attempts to automatically renew the token in the background before it expires. Be aware that this mechanism requires the browser to support [third-party cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Third-party_cookies).

To detect whether the user's browser supports the mechanism, use the script in the [`third-party-cookies`](https://github.com/SAP/luigi/tree/master/core/third-party-cookies) catalog. Deploy these files on a domain different from your main application's and set **thirdPartyCookiesScriptLocation** to the `init.html` file. During initialization, Luigi detects the cookies support and produces a warning in the console if cookies are disabled in the user's browser.
To detect whether the user's browser supports the mechanism, use the script in the [`third-party-cookies`](https://github.com/SAP/luigi/tree/master/core/third-party-cookies) catalog. Deploy this file on a domain different from your main application's and set **thirdPartyCookiesScriptLocation** to the `init.html` file. During initialization, Luigi detects the cookies support and produces a warning in the console if cookies are disabled in the user's browser.

When Luigi fails to renew the token and then logs the user out, it adds the `?reason=tokenExpired&thirdPartyCookies=[VALUE]` query parameters to the logout page redirect URL. Luigi replaces **[VALUE]** with one of these options:
- `disabled` means that third party cookies are disabled.
Expand Down
20 changes: 20 additions & 0 deletions docs/general-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ settings: {
allowRules: ['microphone'],
appLoadingIndicator: {
hideAutomatically: true
},
thirdPartyCookieCheck = {
thirdPartyCookieDetection: true,
//thirdPartyCookieScriptLocation: 'https://domain/init.html',
thirdPartyCookieErrorHandling: () => {
const alert = {
text: 'Third Party Cookies are not enabled. Please check your browser settings.',
type: 'warning'
};
Luigi.ux().showAlert(alert);
}
}
}
```
Expand Down Expand Up @@ -88,3 +99,12 @@ For example, to allow 'fullscreen' for non-modal iframes:
```
* **allowRules** is an array of rules for the content in the iframe, managed by the HTML **allow** attribute. You can use one or more rules by adding them to the array, for example `allowRules: ['microphone', 'camera']`. Be aware that this mechanism requires the browser to support [Feature Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Feature_Policy).
* **appLoadingIndicator.hideAutomatically** allows you to disable automatic hiding of the app loading indicator, which is enabled by default in case the app loading indicator is being used. Take a look at the [App loading indicator](luigi-ux-features.md#app-loading-indicator) section on how to use this feature.
### Third-party cookies support check
There are two ways to check whether the user's browser supports third-party cookies:
**thirdPartyCookieCheck** is an object which expects a function called `thirdPartyCookieErrorHandling` and an optional **thirdPartyCookiesScriptLocation** parameter. When **thirdPartyCookiesScriptLocation** is set, the Luigi Core application checks third-party cookie support only once and not on every micro frontend call. If it is *not* set, the Luigi Core application checks third-party cookie support whenever a micro frontend is loaded.
* `thirdPartyCookieErrorHandling` is a function where you could call an alert like `Luigi.ux().showAlert({})`.
* **thirdPartyCookieScriptLocation** is the URL to the page containing third-party cookies support check.
To detect whether the user's browser supports the mechanism, use the script in the [`third-party-cookies`](https://github.com/SAP/luigi/tree/master/core/third-party-cookies) catalog. Deploy this file on a domain different from your main application's and set `thirdPartyCookieScriptLocation` to the `init.html` file. During initialization, Luigi detects cookies support and produces an alert if cookies are disabled in the user's browser.

0 comments on commit 664cba0

Please sign in to comment.