{"action":"created","issue":{"url":"https://api.github.com/repos/edx/edx-platform/issues/8262","labels_url":"https://api.github.com/repos/edx/edx-platform/issues/8262/labels{/name}","comments_url":"https://api.github.com/repos/edx/edx-platform/issues/8262/comments","events_url":"https://api.github.com/repos/edx/edx-platform/issues/8262/events","html_url":"https://github.com/edx/edx-platform/pull/8262","id":82306861,"number":8262,"title":"Cleanup of third-party login and auto-enrollment","user":{"login":"bradenmacdonald","id":945577,"avatar_url":"https://avatars.githubusercontent.com/u/945577?v=3","gravatar_id":"","url":"https://api.github.com/users/bradenmacdonald","html_url":"https://github.com/bradenmacdonald","followers_url":"https://api.github.com/users/bradenmacdonald/followers","following_url":"https://api.github.com/users/bradenmacdonald/following{/other_user}","gists_url":"https://api.github.com/users/bradenmacdonald/gists{/gist_id}","starred_url":"https://api.github.com/users/bradenmacdonald/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bradenmacdonald/subscriptions","organizations_url":"https://api.github.com/users/bradenmacdonald/orgs","repos_url":"https://api.github.com/users/bradenmacdonald/repos","events_url":"https://api.github.com/users/bradenmacdonald/events{/privacy}","received_events_url":"https://api.github.com/users/bradenmacdonald/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/edx/edx-platform/labels/open-source-contribution","name":"open-source-contribution","color":"bfe5bf"},{"url":"https://api.github.com/repos/edx/edx-platform/labels/waiting%20on%20author","name":"waiting on author","color":"0052cc"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":32,"created_at":"2015-05-29T07:25:34Z","updated_at":"2015-06-10T06:47:20Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/edx/edx-platform/pulls/8262","html_url":"https://github.com/edx/edx-platform/pull/8262","diff_url":"https://github.com/edx/edx-platform/pull/8262.diff","patch_url":"https://github.com/edx/edx-platform/pull/8262.patch"},"body":"**Description**\r\nThis is a fix for [CRI-9](https://openedx.atlassian.net/browse/CRI-9) (\"Third party auth association fails to link on login/registration\") and [ECOM-1503](https://openedx.atlassian.net/browse/ECOM-1503). In order to fix that issue in a clean way, I did some refactoring of parts of the login and auto-enrollment flow.\r\n\r\nThere were three different parts of the code handling user login and optional auto-enrollment: the old login/register views, the third party auth pipeline, and the new combined \"logistration\" page. Each of these three had a completely separate implementation for auto-enrolling users into a course following login/registration. Also, none of them correctly completed the third party auth pipeline under all circumstances, meaning that users who do a \"social\" login often find that their social account never gets linked to their edX account. \r\n\r\n[Current Situation](https://docs.google.com/drawings/d/1OYIoXPlHst4kPav4_NxqI0xufEVv-bb3LXpzc7ShEeU/edit) vs. [New Situation](https://docs.google.com/drawings/d/1c4naj3FJ-75tjsvdK2ZjygSlV0GgfLhXoZKliYRHxII/edit)\r\n\r\n**Detailed Description**\r\nFirst, it's important to understand the many different ways that users can login to or register for the LMS:\r\n\r\n* Can be a potential user (not yet registered), a newly registered user (email is unverified, won't be able to login again until verifying), or a normal user\r\n* Can be authenticated via first party auth (username/password), third_party_auth (Facebook/Google/etc.), Legacy Shibboleth (work is underway to consolidate this with third_party_auth), or the edX API (used by the mobile app)\r\n* Can use the new combined login/registration (\"logistration\") page (à la edx.org) or the old/deprecated login/registration pages (à la Edge). Each of which uses different APIs to do the login/registration.\r\n* The login/register page[s] will sometimes be passed a \"course_id\" (and other) parameters from the edX marketing site. If present, the code must try to enroll the user in the specified course once the user has logged in or created an account. If the course is paid, the user should be redirected to the checkout flow.\r\n\r\nThe code has two significant issues that are addressed by this PR:\r\n* Third party authentication is not handled correctly in many cases\r\n  - As you can see in the [flow chart](https://docs.google.com/drawings/d/1OYIoXPlHst4kPav4_NxqI0xufEVv-bb3LXpzc7ShEeU/edit), there are several ways to login/register (vertical columns) where the third_party_auth (\"TPA\") pipeline does not get completed. This goes against [the design principles of the pipeline](https://github.com/edx/edx-platform/blob/da57b13b/common/djangoapps/third_party_auth/pipeline.py#L468) and means that user's social accounts do not get linked to their edX account during the login or registration process.\r\n* There are three redundant implementations of auto-enrollment (see scribbled red circles on the [flow chart](https://docs.google.com/drawings/d/1OYIoXPlHst4kPav4_NxqI0xufEVv-bb3LXpzc7ShEeU/edit)):\r\n  - third_party_auth.pipeline.change_enrollment *sometimes* handles auto-enrollment if third party auth is being used for login. It updates the CourseEnrollment table directly.\r\n  - student.views.[create_account/login_user] handle auto-enrollment for the old login/register screens (using `try_change_enrollment` and `change_enrollment` in that same file)\r\n  - the new login form has client-side code (AccessView.js) containing the auto-enrollment logic, and it uses the `commerce` API which in turn uses the `enrollment` API\r\n\r\nChanges in this PR:\r\n* python-social-auth version is bumped to 0.2.7 which gives us more fine-grained control over the pipeline when unverified users are involved. This change is confined to its own commit.\r\n* The three different flows for auto-enrollment and all the redundant logic is combined into a new page. The login views and the third party auth views no longer need to know anything about auto-enrollment; they simply know to send the user to the \"auto-enrollment\" page following login/registration. The new page has the same auto-enrollment logic that was previously used by the combined logistration form. I just moved it from `AccessView.js` to `FinishAuthView.js`.\r\n  - See [New Design flow chart](https://docs.google.com/drawings/d/1c4naj3FJ-75tjsvdK2ZjygSlV0GgfLhXoZKliYRHxII/edit)\r\n* Adds a new \"Dummy\" third party auth provider that can be used for tests and development.\r\n\r\nBenefits of this PR:\r\n* Social auth accounts now get linked correctly during login/registration. There is no need for users to go to their \"Account Settings\" page and manually link their accounts.\r\n* The social auth pipeline now always gets completed, as [required by its design assumptions](https://github.com/edx/edx-platform/blob/da57b13b/common/djangoapps/third_party_auth/pipeline.py#L468).\r\n* No API changes were necessary\r\n* Redundant auto-enrollment logic has been reduced substantially\r\n* The auto-enrollment process now displays status updates to the user, which is nicer than the login form simply taking an unusually long time to submit.\r\n* If desired, the marketing site could be changed to simply enroll users in a course by sending them to `/account/finish_auth?course_id=x&enrollment_action=enroll` regardless of whether they are logged in or not. Currently the marketing site tracks the user's logged in status and uses different APIs and different logic depending on whether or not the user is logged in. If it did this, there is even more code that could be removed from edX platform, since the login/register pages would no longer need to know about any query string arguments other than `next`.\r\n\r\n**Sandbox**\r\n* http://sandbox4.opencraft.com/login - updated June 4\r\n\r\n**Upgrade Issue**\r\nWhen merged, this PR does cause a problem for existing installations: `python-social-auth` at one point converted from `syncdb` to south/django migrations, and bumping the version of `python-social-auth` that we use will result in this error next time `paver update_db` is run:\r\n```\r\ndjango.db.utils.DatabaseError: table \"social_auth_usersocialauth\" already exists\r\n```\r\nTo fix this (on devstack), the user must manually run this command:\r\n```\r\n./manage.py lms migrate default 0001_initial --fake --settings=devstack\r\n```\r\nUnfortunately, I'm not aware of any way to avoid this issue other than this manual fix. New installs are not affected.\r\n\r\n**Screenshots**\r\n\r\n* [New auto-enrollment page](https://cloud.githubusercontent.com/assets/945577/7879628/f738e534-05a6-11e5-9b44-fe56cc6fa773.png). (Only ever seen if auto-enrollment is happening, and is not really meant to be seen at all. If the server's responding quickly, the user will barely see it and will be immediately redirected.) \r\n\r\n\r\n**Testing Instructions**\r\n\r\n1. Checkout this branch, get it running, and configure ~/lms.auth.json so that a social auth provider (e.g. \"Google\" or \"Dummy\") is enabled. Dummy requires no configuration and is the easiest, but it always returns the same user information/id.\r\n2. Note the setting of `ENABLE_COMBINED_LOGIN_REGISTRATION` in the `FEATURES` of `~/lms.env.json` (this change should work whether it's true or false, but each uses different code paths)\r\n3. Open an incognito window for the remainder of this test.\r\n4. On your LMS, go /login . Click on a third party auth provider.\r\n5. Once back at the login page (\"You authenticated but this account is not associated with an edX account\"), click \"Register Now\" and finish creating the account.\r\n6. Go to Account Settings and verify that the third party account is linked. (This indicates the fix worked).\r\n7. In your devstack console output, copy the link from the activation email, and paste it into the browser in order to activate this account. (Or run these commands in the django shell: `from django.contrib.auth.models import User; u=User.objects.get(username=\"Galactica1\"); u.is_active=True; u.save()`)\r\n8. From Account Settings, unlink the account and also create a password for the user.\r\n9. Go back to /login and use the third party auth to login again. Because we unlinked, the user won't be recognized (\"You authenticated but this account is not associated with an edX account\"). Enter the password from step 8 and login.\r\n10. Go to Account Settings and verify that the third party account is linked again because of this new login. (This indicates the fix worked).\r\n11. Paste the URL /account/finish_auth?course_id=course-v1%3Aorg%2Bcourse%2Brun&enrollment_action=enroll&email_opt_in=false but replace `org` `course` and `run` with the values for an actual course on this instance.\r\n12. Verify that the user gets auto-enrolled in that course.\r\n13. Close and re-open the incognito window.\r\n14. Paste the URL /login?course_id=course-v1%3Aorg%2Bcourse%2Brun&enrollment_action=enroll&email_opt_in=false but replace `org` `course` and `run` with the values for a different course on this instance.\r\n15. Login using third party auth, and verify that the user gets auto-enrolled in that new course.\r\n16. (In a normal browser window - not incognito:) As an admin-capable user, go to /admin/auth/user/ and delete the user you have been testing with. It's important that you delete it from that page by checking the checkbox next to that user then selecting \"Delete\" from the dropdown menu. If you are not on a debug machine, this may not work - in that case, use the shell to delete the UserPreference entries for the user, then delete the user using any means.\r\n17. (Back in incognito:) Go to /login?course_id=course-v1%3Aorg%2Bcourse%2Brun&enrollment_action=enroll&email_opt_in=false but replace `org` `course` and `run` with the values for a course on this instance.\r\n18. Click \"Register\". The URL may change, but that's ok.\r\n19. Click on a third party provider, finish creating the account, then make sure that the user has been enrolled in the course and that the third party account has been linked.\r\n20. Repeat step 16\r\n21. Change the setting of `ENABLE_COMBINED_LOGIN_REGISTRATION`, restart the server, and repeat the process to test the other views.\r\n\r\n**TODO**:\r\n* Add a couple new bok choy third_party_auth tests (take advantage of the Dummy Provider)\r\n* A JIRA task should be created to remove/simplify `student.views.change_enrollment` in the future (the LMS should use the enrollment API instead for consistency with the login process)\r\n\r\n**Reviewers**:\r\nCode: Destination team\r\nProduct: Griff, Beth\r\nDevOps: (TBD)"},"comment":{"url":"https://api.github.com/repos/edx/edx-platform/issues/comments/110616409","html_url":"https://github.com/edx/edx-platform/pull/8262#issuecomment-110616409","issue_url":"https://api.github.com/repos/edx/edx-platform/issues/8262","id":110616409,"user":{"login":"bradenmacdonald","id":945577,"avatar_url":"https://avatars.githubusercontent.com/u/945577?v=3","gravatar_id":"","url":"https://api.github.com/users/bradenmacdonald","html_url":"https://github.com/bradenmacdonald","followers_url":"https://api.github.com/users/bradenmacdonald/followers","following_url":"https://api.github.com/users/bradenmacdonald/following{/other_user}","gists_url":"https://api.github.com/users/bradenmacdonald/gists{/gist_id}","starred_url":"https://api.github.com/users/bradenmacdonald/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bradenmacdonald/subscriptions","organizations_url":"https://api.github.com/users/bradenmacdonald/orgs","repos_url":"https://api.github.com/users/bradenmacdonald/repos","events_url":"https://api.github.com/users/bradenmacdonald/events{/privacy}","received_events_url":"https://api.github.com/users/bradenmacdonald/received_events","type":"User","site_admin":false},"created_at":"2015-06-10T06:47:20Z","updated_at":"2015-06-10T06:47:20Z","body":"Jenkins, test this please"}}