feat: associates user by email for oauth when tpa is required - #25935
Conversation
|
Thanks for the pull request, @nizarmah! I've created OSPR-5312 to keep track of it in JIRA, where we prioritize reviews. Please note that it may take us up to several weeks or months to complete a review and merge your PR. Feel free to add as much of the following information to the ticket:
All technical communication about the code itself will be done via the GitHub pull request interface. As a reminder, our process documentation is here. Please let us know once your PR is ready for our review and all tests are green. |
53a6fb5 to
2290f04
Compare
8208877 to
914410a
Compare
|
Sorry for all the messy force pushes! I just wanted to clean the history before any reviewer took a look. I have been testing on the sandbox, which made pushing to the branch just more convenient. |
e1fa76f to
2f727ba
Compare
|
👍 🎉
|
|
@natabene, I hope you and the members on the edX team are having/have had a nice holiday! |
|
@nizarmah Thanks, lining this up for our review. |
|
This will likely need product review but I would be inclined to suggest making this the default behavior and deprecating the previous behavior with the yellow message ("You have successfully signed in but there's no linked account"). Everyone I've ever talked to about the current flow has said it's confusing. The most common case is that the user's SSO email matches their existing account's email, and in that case it should automatically link (if we trust the SSO provider), which I believe is what's happening here. The "edge case" is that the user's SSO email is different from their existing account's email; in that case if they want to "link" instead of creating a new account, they can always sign in to their existing account, go to the account settings page, and link the accounts from there. That's how most other websites work anyways. It may also be necessary to enable this per provider, because we don't necessarily trust every provider's "email" field (e.g. user logs in via their company provider and company provider was hacked to say that they own the email of an edX employee, we don't want to log them in to the edX employee's account). |
|
@nasthagiri Are you ok with this going to core committers? |
|
@natabene Yes, I am. @bradenmacdonald +1 to your suggestion of changing the default. @wajeeha-khalid can provide Product input on this. |
waheedahmed
left a comment
There was a problem hiding this comment.
Just one concern otherwise looks good now.
There was a problem hiding this comment.
It will enable it by default for each auth entry in the oauth2 provider's case and I believe the purpose of associate_by_email_if_login_api is failed here. Don’t you think we need to put it under the feature flag ENABLE_REQUIRE_THIRD_PARTY_AUTH?
There was a problem hiding this comment.
And if we are making it the default behavior in the oauth2 providers case, then I think we can change this check if auth_entry == AUTH_ENTRY_LOGIN_API: to something if is_oauth_provider(backend.name, **kwargs) and auth_entry in ALLOWED_AUTH_ENTRIES: instead of this new pipeline function.
ALLOWED_AUTH_ENTRIES will be a list of auth entries you want to allow here. e.g. login_api, login, register.
There was a problem hiding this comment.
@waheedahmed Yes, I do think we need to put it under the feature flag ENABLE_REQUIRE_THIRD_PARTY_AUTH, that's a great point.
Your recommendation about the ALLOWED_AUTH_ENTRIES is great, but I'm hesitant to make such a change because it can be considered "breaking".
There was a problem hiding this comment.
@waheedahmed may you please check the latest changes? I added the setting check. I also added a test to verify that it is working 😃
I thought of adding another test, when the flag is disabled, but I believe test_new_account_registration_assigns_distinct_username_on_collision already covers the default case. Let me know though, please, if you don't consider that to be enough 👍🏼
7bd19f9 to
776912e
Compare
There was a problem hiding this comment.
This test is passing even with ENABLE_REQUIRE_THIRD_PARTY_AUTH=False, shouldn’t it fail without this setting enabled?
There was a problem hiding this comment.
😯 it should indeed fail without this setting enabled... I'll look into it. Sorry about that!
|
@waheedahmed sorry for this taking so much longer than it should 😞 Anyway, I updated the tests, and I also added some additional tests for the utils I added 👍🏼 I went also with a different approach for the test, which is just the opposite of This should be ready for your review again 😁 cc @natabene |
|
For historical purposes, would you mind updating the PR description? Thank you. |
|
@robrap thanks for the reminder 👍🏼 The description has been updated, and I made sure to link to two important messages in the pull request. 😄 |
waheedahmed
left a comment
There was a problem hiding this comment.
A small nit otherwise looks good now 👍, please squash your commits and let me know when it's ready to merge.
Thanks!
There was a problem hiding this comment.
Since you have already defined the return value within the mock call, I guess you can remove this unnecessary as statement _mock_get_associated_user_by_email_response.
There was a problem hiding this comment.
Sure! 👍🏼
I also removed _mock_associate_by_email since it was also not used 😃
This should be addressed by now. I also squashed by the way.
This change associates users signing in using oauth providers when tpa is required, verifying that only a single database user is associated with the email. For more information as to why this was added in a separate pipeline, check edx-platform#25935.
fd6541c to
a9285b6
Compare
|
@waheedahmed 🥳 awesome! Thank you a lot for the review and for being patient with me through this change 😅 I addressed your nit and squashed. This is ready to be merged 👍🏼 (once the builds pass) |
|
Your PR has finished running tests. There were no failures. |
|
@nizarmah 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
|
EdX Release Notice: This PR has been deployed to the staging environment in preparation for a release to production. |
|
EdX Release Notice: This PR has been deployed to the production environment. |
…on (openedx#25935)" This reverts commit be12567.
…edx#25935) (cherry picked from commit 914410a47b50933e5a92e2e77e0dbc85ff405cce)
Description
Currently, in the edX platform, if you try to login with an SSO account using the login form, a username is generated for you based on the email that is used with the SSO provider.
The username is generated using the pipeline
third_party_auth.pipeline.get_username.If the username already exists in the platform, you run into a small conflict which sends you back to the login form and requests the following:

It basically requests that you link your edX account and your SSO account.
However, sometimes we would want the edX account and SSO account to be associated by email. There's already a special pipeline available in the platform for that,
third_party_auth.pipeline.associate_by_email_if_login_api. Sadly, however, it is only available for a certain entry method of authentication, calledlogin_api.So in order to start associating the edX account and SSO account by email, this pull request adds a waffle switch.Update: After a lot of reading through the code and investigation, it seems like thelogin_apiauth entry is no longer used. Accordingly, I took the liberty of removing said pipeline and replacing it with something that seemed useful. Now the pipeline runs whenever third party authentication is required.Update: After @waheedahmed's findings, which is that
login_apiis in fact still used, and @zamanafzal's request, which is to make the functionality specific to Oauth providers, a new pipeline was added to associate the user by email only when the following conditions are met:ENABLE_REQUIRE_THIRD_PARTY_AUTHis enabledSupporting information
Testing instructions
Preparation
Please send an email to
nizaratopencraft.com, requesting to be added as a test user to the Google SSO used for this sandbox.You need a Google Account, because you'll be using the same email address when registering through the form and through the SSO.
Reproducing the problem
Logging in with the SSO
Login with the Google SSO over at the sandbox with default behavior
Removing Social Auth Record
Sign in as
staff:edxinto the django admin and delete the user social auth for your user.Logging in with the SSO, again...
Login, again, with the Google SSO over at the sandbox with default behavior. After doing that, you should receive a similar screenshot

Testing the fix
Logging in with the SSO
Login with the Google SSO over at the sandbox with default behavior
Removing Social Auth Record
Sign in as
staff:edxinto the django admin and delete the user social auth for your user.Logging in with the SSO, again...
Login, again, with the Google SSO over at the sandbox with default behavior. After that, you should be able to directly login 😃
Settings