Our ability to implement single log out is hamstrung by Drupal 8's session management. Since session IDs are stored hashed in the database, we are unable to process a SLO request because we don't have a way to actually find out the real session ID to tell php to kill it. As I see it, we have three options:

1. Don't implement SLO at all, remove current SLO code scaffolding from module.

2. Implement SLO by storing a record of session IDs for all cas-authenticated sessions in a dedicated database table for our use.

3. Same as option 2, disable storage by default, warn users that enabling SLO removes a security hardening measure new to Drupal 8.

In my mind option 3 is strictly better than option 2, but I'm not sure between 1 and 3.

Comments

yalet created an issue. See original summary.

konfuzed’s picture

From a usability standpoint: users generally expect to have their CAS session continued across their browser in other tabs after they finish whatever task they are doing in one and log out there, unless they specifically select for CAS to log out all sessions. I know we'd have to have a lot of retraining just to break habits and expectations with #1.

#2 by default without a real description as to what's being done behind the scenes nor choice for it removes a decision which shouldn't be presumed. It does seem a poor choice.

I think #3 is the best educated approach to deciding on a site-by-site basis and weigh the pros and cons. It could also speed deployment though by falling back to no SLO until #3 could be implemented cleanly.

bkosborne’s picture

And to be clear, we have no problem implementing SLO for the CAS Server component, where the Drupal site acts as the CAS login server.

The problem is that when Drupal is used as a CAS client, we cannot appropriately handle a "single log out" request that an external CAS server makes. This request comes in the form of an HTTP POST request containing the CAS service ticket for that user's session. We would normally store a mapping of this CAS service ticket to a local Drupal user's session ID, but we cannot do that in Drupal 8 because the session ID is not stored plaintext in database, instead it is stored as a hash.

I think #3 is the best bet as well. Honestly it seems like a horrible compromise, to remove a security feature to implement SLO, but if someone really needs it, then so be it. It won't be any worse off than Drupal 7 was I guess. We just have to provide a nice human readable description of this problem directly in the module.

yalet’s picture

Assigned: Unassigned » yalet
Category: Plan » Task

Alright, working on a patch for option 3.

yalet’s picture

Status: Active » Needs review
StatusFileSize
new11.58 KB

Patch implementing option 3. Tests not updated.

Status: Needs review » Needs work

The last submitted patch, 5: 2583363_5.patch, failed testing.

The last submitted patch, 5: 2583363_5.patch, failed testing.

bkosborne’s picture

  1. +++ b/src/Controller/ServiceController.php
    @@ -90,11 +90,10 @@ class ServiceController implements ContainerInjectionInterface {
    +    if ($request->getContentType() === 'xml') {
    

    Why the change here?

  2. +++ b/src/Form/CasSettings.php
    @@ -173,20 +173,28 @@ class CasSettings extends ConfigFormBase {
    +        'cause session IDs to be stored unencrypted in the database.'),
    

    should be "unhashed" not "unencrypted"

  3. +++ b/src/Service/CasLogin.php
    @@ -148,17 +148,23 @@ class CasLogin {
    +        array('sid', 'plainsid','ticket'),
    

    missing a space after comma

  4. +++ b/src/Service/CasLogout.php
    @@ -3,16 +3,41 @@
    +  /** ¶
    

    nit: extra space

  5. +++ b/src/Service/CasLogout.php
    @@ -20,6 +45,16 @@ class CasLogout {
           // A quick look at SessionManager doesn't look good, as deleting a session
           // can only be done by a user. We cannot just delete the session record
           // from the DB because you can have session data stored elsewhere.
    

    This comment block should be updated?

yalet’s picture

1. Because the previous line, in my manual testing, just didn't actually work.

2, 3, 4, 5 - Agreed.

yalet’s picture

Status: Needs work » Needs review
StatusFileSize
new11.46 KB
new9.69 KB

Addressed comments above. Reset the condition back to the original check (point 1 from above review), can someone manually try this? Interested to see if this fixes the fail.

bkosborne’s picture

StatusFileSize
new12.16 KB
new2.12 KB

I fixed two things:

(1) There were duplicate config schema's for the "logout" namespace, which was causing issues. Now all 3 logout config settings are together like they should be in cas.schema.yml

(2) When saving form config, I moved the new cas SLO setting to be alongside the other two logout settings

I also tested this with my local CAS server. The CAS logout service is indeed being invoked from the SLO POST request. However, it doesn't work. Our logic for clearing out a session doesn't work:

    session_id($sid);
    session_unset();
    session_destroy();
    session_write_close();
    session_regenerate_id(TRUE);
bkosborne’s picture

StatusFileSize
new12.13 KB
new409 bytes

This fixes it so it works. We needed to call session_start(). I also removed session_unset() and session_write_close() since I don't think they were necessary?

yalet’s picture

PHP session handling is voodoo, if it works, it works. Is it generating notices or anything in your log? At some point in the process, these session calls were throwing notices for me.

  • bkosborne committed 04d72ac on 8.x-1.x authored by yalet
    Issue #2583363 by bkosborne, yalet: Decide what to do about single log...
bkosborne’s picture

Status: Needs review » Fixed

I tested again and didn't find any notices in the log, so I committed it. Also changed the wording for the SLO setting a bit.

I'm still not completely happy with this - but at least we have something in here that works.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.