-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: link LTI Provider launches to authenticated users #33310
feat: link LTI Provider launches to authenticated users #33310
Conversation
Thanks for the pull request, @tecoholic! 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 as you can:
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. |
6d403f4
to
ef507f1
Compare
ef507f1
to
5b3d18a
Compare
Didn't work for me with the trailing slash. After I removed, it worked. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Once the other comments are addressed. Also, is there someone this can be documented for admins?
- I tested this: followed the testing instructions.
- I read through the code
- [-] I checked for accessibility issues
- Includes documentation
b3a83a9
to
9e9ed70
Compare
…tion A new flag was introduced in the LTI Consumer configuration which allows automatically linking LTI users with the edX platform users by matching the email ID. This commit describes the purpose of the flag with its caveats. Ref: openedx/edx-platform#33310
@Cup0fCoffee I have added the documentation to the relevant section and create a PR. |
64955f5
to
ca81ca5
Compare
…tion A new flag was introduced in the LTI Consumer configuration which allows automatically linking LTI users with the edX platform users by matching the email ID. This commit describes the purpose of the flag with its caveats. Ref: openedx/edx-platform#33310
ca81ca5
to
7d7e101
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tecoholic, it took me a while to set up Canvas and learn the way around it. Two main issues I encountered while testing this:
- Permission errors after starting Canvas. (solution)
- Canvas generates identical GUIDs for the Open edX LTI Consumers. The GUID has precedence over the client_id while retrieving the correct consumer, so I had to manually remove this value from the consumer after each LTI launch.
I like this solution - it's clean and straightforward. But...
Assumption: none of your Canvas users has staff or superuser permissions in Open edX.
Let's say somebody gains unauthorized access to your admin account of the Canvas instance. They can modify the email address to be anything without any confirmation. This way, they can send any value in the lis_person_contact_email_primary
, thus impersonating any user in the Open edX.
This might be an acceptable risk for instances managed by a single organization, but it can be dangerous for multi-org instances.
For a comparison, when you try to use SAML or OAuth2 with an email already bound to an Open edX account, you are redirected to the login page. When you log in (with your password or an already confirmed TPA), the UserSocialAuth
account is linked to your main account.
Could we utilize the LTIProviderConfig
from the third_party_auth
app to use this existing mechanism?
@cmltaWt0 Hi, we were trying to get this into Quince. But discovered a potential security issue and are working on updating the PR to handle it. I will create a backport and add it to the backport list once this goes through. Just wanted to give you a heads-up and see if you have any concerns. |
3b2fd80
to
c8ad65e
Compare
@Agrendalath Hi, after exploring multiple avenues, I think I have a fair solution here. The important changes are:
Testing Tips:
from .common import FEATURES, INSTALLED_APPS, AUTHENTICATION_BACKENDS
FEATURES['ENABLE_LTI_PROVIDER'] = True
INSTALLED_APPS.append('lms.djangoapps.lti_provider.apps.LtiProviderConfig')
AUTHENTICATION_BACKENDS.append('lms.djangoapps.lti_provider.users.LtiBackend')
SESSION_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE_FORCE_ALL = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'None'
# Needed for showing pages in iframe
X_FRAME_OPTIONS = "ALLOW-FROM canvas.docker"
# These are probably not needed
ENABLE_CORS_HEADERS = True
ENABLE_CROSS_DOMAIN_CSRF_COOKIE = True
DCS_SESSION_COOKIE_SAMESITE = 'None'
DCS_SESSION_COOKIE_SECURE = True
DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL = True Kindly review and see if the security concerns are addressed. I might have inadvertently created more with the cookie permissions, but they can be mitigated by launching on new tab. But everything have been tested in iframe to ensure we are not forcing a new tab on the learner for anything apart from the "Sign in". |
Sandbox deployment successful. Sandbox LMS is available at pr-33310-139931.staging.do.opencraft.hosting |
1 similar comment
Sandbox deployment successful. Sandbox LMS is available at pr-33310-139931.staging.do.opencraft.hosting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tecoholic, I'm trying to understand why we need to change these cookie settings now. The previous approach worked correctly without these changes. What did we change that requires this? Does it mean that the user switching functionality has not been working correctly since the default cookie behavior was altered in the browsers?
didn't work as the OAuth signature validation kept failing.
Maybe it's not the best approach, but I usually just turn this validation off by making the validation functions return True
in the devstack.
Sandbox update request received. Deployment will start soon. |
The user-switching was working before because, the
We need to change the cookie settings now, as we need to be able to authenticate the user who logged in outside the Iframe. |
Sandbox deployment failed. Check failure logs here https://grove-stage-build-logs.nyc3.digitaloceanspaces.com/34602668-5445942825.log Please check the settings and requirements and retry deployment by updating the pull request or posting a |
Sandbox deployment started. |
lms/djangoapps/lti_provider/users.py
Outdated
lti_user.edx_user != request.user | ||
): | ||
lti_user.edx_user = request.user | ||
lti_user.save() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tecoholic, let's assume we have Alice and Bob who are the learners. Is the following scenario correct?
- Alice has already used LTI, so her Canvas and Open edX accounts are linked.
- Bob used a shared computer in a classroom and left his Open edX account logged in.
- Alice uses the same shared computer, logs into Canvas, and goes to a Canvas page with the LTI content from Open edX.
- We have one of the following outcomes:
- If Bob had used LTI before, this raises an
IntegrityError
(due to the'lti_consumer', 'lti_user_id'
uniqueness violation). - Otherwise, Bob's account is accidentally "hijacked" by Alice.
- Bob's account will get re-linked again (to the correct account) the next time he uses the LTI, but it is still a security concern.
- If Bob had used LTI before, this raises an
In this scenario, we want to switch the Open edX user to the one linked to the LtiUser
(with the switch_user
function).
The only real-world usage I can think of for re-linking the accounts is moving the existing (automatically created) LTI users to "real" Open edX accounts after enabling an existing provider's require_user_account
option. If this is our goal, we should verify if the User
's email ends with settings.LTI_USER_EMAIL_DOMAIN
. However, all existing progress of such users will be lost this way, so we should be sure that we want to do this (instead of, e.g., changing the emails of their automatically created accounts).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Agrendalath First up, I am just astounded at how many of the issues I miss and you catch. And I entirely understand that's the function of the work-review cycle and really appreciate it.
And yes, the only real reason to switch the user here is to make sure we don't have a mix of real users and anonymous users on a client if/when the flag is turned on. I had my reservations about it, but this is something I totally missed
However, all existing progress of such users will be lost this way, so we should be sure that we want to do this
So, I think it is best to remove the re-linking part now. I will update the PR.
With this change the platform users who access content via LTI will automatically be linked their platform account instead of the anonymous account when the following conditions are met: * the LtiConsumer should be configured to auto link the users via email * the LTI Consumer should share the email of the user using the lis_person_contact_email_primary parameter in the LTI Launch POST data Internal-ref: https://tasks.opencraft.com/browse/BB-7875
With the auto linking of edx_user with the lti_users, the scenario where multiple LTI consumers will create independent LtiUsers depending on the same edx_user is created. This will not be possible if the edx_user has a one-to-one relationship with the lti_user. This commit replaces the one-to-one relationship with an one-to-many relationship so that multiple LtiUser objects can be created referencing the same edx_user.
Co-authored-by: Piotr Surowiec <[email protected]>
1452aa2
to
2fb1a06
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, @tecoholic!
👍
- I tested this: linking existing Open edX accounts with the ones from LTI
- I read through the code
- I checked for accessibility issues: n/a
- Includes documentation: docs: adds note about the auto linking flag in LTI Consumer configuration edx-documentation#2190
@tecoholic 🎉 Your pull request was merged! Please take a moment to answer a two question survey so we can improve your experience in the future. |
…tion A new flag was introduced in the LTI Consumer configuration which allows automatically linking LTI users with the edX platform users by matching the email ID. This commit describes the purpose of the flag with its caveats. Ref: openedx/edx-platform#33310
2U Release Notice: This PR has been deployed to the edX staging environment in preparation for a release to production. |
2U Release Notice: This PR has been deployed to the edX production environment. |
Description
The LTI Provider feature of the platform currently allows accessing content from other LMS systems only as an anonymous user. Technically, there is support for using LTI Authentication, which can be used for non-anonymous use case. However, this seems to have been built with Blackboad integration in mind (see section "Authentication & User Provisioning") and doesn't work with Canvas when tested.
Furthermore, the LTI Launch view and the auth mechanism do not consider the existing logged-in user and switch over to the anonymous user account when accessing content over LTI.
For organizations that use multiple LMS, this creates the issue of the grades and outcomes of users not being linked to their accounts despite having an account on the Open edX Platform.
This PR tries to bridge the gap by introducing an opt-in flag that can be set on the LtiConsumer configurations that will allow linking existing users to the actions performed via LTI. The auto-linking of the
edx_user
and thelti_user
is performed when the following conditions are met:Require user account
checkbox enabled.lis_person_contact_email_primary
during the LTI launch and an user account with the same email already exists in the platform.Who does this change affect?
Screenshots
A new flag is now added to the Admin UI of the LTI Consumer model.
Configuration Changes
Since the LTI Provider is already behind the
ENABLE_LTI_PROVIDER
feature flag, and the auto-linking introduced here is only enabled with an explicit flag included in the PR, no other configuration has been introduced/changed.Supporting information
lis_person_contact_email_primary
optional parameter used in this PR to perform auto-linking.Testing instructions
NOTE: This has been tested only with Canvas LMS. Technically, it should be possible to test this with any LTI Consumer that sends the user's email using the
lis_person_contact_email_primary
parameter in the LTI launch request's POST data.Setting up the platform
data-usage-id
) of an XBlock.Setting up Canvas
+ App
to add a new app.http(s)://<your-domain>/lti_provider/courses/<course_id>/<usage_id>
Testing the changes
Without auto-linking (existing functionality)
test_one
and accept the course assignment.With auto-linking (introduced in this PR)
test_two
and accept the course assignment, open the section with the XBlock../manage.py lms shell
Deadline
"None" if there's no rush, or provide a specific date or event (and reason) if there is one.
Other information
lis_person_contact_primary_email
feels like unnecessary as addressing the issues with the broken LTI Authentication mechanism mentioned earlier in the description should have this working out of the box. However, it was discovered during the investigation that theLtiUser
in only ever created from thelti_launch
view (also noted by @ztraboo in the forum comment here). This means, in order for the auto-linking to work, on top of fixing the LTI Authentication, we will still need to modify theLtiUser
creation logic, which this PR handles.