From f75ae33580aa7ce1d5d35ca96ce6d0ed9b1b9193 Mon Sep 17 00:00:00 2001 From: Tim McCormack Date: Wed, 25 Aug 2021 16:16:48 +0000 Subject: [PATCH] feat: Implement (but don't activate) LMS OAuth2 SSO login for Studio (#28533) Once LOGIN_URL is changed for an environment, the OAuth flow will be activated. (See included temporary doc.) This is for ARCHBOM-1860: Convert Studio to use LMS OAuth login. --- cms/envs/common.py | 9 ++++- cms/urls.py | 3 +- docs/guides/studio_oauth.rst | 60 ++++++++++++++++++++++++++++++++ requirements/edx/base.in | 1 + requirements/edx/base.txt | 9 +++++ requirements/edx/development.txt | 9 +++++ requirements/edx/testing.txt | 9 +++++ 7 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 docs/guides/studio_oauth.rst diff --git a/cms/envs/common.py b/cms/envs/common.py index d85a10222b..a76afde191 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -615,6 +615,7 @@ EDX_ROOT_URL = '' # use the ratelimit backend to prevent brute force attacks AUTHENTICATION_BACKENDS = [ + 'auth_backends.backends.EdXOAuth2', 'rules.permissions.ObjectPermissionBackend', 'openedx.core.djangoapps.oauth_dispatch.dot_overrides.backends.EdxRateLimitedAllowAllUsersModelBackend', 'bridgekeeper.backends.RulePermissionBackend', @@ -632,8 +633,11 @@ LMS_BASE = 'localhost:18000' LMS_ROOT_URL = "https://localhost:18000" LMS_INTERNAL_ROOT_URL = LMS_ROOT_URL +# Use LMS SSO for login, once enabled by setting LOGIN_URL (see docs/guides/studio_oauth.rst) +SOCIAL_AUTH_STRATEGY = 'auth_backends.strategies.EdxDjangoStrategy' LOGIN_REDIRECT_URL = EDX_ROOT_URL + '/home/' -# TODO: Determine if LOGIN_URL could be set to the FRONTEND_LOGIN_URL value instead. +# TODO: Set LOGIN_URL to '/login/' after Studio OAuth transition is complete, and +# finish ARCH-1253 cleanup. See docs/guides/studio_oauth.rst LOGIN_URL = reverse_lazy('login_redirect_to_lms') FRONTEND_LOGIN_URL = lambda settings: settings.LMS_ROOT_URL + '/login' derived('FRONTEND_LOGIN_URL') @@ -1615,6 +1619,9 @@ INSTALLED_APPS = [ # Database-backed Organizations App (http://github.com/edx/edx-organizations) 'organizations', + + # Allow Studio to use LMS for SSO + 'social_django', ] diff --git a/cms/urls.py b/cms/urls.py index 10ca275e4f..fa0fe871b0 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -7,6 +7,7 @@ from django.conf.urls import include, url from django.conf.urls.static import static from django.contrib.admin import autodiscover as django_autodiscover from django.utils.translation import ugettext_lazy as _ +from auth_backends.urls import oauth2_urlpatterns from edx_api_doc_tools import make_docs_urls from ratelimitbackend import admin @@ -43,7 +44,7 @@ COURSELIKE_KEY_PATTERN = r'(?P({}|{}))'.format( # Pattern to match a library key only LIBRARY_KEY_PATTERN = r'(?Plibrary-v1:[^/+]+\+[^/+]+)' -urlpatterns = [ +urlpatterns = oauth2_urlpatterns + [ url(r'', include('openedx.core.djangoapps.user_authn.urls_common')), url(r'', include('common.djangoapps.student.urls')), url(r'^transcripts/upload$', contentstore_views.upload_transcripts, name='upload_transcripts'), diff --git a/docs/guides/studio_oauth.rst b/docs/guides/studio_oauth.rst new file mode 100644 index 0000000000..6df1b7d3bf --- /dev/null +++ b/docs/guides/studio_oauth.rst @@ -0,0 +1,60 @@ +Enabling OAuth for Studio login +=============================== + +Migration guide for edx.org (and anyone else following master) in converting Studio login to use OAuth. + +This is a temporary document for Arch-BOM. + +Background +---------- + +As of Lilac, the Studio by default shares a session cookie with the LMS. This either forces Studio to be on a subdomain of the LMS or the LMS to set its session cookie on a wide domain, which exposes it to a potentially large number of subdomains. + +By setting up Studio to use LMS's OAuth2-based single-sign-on (SSO), the cookies (and domains) can be decoupled to improve both flexibility and security. + +Migration +--------- + +Most of the configuration is already in place, and Studio and LMS just need to be configured in each environment to enable the new flow. (Devstack and sandboxes will autoconfigure for OAuth.) + +For each deployed environment (stage, production, etc.): + +#. Register an SSO OAuth2 client in LMS: + + - Add OAuth2 client: + + - Go to ``/admin/oauth2_provider/application/add/`` in LMS admin + - Copy the prepopulated client ID and secret to a secure place + - Leave the user field empty + - Set redirect URLs to ``/complete/edx-oauth2/`` + - Set client type to ``Confidential`` + - Set authorization grant type to ``Authorization code`` + - Set the name to ``studio-sso`` + - Select the "Skip authorization" checkbox + + - Configure the client's scope: + + - Go to ``/admin/oauth_dispatch/applicationaccess/add/`` in LMS admin + - Select application ``studio-sso`` + - Set scopes to ``user_id`` + +#. Configure Studio: + + - ``SOCIAL_AUTH_EDX_OAUTH2_KEY = '...client id...'`` + - ``SOCIAL_AUTH_EDX_OAUTH2_SECRET = '...client secret...'`` + - ``SOCIAL_AUTH_EDX_OAUTH2_URL_ROOT = '...server-to-server LMS root URL...'`` + - ``SOCIAL_AUTH_EDX_OAUTH2_PUBLIC_URL_ROOT = '...public LMS root URL...`` + +#. Set ``LOGIN_URL`` for Studio to ``'/login/'`` and verify that it causes logins to use OAuth. Existing sessions should continue to work. + + +Cleanup +------- + +Config and code changes to be performed after all environments are using OAuth flow for Studio. + +- Set ``LOGIN_URL`` to ``'/login/'`` in ``cms/envs/common.py`` +- Deploy +- Remove ``LOGIN_URL`` overrides from all environments (devstack and others) +- Remove remaining ``ARCH-1253`` detritus (login redirect) +- Remove this doc! diff --git a/requirements/edx/base.in b/requirements/edx/base.in index 0bc7b01724..b21b7092f2 100644 --- a/requirements/edx/base.in +++ b/requirements/edx/base.in @@ -74,6 +74,7 @@ done-xblock edx-ace edx-analytics-data-api-client edx-api-doc-tools +edx-auth-backends # Allow Studio to use LMS SSO edx-bulk-grades # LMS REST API for managing bulk grading operations edx-ccx-keys edx-celeryutils diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 8239e057ae..19ca3dff80 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -191,6 +191,7 @@ django==2.2.24 # drf-yasg # edx-ace # edx-api-doc-tools + # edx-auth-backends # edx-bulk-grades # edx-celeryutils # edx-completion @@ -400,6 +401,10 @@ edx-analytics-data-api-client==0.17.0 # via -r requirements/edx/base.in edx-api-doc-tools==1.4.3 # via -r requirements/edx/base.in +edx-auth-backends==3.4.0 + # via + # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt + # -r requirements/edx/base.in edx-bulk-grades==0.9.1 # via # -r requirements/edx/base.in @@ -768,6 +773,7 @@ pyjwt[crypto]==1.7.1 # -c requirements/edx/../constraints.txt # -r requirements/edx/base.in # drf-jwt + # edx-auth-backends # edx-proctoring # edx-rest-api-client # social-auth-core @@ -933,6 +939,7 @@ six==1.16.0 # codejail # crowdsourcehinter-xblock # edx-ace + # edx-auth-backends # edx-bulk-grades # edx-ccx-keys # edx-django-release-util @@ -967,11 +974,13 @@ social-auth-app-django==4.0.0 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/edx/base.in + # edx-auth-backends social-auth-core==3.4.0 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -c requirements/edx/../constraints.txt # -r requirements/edx/base.in + # edx-auth-backends # social-auth-app-django sorl-thumbnail==12.7.0 # via diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index d2bf74594d..4d486a5656 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -266,6 +266,7 @@ django==2.2.24 # drf-yasg # edx-ace # edx-api-doc-tools + # edx-auth-backends # edx-bulk-grades # edx-celeryutils # edx-completion @@ -501,6 +502,10 @@ edx-analytics-data-api-client==0.17.0 # via -r requirements/edx/testing.txt edx-api-doc-tools==1.4.3 # via -r requirements/edx/testing.txt +edx-auth-backends==3.4.0 + # via + # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt + # -r requirements/edx/testing.txt edx-bulk-grades==0.9.1 # via # -r requirements/edx/testing.txt @@ -1042,6 +1047,7 @@ pyjwt[crypto]==1.7.1 # -c requirements/edx/../constraints.txt # -r requirements/edx/testing.txt # drf-jwt + # edx-auth-backends # edx-proctoring # edx-rest-api-client # social-auth-core @@ -1300,6 +1306,7 @@ six==1.16.0 # codejail # crowdsourcehinter-xblock # edx-ace + # edx-auth-backends # edx-bulk-grades # edx-ccx-keys # edx-django-release-util @@ -1352,11 +1359,13 @@ social-auth-app-django==4.0.0 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/edx/testing.txt + # edx-auth-backends social-auth-core==3.4.0 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -c requirements/edx/../constraints.txt # -r requirements/edx/testing.txt + # edx-auth-backends # social-auth-app-django sorl-thumbnail==12.7.0 # via diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index ceb223171e..b41cba1afb 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -251,6 +251,7 @@ distlib==0.3.2 # drf-yasg # edx-ace # edx-api-doc-tools + # edx-auth-backends # edx-bulk-grades # edx-celeryutils # edx-completion @@ -482,6 +483,10 @@ edx-analytics-data-api-client==0.17.0 # via -r requirements/edx/base.txt edx-api-doc-tools==1.4.3 # via -r requirements/edx/base.txt +edx-auth-backends==3.4.0 + # via + # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt + # -r requirements/edx/base.txt edx-bulk-grades==0.9.1 # via # -r requirements/edx/base.txt @@ -979,6 +984,7 @@ pyjwt[crypto]==1.7.1 # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt # drf-jwt + # edx-auth-backends # edx-proctoring # edx-rest-api-client # social-auth-core @@ -1223,6 +1229,7 @@ six==1.16.0 # codejail # crowdsourcehinter-xblock # edx-ace + # edx-auth-backends # edx-bulk-grades # edx-ccx-keys # edx-django-release-util @@ -1268,11 +1275,13 @@ social-auth-app-django==4.0.0 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/edx/base.txt + # edx-auth-backends social-auth-core==3.4.0 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -c requirements/edx/../constraints.txt # -r requirements/edx/base.txt + # edx-auth-backends # social-auth-app-django sorl-thumbnail==12.7.0 # via