Problem/Motivation
After recently upgraded from 3.0.0-alpha3 to 3.0.0-alpha4 or 3.0.0-alpha5, our site seems to remove a user's custom Drupal roles after they log in with the OpenID Connect button.
Steps to reproduce
- Dev: Run composer update to upgrade the module from 3.0.0-alpha3 to 3.0.0-alpha4 or 3.0.0-alpha5.
- Dev: Check in updated composer.lock and deploy.
- Prod: Deployment script picks up the latest changes, and runs
drush deployafter composer install. - User logs in using the OIDC button.
- User notices custom roles removed. Only "Authenticated" role remain.
A key point to reproduce is issue is, drush config:export was not run after doing composer update on Dev or Prod. As a result, the necessary configuration updates brough by 3.0.0-alpha5 are not applied during the deployment process.
We are running Drupal 10.3.10 on PHP 8.3.14.
Before that, the website runs on 10.3.1 on PHP 8.1.
(Update: I corrected the version numbers before/after the upgrade.)
(Update2: Issue summary updated to highlight the absence of drush cex in deployment to reproduce this issue.)
Proposed resolution
The original problem reported in this issue was caused by a deployment process that ignored configuration changes. It reverted to the original configuration after running database-update functions. See Comments #1 to #26.
The current scope, described here, evolved from the discussion starting in Comment #35.
Add the new setting force_reset_role_mappings: boolean, default to TRUE.
On /admin/config/people/openid-connect/settings, the site owner can configure some roles to be managed by the OIDC provider, in the "User role mapping" section. The rest of this section applies only to roles that have non-empty configuration in that section.
When force_reset_role_mappings is TRUE and a user logs in using OpenID Connect, the user's roles are reset based on the groups from the OpenID Connect provider and the role_mappings setting. In some cases, this means the user will have no roles assigned other than Authenticated. In all cases, any roles that have been added or removed by a site administrator will be overridden.
When force_reset_role_mappings is FALSE and a user logs in using OpenID Connect, the user's roles are reset only if the OpenID Connect provider specifies at least one group and the role_mappings setting is not empty. In some cases, this can still lead to a user having only the Authenticated role. On the other hand, the site administrator can set force_reset_role_mappings to FALSE and leave the role_mappings setting empty. This will have the effect of ignoring the groups from the OpenID Connect provider, so roles are always controlled through Drupal.
| Comment | File | Size | Author |
|---|---|---|---|
| #56 | openid_connect_issue_3497559_3.0.0-alpha8.patch | 62.46 KB | jwylarsen |
| #38 | open_id_connect_issue_3497559.patch | 2.07 KB | terry_kolodiy |
Issue fork openid_connect-3497559
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
Comment #2
hktang commentedComment #3
hktang commentedComment #4
pfrillingThis sounds like a similar issue as #3487116, which should have corrected this.
- What OpenID Client are you using?
- Can you provide the plugin's configuration before and after the upgrade (obfuscating the sensitive parts)?
Comment #5
dcam commentedDid you run the database updates after updating to alpha5?
Comment #6
gokul.jayan commentedI encountered the same problem, and re-saving the OpenID Connect settings resolved it for me.
Comment #7
hktang commented@pfrilling
Below is the config in question. It seems to stay the same after upgrading from alpha3 to alpha4.
@dcam
I did run drush deploy after upgrading so I assume database update was successful.
@gokul.jayan
I tried creating a new Google profile with the same configuration. But it still wipes away my user roles after switching to that profile (on alpha4).
Here is the Google plugin setting:
Here is the module setting:
Comment #8
hktang commentedPerhaps this is the culprit? If we don't have any mappings, we should skip role syncing, right?
Comment #9
dcam commentedalpha5 has the fix for this issue.
Comment #10
hktang commentedHi @dcam, I tried upgrading from alpha4 to alpha5 and still have the same issue.
Comment #11
gokul.jayan commentedUpdate to alpha5, and there are configuration changes for the module settings that needs to be exported. After the export the configuration looks something like this.
Comment #13
dcam commentedI'd need to know more about your deployment workflow. Did you update the module on a dev environment, update the database (without using
drush deploy), export the configuration, commit the configuration, push your changes to production, install the update, and then rundrush deploy?Comment #14
hktang commentedHi @dcam:
I was performing a minor Drupal upgrade alongside other module upgrades .
Hope this helps!
Comment #15
hktang commentedHi @gokul.jayan,
I don't know why but my role mapping has empty items with my Drupal site roles. (see #7).
I added a quick fix but hopefully that doesn't break other functionalities.
Comment #19
dcam commentedI asked about the workflow because
drush deployruns database updates and then imports your configuration. If a person did that on an environment without following a strict procedure for configuration management, then their database would be updated and then immediately overwritten with the old configuration. That would result in no changes being apparent.In any case, if the database updates were run but your configuration remains in a broken state, then it's probably going to need to be manually repaired at this point. @gokul.jayan gave the solution. The role_mappings key needs to be reduced to an empty array,
role_mappings: { }. Personally, I would just edit the config file to do it and then import the configuration.Comment #20
gokul.jayan commentedHi @hktang
I also encountered the same problem with alpha5. In my case, when I resaved the module settings, there were changes to the role mappings—specifically, the removal of all role mappings and their replacement with only the role_mapping key containing an empty array. I believe resaving the module settings should resolve the issue.
Comment #21
dcam commentedYeah. That should work too.
Comment #22
hktang commentedHi @dcam and @gokul.jayan, thank you for your feedback!
I tried renaming the database upgrade script and quickly rerun it as 30003.
Then I did a config export just to make sure the
role_mappingsis emptied.Still, it seems the upgrade script didn't empty the
role_mappingsconfig item as expected. My config stays the same as #7.Here's the log for drush deploy and drush cex -y.
Comment #23
hktang commentedAlso, I agree with you that we should follow deployment best practices.
Manually updating the config yaml file might have the risk of it being overwritten by other processes. Wouldn't it be better if we just have a simple check and skip the dangerous role removal, as suggested in the merge request?
Comment #24
hktang commentedHi guys, I also confirm the update script runs correctly but it seems drush still thinks there's no difference.
This is the config right after running the update script.
But my config, after running drush cex, is still the same as #7. i.e. different content, but considered same by Drush(?)
Comment #25
gokul.jayan commentedHi @hktang
During the Drush deploy process, configuration changes were there in the openid_connect.settings, and the new changes were overridden. Please try resaving the module settings (
/admin/config/people/openid-connect/settings) and then run drush cex.Comment #26
hktang commentedHi there, I finally confirmed what happened. It's caused by the deployment script which uses "drush deploy".
According to documentation,
drush deployimports existing config immediately after running database update. It's a combination of:This sequence of actions effectively ignores the $config-save() action made by the update script added via https://www.drupal.org/node/3487116. When I do `drush cex` after deployment, I am actually exporting the old configuration instead of the new one.
Thank you @dcam and @gokul.jayan for the hint.
I wonder if
drush deployis the standard deploy action? At least we should account for the users relying on "drush deploy", I believe.Comment #27
hktang commentedComment #28
hktang commentedComment #29
chrisck+1 We have also run into this issue where our custom Drupal roles are getting removed on user log in. We aren't using the role mapping feature built into the module and the experimental fields are blank. We do use
drush deploy, and I agree with @hktang's comment #26 that it should work either way withdrush deployordrush cim. Also thank you to @hktang for diving into the issue and finding out this weird problem.Comment #30
robertragas commented+1 Also ran into this issue where we don't have role mapping enabled, but the role_mappings config not being an empty array and overriding on login.
After changing the config manually it works again.
Comment #31
hktang commentedThank you for your feedback!
I am moving this post to Needs Review as the change should do what it's expected to do. Thanks in advance for community review.
Comment #32
venu_bhagirath commentedhi,
We were facing this issue with openid_connect. As the users was logging in the role was removed for the users. The fix provided helped us resolve the issue.
Thanks
I am not moving the issue to RTBC as the pipeline for the MR is failing. Once the pipeline passes it will be ready for RTBC.
Comment #33
hktang commentedThank you. I propose we update the test case to reflect the same expected behavior: we don't remove roles if the groups does not exist in the first place. Please see the commit above.
Comment #34
timwoodIt is also possible to run into this situation if you are using config_split to only enable certain modules on upper environments (eg. Prod) and forget to account for an update hook for those modules.
Comment #35
pfrillingI think there are situations where a site would prefer to have the roles cleared if the groups array was empty (as is the current behavior). We should probably add a configuration option that would allow a site to choose the behavior. Then, we need to decide which option should be the default. I'm leaning to making the default to _not_ clear the roles, as that feels like the least intrusive, but am open to other opinions.
Comment #36
hktang commentedFully agree that we should not not clear the empty roles by default.
Regarding the configuration option, shall we address it in a separate issue? I am happy to start a new ticket for it.
I am suggesting this because I feel this issue should be patched with some urgency, and the configuration helper text could need some refining, which could take time.
Comment #37
mialdi98 commentedWe are facing the issue after updating the roles after each re-login is cleared. (our mapping is default, email)
So also looking for a solution to that.
Comment #38
terry_kolodiy commentedPatch from the MR. It works for me.
Comment #40
pfrillingI started a new branch and merge request from the patch of MR 133 (I couldn't figure out how to rename the branch 🤷♂️). See MR #157 for the updated code.
The new MR includes the aforementioned configuration option that would allow sites reliant on the current default behavior to continue working. I set the default value to be off. Any sites that want this behavior to continue will need to manually enable that configuration option. I don't see a method to enable that for some sites and not others. I'll need to over communicate that breaking change in the release notes after this merges.
Comment #42
pfrillingThanks for the review @hktang! I resolved all the threads in the MR. Can you review again?
Comment #43
hktang commentedThank you very much for addressing my comments.
Comment #44
guedressel commentedAm I right, that this behavior to remove all roles if no "groups" is set came in with #3492759: Mapped user roles are not always revoked?
See here: https://git.drupalcode.org/project/openid_connect/-/merge_requests/130/d...
Comment #45
hktang commentedThe current change should address the above issue, except that site admins must explicitly turn on "force reset role mappings"...
Either way, there will be breaking change for a subset of sites, am I correct? Specifically (after this change), site admins do not need to do anything if they don't use the experimental role mappings feature; however, they must turn on "force reset role mapping" if and only if they (1) intend to use the role mapping feature AND (2) they have completely empty role mapping from the service provider.
I would be happy if we can move forward with the current change, as it fits our use case. However, I am also wondering if a new option "Turn on experimental role mappings feature" would be useful. I would even call it "(Experimental) Pull and synchronize roles from the service provider", because "mapping" sounds bi-directional to me -- maybe just my own understanding though.
Comment #46
pfrillingYou are correct @hktang, the way it is configured now, any site that wants the roles cleared will have to update the configuration and enable the new checkbox. I don't think there is a reliable way to write an update hook to turn it on for some sites and off for others.
The other option is to default the new configuration to be enabled and force existing sites to opt-in to disabling the role map clearing. This would be more consistent with existing behavior and would requires sites like yours to disable the new configuration option.
Either way, some sites will have to make a configuration change.
I like defaulting the option to off and forcing new sites to enable the feature as I think it will cause less confusion in the future. Unfortunately, this is an inconvenience for existing sites. I'm open to other suggestions/thoughts.
@guedressel, I believe the functionality always existed prior to the change you called out. Well... unless `groups` was never defined in $userinfo 🤔. Maybe the conditional should be added back in?
Comment #47
r.aubin commentedIf you're going to add this as a config option for the module without advanced notice (like announcing and waiting a release cycle), I agree it will be least disruptive for existing users to have the default setting match current behavior.
If you notify users between releases that the change is coming in an upcoming release, ensuring it's visible on the module description page, then changing the default behavior from what it is now should reduce the risk that any users are caught off guard by the change and then it becomes the standard behavior.
Comment #48
guedressel commentedWe use this module in a setup where we rely on the OIDC group to Drupal role mapping. But there it is okay to have not group defined (empty) and also to have Drupal roles manually assigned to user. With the change in #3492759: Mapped user roles are not always revoked all manually assigned roles get lost on login of an user.
Hence we are currently working with a patch to roll-back the changes from #3492759: Mapped user roles are not always revoked and waiting for this issue to give a way forward without patching.
Comment #49
hktang commented@pfrilling I agree with you. Clearing all roles is destructive, and especially so for sites already have roles defined.
Comment #50
steinmb commented+1 to default setting match current behavior. If we want to change the default in the future, what about including a message in watchdog or status-page that there now is a new setting that controls the module role behavior, that should be verified? I provide admins ample time to review and test the implementation. The module can through the issue queue get feedback on this new behavior before changing the default in the future. Though it should perhaps be done before rolling the first beta of 3.x.
Comment #51
pfrilling- I refactored the logic based on the latest feedback and I reverted the default `force_reset` option to be enabled by default, which should be more in line with the existing behavior.
- I added back the original
isset($context['userinfo']['groups'])`check to get back to the original role behavior before #3492759.- I replaced the unit testing with better functional testing of the group logic.
I believe all of the functionality is back in place with the new configuration option. Would love some testing/feedback.
Comment #52
hktang commentedHi, I will test the patch on 3.x.
-- update --
I wasn't able to reproduce the same issue using a clean install and upgrading from alpha3 to alpha4/5/6.
Comment #53
steinmb commentedWhat is left in here? Is it only manual testing?
Comment #54
solideogloria commentedCan someone verify that the issue is reproduceable and fixed by the changes?
Comment #55
pfrillingYes, I believe the only thing left here is manual testing to confirm the original role mapping is retained after updating.
Comment #56
jwylarsen commentedalpha8-compatible patch
Comment #57
danflanagan8I haven't manually tested, but I reviewed pretty closely about three weeks ago, especially with regard to the test coverage. I think the coverage is sound. It's kind of a bummer that some fast unit tests are being replaced by some slow functional tests, but I think the closer-to-real-life issues scenarios are hard to do with unit tests. The only missing coverage I noticed and commented on has been addressed.
Comment #58
benjifisherI am adding a "Proposed resolution" section to the issue summary.
Comment #36 suggested closing this issue and opening a new one for the new setting. I think it would have been simpler to follow that suggestion (converting the issue to a support request).
I have reviewed the non-test code, and it looks good. @danflanagan8 approved the test code (Comment #57). If someone has done manual testing, then we can consider this issue RTBC.
The individual configuration options are not documented in the README, but they are (with screenshots) on https://www.drupal.org/docs/8/modules/openid-connect/configuration. I added #3582142: Update documentation for the 3.x branch.
Comment #59
benjifisherI set up a local test site. Using
ddev shareand following the instructions on https://www.drupal.org/docs/contributed-modules/openid-connect/client-co..., I configured Google as an OIDC provider.I tested both the original report on this issue and the effect of the new
force_reset_role_mappingssetting. One thing I missed until today is the last part of the description for the "User role mapping" setting:I am updating the issue summary to take that into account.
The new setting has the expected effect. Along with Comments #57 and #58, I can now set the status to RTBC.
Comment #60
pfrillingThanks everyone! This has been added to the merge train 🚆