Leveraging the Storage Access API
The persistence service (PS) needs to access first party, non-partitioned storage to be able to remember chosen IdPs across different SPs. Recent developments in browser technology, designed to protect end user’s privacy, mean that to do so, the PS will have to make use of the Storage Access API (SAA), which provides access to non-partitioned storage from a 3rd party context.
As mentioned in the introduction and in using thiss-ds.js, for users of chrome and chromium based browsers that have enabled a privacy setting (at this point -July 2025- still to be specified), using the SAA requires some special setup. So this section is for integrators that want to provide global persistence for such users.
For these users, the SAA can only be called in reaction to an end user interaction with some UI element in the third party context. In addition, to be able to use the API, the user must have previously (less than 30 days earlier) visited the third party origin in a first party context.
By default, the PS runs in an iframe that is fully hidden, with no elements exposed in the UI. If we want to provide global persistence for these users, the PS will need to expose some element in the UI. For the moment, this element is a checkbox. The integrators using the PS client in their code will need to decide where to expose it. So the call to the constructor for the client for the PS can take a new parameter, a DOM locator, pointing to some element in the UI to which the checkbox will be attached.
The behaviour of the checkbox only affects the way user choices are persisted.
If the third party origin (the PS origin) has not been visited (in the current or in previous browser sessions) and thus the API cannot be used, the checkbox will be loaded unchecked.
With the checkbox unchecked, no attemp at persistence is made.
If the user checks the checkbox, but the PS origin has not been visited in a first party context, there will be local (partitioned) persistence: the choice of IdP will be remembered per SP. On a subsequent load, the checkbox will be unchecked.
When the user has visited the PS origin in a first party context (e.g. the user has visited the discovery service (DS)), the checkbox will be loaded unchecked. If the user checks it, the Storage Access API will be called, and the user will be prompted for storage access permission.
If the user grants the permission, any choices stored in local, partitioned storage will be moved to global, unpartitioned storage, and subsequently there will be global persistence. The checkbox will then on subsequent visits load checked.
If the user denies the permission, there will only be local persistence for a period of time (30 days) until the API allows prompting the user for storage access permission again.
In any case, there will be persistence (global or local) when the checkbox is checked.
Accessing the SeamlessAccess persistent storage through Storage Access API
As mentioned above, first we create an element which will hold the PS checkbox, and then provide the PS constructor with a selector for the element.
This is an example of accessing the PS. The client page will have some HTML similar to:
<p><span id="ps-checkbox-holder"><span/> Remember my choice</p>
Then we call the constructor:
import {PersistenceService} from "@theidentityselector/thiss-ds/src/persist.js";
const ps = PersistenceService(
'https://use.thiss.io/ps/',
{
selector: '#ps-checkbox-holder',
});
// do something with `ps`
Now we can do things with the ps object, see the PS API api/persist
The changes to code using the DiscoveryService class are similar, since it includes a PersistenceService property.
First we would add some HTML element to hold te checkbox, and the provide the constructor with a selector for the element:
var ds = new DiscoveryService(
'https://md.thiss.io/entities/',
'https://use.thiss.io/ps/',
'my_context',
{
selector: "#ps-checkbox-holder",
}):
And now we can do things with the ds object, see the DS API api/discovery
Event signalling that the end user has clicked on the PS checkbox
Whenever the end user clicks on the PS checkbox, the PS will emit a message event that the top level site can subscribe to. This way, integrations can leverage the checkbox for their own purposes. This event will have (post-robot) id sa-checkbox-clicked and will include the subsequent state of the checkbox (checked/unchecked). For example:
postRobot.on('sa-checkbox-clicked', {window: ds.ps.dst}, function(event) {
const checked = event.data.checked; // checked is a boolean
// do something
});
Exposing the checkbox after the persistence service is loaded
There may be cases where the advanced integrator may want to expose the persistence service checkbox in an element that is not visible on page load, for example in a modal that is opened in response to an end user interaction. In this case, we need to append the checkbox after the modal has loaded and is exposing the element to which the checkbox is to be attached. So we would first instantiate the persistence service without providing it with a locator:
import {PersistenceService} from "@theidentityselector/thiss-ds/src/persist.js";
const ps = PersistenceService('https://use.thiss.io/ps/');
Then, at the time of displaying the element that will contain the checkbox, we need to call PersistenceService.show_checkbox(selector: string). In this case, if we want to handle the sa-checkbox-clicked post-message event, we have to set the handler after calling show_checkbox (since show_checkbox will change ps.dst):
someButton.addEventListener("click", (e) => {
// Code to display element with id "checkbox-sa-holder"
// ...
// Then attach checkbox to it:
ds.ps.show_checkbox("#checkbox-sa-holder");
postRobot.on('sa-checkbox-clicked', {window: ds.ps.dst}, function(event) {
// Do something
});
});
Finally, if we need to hide the element that contains the checkbox (e.g., the checkbox is shown in a modal, and the end user closes the modal), we have to call hide_checkbox beforehand.
someButton.addEventListener("click", (e) => {
ds.ps.hide_checkbox("#checkbox-sa-holder");
// now we can remove the element holding the checkbox from the UI.
});