Document possible impacts of disabling third-party cookies on front-channel logout

Issue #1003 resolved
Michael Jones created an issue

Contributors have described that their front-channel logout implementations do not work when third-party cookies are disabled. The working group should discuss this situation and at a minimum, document that front-channel logout may/will not work with third-party cookies disabled, and describe why this is the case. If it is possible to work around this situation, the work-arounds should also be described.

Comments (9)

  1. Filip Skokan

    First and foremost, this does not only affect Front-Channel, by my findings Session Management is affected too.

    The problem comes when User-Agents block access to third party site data. For the sake of simplicity third party means a website content (in our case an iframe) with origin different than the one of the focused User-Agent window. Site data includes Cookies and any Web Storage API (sessionStorage, localStorage).

    When do User-Agents block this access?

    Most commonly this behavior is disabled by default and must be explicitly enabled by the End-User. Some browsers (most notably Internet Explorer on Medium-High privacy setting) come with pre-sets that already block this access and on some mobile browsers this is already default (i was not able to confirm, but iOS safari recent versions)

    How is this block implemented?

    This differs from browser to browser and from type of data too. Web Storage APIs may throw an Exception when trying to access the getters, they might also return undefined instead. Cookies (accessed both via javascript or when (not) sent to the browser with the request in question) are simply not present / are undefined. There is heavy inconsistency in the implementation of Web Storage API blocks when it comes to browser distributions. Firefox and Chrome both throw an instance of SecurityError when trying to access the API, other browsers in their current state either don't block this access yet or their block mechanism cannot be relied upon. There is also inconsistency in the Cookie block implementations, some browsers include options to only enforcing block for non-visited websites, some seem to imply this rule.

    When this User-Agent feature is enabled, how is OpenID Connect affected?

    • Core - prompt=none authorization within an iframe (should the IdP support being iframed for this case) will not be able to access the IdP session
    • Discovery - no discovered side effects
    • Back-Channel Logout - no discovered side effects
    • Session Management - Cookies and Web Storage APIs may not be available in the OP frame loaded in the RP context. The side effect here is that, depending on the used mechanism (cookie or web storage) the data needed to recalculate session_state is not going to be present. Cookie based implementations will likely return "changed" for every single call. Causing infinite loops of re-authentications.
    • Front-Channel Logout - Cookies and Web Storage APIs may not be available in the RP frontchannel_logout_uri loaded in the OP logout page context. The side effect here is that the RP frame will not be able to modify the session state without this data and will therefore not logout the user, failing the front-channel logout process on the specific RP.

    Recommendation

    Due to the inconsistency in implementations i ended up attempting to read the data anyway (my implementation is cookie based) and have a detection mechanism for this in place (https://github.com/mindmup/3rdpartycookiecheck). So in cases where the expected data was not there and a detection mechanism returned true, i return 'error' as per the specification to tell the RP not to do a re-authentication.

    session management - RPs should be encouraged to perform a detection of this on their own and skip loading the OP and RP frames in those cases, they should be warned that this may result in a chain of endless re-authentications due to the possibly returned "changed" state.
    front-channel logout - RPs should be informed that this mechanism is not 100%, should be encouraged to always implement both front and back channels should the OP support it as there is no workaround for the issue.

  2. Filip Skokan

    A reference cookie based implementation of session management. This mitigates the unwanted behavior of endless re-authentications by the RP by returning error in scenarios where third party cookies are assumed block.

    <!DOCTYPE html>
      <html>
      <head lang="en">
        <meta charset="UTF-8">
        <title>Session Management - OP iframe</title>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.2.0/sha256.js" integrity="sha256-cZOjfJHUnIR4AN0bIASJHvhhJudsombORNNWzHKVoXY=" crossorigin="anonymous"></script>
      </head>
      <body>
    
      <script type="application/javascript">
        var debug = false;
        var thirdPartyCookies = true;
    
        function receiveMessage(e) {
          if (e.data === 'MM:3PCunsupported') {
            thirdPartyCookies = false;
            return;
          } else if (e.data === 'MM:3PCsupported') {
            return;
          }
          try {
            var message_parts = e.data.split(' ');
            var clientId = message_parts[0];
            var actual = message_parts[1];
            if (debug && console) console.log('OP recv session state: ' + actual);
            var salt = actual.split('.')[1];
    
            var opbs = getOPBrowserState(clientId);
            var shaObj = new jsSHA('SHA-256', 'TEXT');
            shaObj.update(clientId + ' ' + e.origin + ' ' + opbs + ' ' + salt);
            var expected = shaObj.getHash('HEX') + ['.' + salt];
            if (debug && console) console.log('OP computed session state: ' + expected);
    
            var stat;
            if (actual === expected) {
              stat = 'unchanged';
            } else {
              stat = 'changed';
            }
    
            if (debug && console) console.log('OP status: ' + stat);
    
            e.source.postMessage(stat, e.origin);
          } catch (err) {
            e.source.postMessage('error', e.origin);
          }
        }
    
        function getOPBrowserState(clientId) {
          var cookie = readCookie('_state.' + clientId);
          if (debug && console) console.log('session state cookie: ' + cookie);
          if (!thirdPartyCookies && !cookie) throw new Error('third party cookies unsupported (detected)');
          return cookie;
        }
    
        function readCookie(name) {
          var nameEQ = name + "=";
          var ca = document.cookie.split(';');
          for(var i=0;i < ca.length;i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') c = c.substring(1,c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
          }
          return null;
        }
    
        window.addEventListener('message', receiveMessage, false);
      </script>
      <iframe src="https://cdn.rawgit.com/panva/3rdpartycookiecheck/92fead3f/start.html" style="display:none" />
    
      </body>
      </html>
    
  3. Michael Jones reporter

    We should say that this will not always work but not try to definitively describe the current situation because it is likely to keep changing. Suggested text would be welcomed!

  4. Michael Jones reporter

    We should say that this will not always work but not try to definitively describe the current situation because it is likely to keep changing. Suggested text would be welcomed!

  5. Michael Jones reporter

    Mike will propose warning text in the Implementation Consideration sections of the Session and Front-Channel specs. Hopefully @gffletch will review it.

  6. Michael Jones reporter

    I propose to add this Implementation Considerations text to the Front-Channel spec. @panva and @gffletch - please review:

    Note that at the time of this writing, some User Agents (browsers) are starting to block access to third-party content by default to block some mechanisms used to track the End-User's activity across sites. Specifically, the third-party content being blocked is website content with an origin different that the origin of the focused User Agent window. Site data includes cookies and any web storage APIs (sessionStorage, localStorage, etc.).

    This can prevent the ability for notifications from the OP at the RP from being able to access the RP's User Agent state to implement local logout actions. In particular, the <spanx style="verb">frontchannel_logout_uri</spanx> might not be able to access the RP's login state when rendered by the OP in an iframe because the iframe is in a different origin than the OP's page. Therefore, deployments of this specification are recommended to include defensive code to detect this situation, and if possible, notify the End-User that the requested RP logouts could not be performed. The details of the defensive code needed are beyond the scope of this specification; it may vary per User Agent and may vary over time, as the User Agent tracking prevention situation is fluid and continues to evolve.

    <xref target="OpenID.BackChannel">OpenID Connect Back-Channel Logout 1.0</xref> is not known to be affected by these developments.

    I likewise propose to add this similar Implementation Considerations text to the Session spec:

    Note that at the time of this writing, some User Agents (browsers) are starting to block access to third-party content by default to block some mechanisms used to track the End-User's activity across sites. Specifically, the third-party content being blocked is website content with an origin different that the origin of the focused User Agent window. Site data includes cookies and any web storage APIs (sessionStorage, localStorage, etc.).

    This can prevent the ability for notifications from the OP at the RP from being able to access the RP's User Agent state to implement local logout actions. In particular,
    cookies and web storage APIs may not be available in the OP frame loaded in the RP context. The side effect here is that, depending on the used mechanism (cookies or web storage), the data needed to recalculate <spanx style="verb">session_state</spanx> might not be available. Cookie based implementations might then return <spanx style="verb">changed</spanx> for every single call, resulting in infinite loops of re-authentications. Therefore, deployments of this specification are recommended to include defensive code to detect this situation, and if possible, notify the End-User that the requested RP logouts could not be performed. The details of the defensive code needed are beyond the scope of this specification; it may vary per User Agent and may vary over time, as the User Agent tracking prevention situation is fluid and continues to evolve.

    <xref target="OpenID.BackChannel">OpenID Connect Back-Channel Logout 1.0</xref> is not known to be affected by these developments.

  7. Log in to comment