Problem/Motivation

Currently, the CAS module does not have a route requirement _user_is_logged_in: 'FALSE'. So if there is log in menu link that uses cas.login route, the link still be visible even if user is logged in. This causes confusion.

Proposed resolution

To address this issue, a condition "_user_is_logged_in" should be added to the cas.login router. This should effectively prevent access to the route for users that are already logged in.

Remaining tasks

User interface changes

Change Record Snippet

Authenticated users no longer have access to the /cas or /caslogin routes. This was done so that menu links to these paths (e.g., for a "log in" link) don't show up for already logged in users. This matches the behavior of login routes of core (/user/login) and other SSO contrib modules like simpleSAMLphp Authentication and SAML Authentication.

However, authenticated users that visit /cas or /caslogin will not be shown an access denied page. Instead, they'll be redirected to the homepage. If a destination parameter was present on the link (e.g., /cas?destination=/some/page), they'll be redirected to that destination instead.

Note that this also means that already authenticated users can no longer use /cas or /caslogin to re-authenticate their session with the CAS server. They must first log out then log back in again.

Issue fork cas-3446948

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Jaspreet Longia created an issue. See original summary.

Jaspreet Longia’s picture

Title: Change the cas route cas.login to have a route requirement _user_is_logged_in: 'FALSE'. This should effectively prevent access to the route for users that are already logged in. » Change the cas route cas.login to have a route requirement _user_is_logged_in: 'FALSE'.
Jaspreet Longia’s picture

Title: Change the cas route cas.login to have a route requirement _user_is_logged_in: 'FALSE'. » Prevent access to cas.login route, if user is already logged in.
Issue summary: View changes
Jaspreet Longia’s picture

Assigned: Unassigned » Jaspreet Longia

bkosborne’s picture

Going to make a new branch because this one was created with branch name 2.x and it's making it harder to review locally (I already have a branch with that name)

bkosborne changed the visibility of the branch 2.x to hidden.

bkosborne’s picture

Status: Active » Needs review

Rather than just issue an access denied error when an authenticated user accesses /cas to login, the merge request now redirects them to the homepage. This is the same behavior as if they did have a successful login via /cas. So users basically shouldn't notice any difference, other than they are not redirected to the CAS server to re-login again anymore. I think this makes the best UX. Someone may have /cas bookmarked and if they still have an active session, showing them an Access Denied error would be confusing. Just redirect them to the homepage as if they had logged in.

This is similar to what core does when an authenticated user tries accessing /user/login. It redirects them to the user profile page instead of showing an access denied.

bkosborne’s picture

Assigned: Jaspreet Longia » Unassigned
bkosborne’s picture

Thanks for the review. I'll see about extending that base class!

Another thing I want to try and resolve here is this scenario:

  1. Authenticated user clicks a link to /cas?destination=/some/page
  2. User is denied access to /cas since they're already logged in
  3. Our subscriber intercepts the exception and redirects the user to the homepage
  4. The /some/page destination is lost

We have at least one site that's using this workflow for links that this patch breaks.

claudiu.cristea’s picture

Status: Needs review » Needs work

Given #3463607: AccessDeniedSubscriber should extend HttpExceptionSubscriberBase is RTBC and most likely will me merged, I think we should do it also here.

i think #11 makes sense

bkosborne’s picture

Pushed an update that uses HttpExceptionSubscriberBase and preserves the destination parameter. Updated issue summary to describe the change.

bkosborne’s picture

Issue summary: View changes
bkosborne’s picture

Issue summary: View changes
bkosborne’s picture

Issue summary: View changes
bkosborne’s picture

Version: 2.2.0 » 3.x-dev
Status: Needs work » Needs review

Updated the MR to be based on 3.x

claudiu.cristea’s picture

Unfortunately tests are failing

bkosborne’s picture

Fixed the broken test

claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

Great. You can merge and release 3.0.0.

I propose the following release notes:

Relevant changes

Updating to CAS 3.0

  • While still on Drupal 10, update your site to CAS 2.3.2. This is very important because starting with CAS 3.0.0, old (post)update functions are removed.
  • Require drupal/cas:^3.0 with Composer
  • If you have custom code that interacts with the CAS module, you may need to make some updates. There are some tiny backwards compatibility breaking changes that require your attention:
    • The type of value returned by CasLoginException::getCode() was changed from integer to enum of type CasLoginExceptionType. If your code calls this method, you should adapt. If you still need the integer value, you can do something like
      $codes = CasLoginExceptionType::cases();
      $code = array_search($exception->getCode(), $codes, TRUE);
      
    • The parameter of CasUserManager::getCasUsernameForAccount() is now strict typed as integer. Make sure you cast the parameter to an Integer before is passed to the method:
      $account = ...;
      $uid = (int) $account->id();
      $name = \Drupal::service('cas.user_manager')->getCasUsernameForAccount($uid);
      
    • The CasServerConfig::setProtocolVersion() setter accepts now a CasProtocolVersion enum case as parameter instead of a string. Same, the CasServerConfig::getProtocolVersion() getter returns now a CasProtocolVersion enum case instead of a string. If needed, get the server version as a legacy string: CasServerConfig::getProtocolVersion()->value.
    • The CasServerConfig::setHttpScheme() setter accepts now a HttpScheme enum case as parameter instead of a string. Same, the CasServerConfig::getHttpScheme() getter returns now a HttpScheme enum case instead of a string. If needed, get the HTTP scheme as a legacy string: CasServerConfig:: getHttpScheme()->value.
    • The CasServerConfig::setVerify() setter accepts now a SslCertificateVerification enum case as parameter instead of an integer. Same, the CasServerConfig::getVerify() getter returns now a SslCertificateVerification enum case instead of an integer. If needed, get the certificate verification scheme as a legacy integer: CasServerConfig:: getVerify()->value.
  • You can now update your site to Drupal 11.
  • After updating to CAS 3.0, prepare for the next CAS version by replacing the deprecated code. Check https://www.drupal.org/node/3462792 to learn what is deprecated in CAS 3.0 and adapt your code.

  • bkosborne committed e9e48114 on 3.x
    Issue #3446948: Prevent access to cas.login route, if user is already...
bkosborne’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

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