From 13651603cff39c52876ca61c11bf0fca87e1f10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Wed, 13 Sep 2023 01:01:32 +0000 Subject: [PATCH 1/8] feat: Add LTI profile user with PII data ADR --- ...-create-lti-profile-user-with-pii-data.rst | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 docs/decisions/0001-create-lti-profile-user-with-pii-data.rst diff --git a/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst b/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst new file mode 100644 index 0000000..18b4d1b --- /dev/null +++ b/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst @@ -0,0 +1,161 @@ +PADV-683: Create LTI profile user with PII data +=============================================== + +Status +====== + +In progress. + +Discovery +========= + +Currently, the LTI tool plugin doesn't make use of the PII data to handle user +authentication on the LMS, we should have a mechanism that could use PII data +(email, name) to log in to an existing user on the LMS. This will require to +modify the current mechanism that handles the retrieval of the LTI profile +user so it's able to use PII data to authenticate and relate it to a +LTI profile, we need to create a discovery in which we analyze the security +risks of allowing such behavior and possible approaches to create this feature. + +Approach +======== + +PII user authentication permission +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There should be a mechanism to determine if the requested user on the PII +data is allowed to log in using the LTI authentication backend, for this +there are various options: + +1. Create a model where we set the users that should be allowed to log in + per tool, similar to the course access configuration model, this could + be a list of users or a list of groups that should be allowed per tool. +2. Add a group or permission that can be set to each user, if that group + or permission is set, then the user is allowed to authenticate from the + LTI authentication backend. + +LTI profile modifications +~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Change the user field on LtiProfile from a OneToOneField to a + ForeignKeyField, with this we remove the uniqueness of users with LtiProfile, + with this we can allow a set of iss, aud, and sub claims to have more than one + possible user. + + user = models.ForeignKey( + get_user_model(), + on_delete=models.CASCADE, + related_name='openedx_lti_tool_plugin_lti_profile', + verbose_name=_('Open edX user'), + editable=False, + ) + +- Modify the unique_together and indexes on the LtiProfile model to include the + user field. + + unique_together = ['platform_id', 'client_id', 'subject_id', 'user'] + indexes = [ + models.Index( + fields=['platform_id', 'client_id', 'subject_id', 'user'], + name='lti_profile_identity', + ), + ] + +- Add a method to generate a URL from iss, aud, sub values and use it to + generate a UUID5 for the LtiProfile instance. We will use this ID on + the auto-generated user, with this we will make sure that it isn't + possible to create more than one auto-generated user for a LtiProfile. + (This mechanism was also used on the LTI tool implementation of content + libraries to generate the UUID of the LTI profile). + + @property + def subject_url(self) -> str: + """An local URL that is known to uniquely identify this profile. + + Returns: + Unique URL string with profile claims. + """ + return '/'.join([ + self.platform_id.rstrip('/'), + str(self.client_id), + str(self.subject_id), + ]) + + def save(self, *args: tuple, **kwargs: dict): + ... + uid = uuid.uuid5(uuid.NAMESPACE_URL, self.subject_url) + self.user, created = get_user_model().objects.get_or_create( + username=f'{USERNAME_PREFIX}{uid}', + email=f'{uid}@{app_config.name}', + ) + +- Modify the get_from_claims method on the LtiProfileManager to allow it + receive an optional parameter with the user email, with this we will + allow to get a LtiProfile by a specific user instead of the + auto-generated user. + + USERNAME_PREFIX = f'urn:openedx:{app_config.name}:username:' + + identity_claims = {'platform_id': iss, 'client_id': aud, 'subject_id': sub} + + if user: + return self.filter(**identity_claims, user=user).first() + + return self.filter(**identity_claims, user__username__startswith=USERNAME_PREFIX).first() + +- Modify the get_or_create_from_claims to be able to receive a user argument + to allow it to send it to the get_from_claims method or create a new LtiProfile + with thae specific user sent. + + lti_profile = self.get_from_claims(iss=iss, aud=aud, sub=sub, user=user) + + if lti_profile: + return lti_profile, False + + return self.create(platform_id=iss, client_id=aud, subject_id=sub, user=user), True + +LTI Launch View and LTI authentication backend modifications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Modify the LtiAuthenticationBackend authenticate method to receive an + optional user argument. +- Modify the call to get_from_claims on the LtiAuthenticationBackend + authenticate method to receive the optional user argument. + + try: + profile = LtiProfile.objects.get_from_claims(iss=iss, aud=aud, sub=sub, user=user) + except LtiProfile.DoesNotExist: + return None + +- Add a method to the LTI launch view that will validate if the user related + to the email sent on the PII data is allowed to be associated to an LTI + profile, if is allowed, return the user model. + + # Get PII email and retrieve user if allowed. + email = launch_data.get('email') + edx_user = self.get_user_from_email(email) + +- Modify the authenticate_and_login and get_or_create_from_claims method to be + able to receive an optional user parameter. + + # Authenticate and login LTI profile user. + lti_profile = LtiProfile.objects.get_or_create_from_claims(iss=iss, aud=aud, sub=sub, user=edx_user) + edx_user = self.authenticate_and_login(request, iss, aud, sub, edx_user) + +Allowed login with PII data custom parameter (optional): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We could also add a custom parameter (this could be set either from the XBlock +custom parameter or the extra claims) that will determine if the XBlock should +use the PII data login mechanism: + + ["pii_login=true"] + +If the custom parameter isn't present on launch or is set to false, the LTI +tool will proceed to execute a regular LTI launch without trying to create a +LTI profile with the requested user email. + +References +========== + +- LTI 1.3 Content Libraries LTI profile subject_url method: https://github.com/openedx/edx-platform/pull/27411/files#diff-36022deef8607c7a4647c8f2620b4d9ed283d5b41077e966bfd097585e0ebe7cR361 From 9e19d73da25f126b2963f3a8ff68b262cc549731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Thu, 14 Sep 2023 17:59:41 +0000 Subject: [PATCH 2/8] feat: PII data on LTI profile approach --- ...-create-lti-profile-user-with-pii-data.rst | 148 +++++++++++++++--- 1 file changed, 127 insertions(+), 21 deletions(-) diff --git a/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst b/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst index 18b4d1b..ef9b560 100644 --- a/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst +++ b/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst @@ -1,27 +1,132 @@ +############################################### PADV-683: Create LTI profile user with PII data -=============================================== +############################################### +###### Status -====== +###### In progress. +######### Discovery -========= +######### + +Currently, the LTI tool plugin doesn't make use of PII data, we should have +a mechanism that could use PII data (email, name) to store it so we can have +a track of the user executing the LTI launch, we could also have a mechanism +that could use PII data (email, name) to log in to an existing user on the +LMS. This will require to modify the current mechanism that handles the +retrieval of the LTI profile user so it's able to use PII data to authenticate +and relate it to an LTI profile, we need to create a discovery in which we +analyze the security risks of allowing such behavior and possible approaches +to create this feature. + +######## +Approach +######## -Currently, the LTI tool plugin doesn't make use of the PII data to handle user -authentication on the LMS, we should have a mechanism that could use PII data -(email, name) to log in to an existing user on the LMS. This will require to -modify the current mechanism that handles the retrieval of the LTI profile -user so it's able to use PII data to authenticate and relate it to a -LTI profile, we need to create a discovery in which we analyze the security -risks of allowing such behavior and possible approaches to create this feature. +*********************** +PII data on LTI profile +*********************** -Approach -======== +We could save PII data (email, name) on the LTI profile, this will allow +us to keep track of the identity (apart from the iss, aud, and sub claims) +of the user executing the LTI launch. Currently the LTI profile fields +represent a unique identity of a user executing a launch, being the sub +(subject_id) the user ID of the user in the external platform. + +LTI profile modifications +========================= + +- Add a email and name field to the LTI profile model: + + email = models.CharField( + max_length=255, + blank=True, + verbose_name=_('Email'), + help_text=_('Profile email.'), + ) + name = models.CharField( + max_length=255, + blank=True, + verbose_name=_('Name'), + help_text=_('Profile name.'), + ) + +- Modify the get_or_create_from_claims method to receive an optional name and + email parameter, if the LTI profile is being created the PII data is used. + + def get_or_create_from_claims(self, iss, aud, sub, email=None, name=None): + try: + return self.get_from_claims(iss=iss, aud=aud, sub=sub), False + except self.model.DoesNotExist: + return self.create( + platform_id=iss, + client_id=aud, + subject_id=sub, + email=email, + name=name, + ), True + +- Modify the save method to allow it use the name field on the user creation. + + def save(self, *args: tuple, **kwargs: dict): + ... + + with transaction.atomic(): + # Create edx user. + self.user = get_user_model().objects.create( + username=f'{app_config.name}.{self.uuid}', + email=f'{self.uuid}@{app_config.name}', + ) + self.user.set_unusable_password() # LTI users can only auth through LTI launches. + self.user.save() + + # Create edx user profile. + profile = user_profile()(user=self.user, name=self.name) + profile.save() + + return super().save(*args, **kwargs) + +LTI launch view modifications +============================= + +- We will retrieve the PII data and send it to the get_or_create_from_claims +method of the LTI profile, if the LTI profile is being created the PII data +will be used on the model. + +- Create a function that will receive a dict with PII data, the function will +verify if the PII value requested for update exists and has changed, if so +then we will update it and save the LTI profile. + + def update_pii_data(pii_data: dict, lti_profile: LtiProfile): + update_fields = [] + + for field, value in pii_data.items(): + if value and value != getattr(lti_profile, field, ''): + setattr(lti_profile, field, value) + update_fields.append(field) + + lti_profile.save(update_fields=update_fields) + + email = launch_data.get('email') + name = launch_data.get('name') + update_pii_data({'email': email, 'name': name}, lti_profile) + +LTI profile post-save signal +============================ + +- Create a post-save signal on the LTI profile that will check if the PII data + changed, if the PII data changed, update the name of the LTIP profile user + and user profile. + +********************************** +User authentication using PII data +********************************** PII user authentication permission -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +================================== There should be a mechanism to determine if the requested user on the PII data is allowed to log in using the LTI authentication backend, for this @@ -35,11 +140,11 @@ there are various options: LTI authentication backend. LTI profile modifications -~~~~~~~~~~~~~~~~~~~~~~~~~ +========================= - Change the user field on LtiProfile from a OneToOneField to a ForeignKeyField, with this we remove the uniqueness of users with LtiProfile, - with this we can allow a set of iss, aud, and sub claims to have more than one + with this, we can allow a set of iss, aud, and sub claims to have more than one possible user. user = models.ForeignKey( @@ -105,7 +210,7 @@ LTI profile modifications - Modify the get_or_create_from_claims to be able to receive a user argument to allow it to send it to the get_from_claims method or create a new LtiProfile - with thae specific user sent. + with the specific user sent. lti_profile = self.get_from_claims(iss=iss, aud=aud, sub=sub, user=user) @@ -115,7 +220,7 @@ LTI profile modifications return self.create(platform_id=iss, client_id=aud, subject_id=sub, user=user), True LTI Launch View and LTI authentication backend modifications -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +============================================================ - Modify the LtiAuthenticationBackend authenticate method to receive an optional user argument. @@ -128,8 +233,8 @@ LTI Launch View and LTI authentication backend modifications return None - Add a method to the LTI launch view that will validate if the user related - to the email sent on the PII data is allowed to be associated to an LTI - profile, if is allowed, return the user model. + to the email sent on the PII data is allowed to be associated with an LTI + profile, if allowed, return the user model. # Get PII email and retrieve user if allowed. email = launch_data.get('email') @@ -143,7 +248,7 @@ LTI Launch View and LTI authentication backend modifications edx_user = self.authenticate_and_login(request, iss, aud, sub, edx_user) Allowed login with PII data custom parameter (optional): -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +======================================================== We could also add a custom parameter (this could be set either from the XBlock custom parameter or the extra claims) that will determine if the XBlock should @@ -155,7 +260,8 @@ If the custom parameter isn't present on launch or is set to false, the LTI tool will proceed to execute a regular LTI launch without trying to create a LTI profile with the requested user email. +########## References -========== +########## - LTI 1.3 Content Libraries LTI profile subject_url method: https://github.com/openedx/edx-platform/pull/27411/files#diff-36022deef8607c7a4647c8f2620b4d9ed283d5b41077e966bfd097585e0ebe7cR361 From 0c4cbc022e5a24882de4c3d7b0c9738196e429ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Thu, 14 Sep 2023 22:56:31 +0000 Subject: [PATCH 3/8] doc: Improve PII data ADR --- ...a.rst => 0001-pii-data-on-lti-profile.rst} | 125 +++++++++--------- 1 file changed, 64 insertions(+), 61 deletions(-) rename docs/decisions/{0001-create-lti-profile-user-with-pii-data.rst => 0001-pii-data-on-lti-profile.rst} (74%) diff --git a/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst b/docs/decisions/0001-pii-data-on-lti-profile.rst similarity index 74% rename from docs/decisions/0001-create-lti-profile-user-with-pii-data.rst rename to docs/decisions/0001-pii-data-on-lti-profile.rst index ef9b560..e83133f 100644 --- a/docs/decisions/0001-create-lti-profile-user-with-pii-data.rst +++ b/docs/decisions/0001-pii-data-on-lti-profile.rst @@ -1,6 +1,6 @@ -############################################### -PADV-683: Create LTI profile user with PII data -############################################### +######################################### +PADV-683: Use PII data on the LTI profile +######################################### ###### Status @@ -13,24 +13,24 @@ Discovery ######### Currently, the LTI tool plugin doesn't make use of PII data, we should have -a mechanism that could use PII data (email, name) to store it so we can have -a track of the user executing the LTI launch, we could also have a mechanism -that could use PII data (email, name) to log in to an existing user on the -LMS. This will require to modify the current mechanism that handles the -retrieval of the LTI profile user so it's able to use PII data to authenticate -and relate it to an LTI profile, we need to create a discovery in which we -analyze the security risks of allowing such behavior and possible approaches -to create this feature. +a mechanism that could use PII data to store it so we can have a track of the +user executing the LTI launch, and use it to personalize the Open edX profile +information, we could also have a mechanism that could use PII data to log in +to an existing user on the LMS. This will require to modify the current +mechanism that handles the retrieval of the LTI profile user so it's able to +use PII data to authenticate and relate it to an LTI profile, we need to create +a discovery in which we analyze the security risks of allowing such behavior +and possible approaches to create this feature. ######## Approach ######## -*********************** -PII data on LTI profile -*********************** +**************************** +Save PII data on LTI profile +**************************** -We could save PII data (email, name) on the LTI profile, this will allow +We could save PII data on the LTI profile, this will allow us to keep track of the identity (apart from the iss, aud, and sub claims) of the user executing the LTI launch. Currently the LTI profile fields represent a unique identity of a user executing a launch, being the sub @@ -39,25 +39,27 @@ represent a unique identity of a user executing a launch, being the sub LTI profile modifications ========================= -- Add a email and name field to the LTI profile model: +- Add a pii_data JSON field to the LTI profile model: - email = models.CharField( + pii_data = models.JSONField( max_length=255, - blank=True, - verbose_name=_('Email'), - help_text=_('Profile email.'), - ) - name = models.CharField( - max_length=255, - blank=True, - verbose_name=_('Name'), - help_text=_('Profile name.'), + default={}, + verbose_name=_('PII Data'), + help_text=_('JSON with user PII data.'), ) -- Modify the get_or_create_from_claims method to receive an optional name and - email parameter, if the LTI profile is being created the PII data is used. +- Modify the get_or_create_from_claims method to receive an optional pii_data + parameter, if the LTI profile is being created the PII data is used. - def get_or_create_from_claims(self, iss, aud, sub, email=None, name=None): + pii_data = { + 'email': launch_data.get('email'), + 'name': launch_data.get('name'), + 'given_name': launch_data.get('given_name'), + 'family_name': launch_data.get('family_name'), + 'locale': launch_data.get('locale'), + } + + def get_or_create_from_claims(self, iss, aud, sub, pii_data={}): try: return self.get_from_claims(iss=iss, aud=aud, sub=sub), False except self.model.DoesNotExist: @@ -65,66 +67,67 @@ LTI profile modifications platform_id=iss, client_id=aud, subject_id=sub, - email=email, - name=name, + pii_data=pii_data, ), True -- Modify the save method to allow it use the name field on the user creation. +LTI launch view modifications +============================= + +- Create a function that will receive a dict with PII data, the function will + verify if the PII data changed, if the PII data changed, update the LTI + profile with the new PII data: + + def update_pii_data(pii_data: dict, lti_profile: LtiProfile): + if pii_data and pii_data != lti_profile.pii_data: + lti_profile.pii_data = pii_data + lti_profile.save() + +******************************** +Use PII data on LTI profile user +******************************** + +We could use the PII data stored on the LTI profile to save it in the LTI +profile related user and the related user Open edX profile. + +LTI profile modifications +========================= + +- Modify the save method to allow it to use the PII data on the user creation. def save(self, *args: tuple, **kwargs: dict): ... - with transaction.atomic(): # Create edx user. self.user = get_user_model().objects.create( username=f'{app_config.name}.{self.uuid}', email=f'{self.uuid}@{app_config.name}', + first_name=self.pii_data.get('given_name'), + last_name=self.pii_data.get('family_name'), ) self.user.set_unusable_password() # LTI users can only auth through LTI launches. self.user.save() # Create edx user profile. - profile = user_profile()(user=self.user, name=self.name) + profile = user_profile()(user=self.user, name=self.pii_data.get('name')) profile.save() return super().save(*args, **kwargs) -LTI launch view modifications -============================= - -- We will retrieve the PII data and send it to the get_or_create_from_claims -method of the LTI profile, if the LTI profile is being created the PII data -will be used on the model. - -- Create a function that will receive a dict with PII data, the function will -verify if the PII value requested for update exists and has changed, if so -then we will update it and save the LTI profile. - - def update_pii_data(pii_data: dict, lti_profile: LtiProfile): - update_fields = [] - - for field, value in pii_data.items(): - if value and value != getattr(lti_profile, field, ''): - setattr(lti_profile, field, value) - update_fields.append(field) - - lti_profile.save(update_fields=update_fields) - - email = launch_data.get('email') - name = launch_data.get('name') - update_pii_data({'email': email, 'name': name}, lti_profile) - LTI profile post-save signal ============================ - Create a post-save signal on the LTI profile that will check if the PII data - changed, if the PII data changed, update the name of the LTIP profile user - and user profile. + changed, if the PII data changed, update the data of the LTIP profile user + and user profile using the PII data. ********************************** User authentication using PII data ********************************** +We could use the email received on the PII data to allow the creation of LTI +profiles with users related to the requested email instead of the +auto-generated LTI profile user. + PII user authentication permission ================================== From 07edf5f50afa9dcd33980aa44df23c2cd043743d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Fri, 15 Sep 2023 16:06:35 +0000 Subject: [PATCH 4/8] doc: Remove LTI launch view example --- docs/decisions/0001-pii-data-on-lti-profile.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/decisions/0001-pii-data-on-lti-profile.rst b/docs/decisions/0001-pii-data-on-lti-profile.rst index e83133f..afcaf07 100644 --- a/docs/decisions/0001-pii-data-on-lti-profile.rst +++ b/docs/decisions/0001-pii-data-on-lti-profile.rst @@ -77,11 +77,6 @@ LTI launch view modifications verify if the PII data changed, if the PII data changed, update the LTI profile with the new PII data: - def update_pii_data(pii_data: dict, lti_profile: LtiProfile): - if pii_data and pii_data != lti_profile.pii_data: - lti_profile.pii_data = pii_data - lti_profile.save() - ******************************** Use PII data on LTI profile user ******************************** From 12dd64d7e681fb33b2a5065bda16be60247cf544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Fri, 15 Sep 2023 16:22:09 +0000 Subject: [PATCH 5/8] docs: Improve LTI launch view example --- docs/decisions/0001-pii-data-on-lti-profile.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/decisions/0001-pii-data-on-lti-profile.rst b/docs/decisions/0001-pii-data-on-lti-profile.rst index afcaf07..c8ebc1e 100644 --- a/docs/decisions/0001-pii-data-on-lti-profile.rst +++ b/docs/decisions/0001-pii-data-on-lti-profile.rst @@ -77,6 +77,17 @@ LTI launch view modifications verify if the PII data changed, if the PII data changed, update the LTI profile with the new PII data: + def update_pii_data(pii_data, lti_profile): + updated_pii_data = {**lti_profile.pii_data} + + for field, value in pii_data.items(): + if value != current_pii_data.get(field): + updated_pii_data.update({field: value}) + + if updated_pii_data != lti_profile.pii_data: + lti_profile.pii_data = updated_pii_data + lti_profile.save() + ******************************** Use PII data on LTI profile user ******************************** From 0780ecdde431e7b1e411cc9cd7997b2444c28b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Fri, 15 Sep 2023 16:28:25 +0000 Subject: [PATCH 6/8] docs: Update references --- docs/decisions/0001-pii-data-on-lti-profile.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/decisions/0001-pii-data-on-lti-profile.rst b/docs/decisions/0001-pii-data-on-lti-profile.rst index c8ebc1e..83bb169 100644 --- a/docs/decisions/0001-pii-data-on-lti-profile.rst +++ b/docs/decisions/0001-pii-data-on-lti-profile.rst @@ -273,4 +273,5 @@ LTI profile with the requested user email. References ########## -- LTI 1.3 Content Libraries LTI profile subject_url method: https://github.com/openedx/edx-platform/pull/27411/files#diff-36022deef8607c7a4647c8f2620b4d9ed283d5b41077e966bfd097585e0ebe7cR361 +1. LTI 1.3 User Identity claims: https://www.imsglobal.org/spec/lti/v1p3#user-identity-claims +2. LTI 1.3 Content Libraries LTI profile subject_url method: https://github.com/openedx/edx-platform/pull/27411/files#diff-36022deef8607c7a4647c8f2620b4d9ed283d5b41077e966bfd097585e0ebe7cR361 From ea4bb66e2032e5a39dad83f1e7563fd9c22ef3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Fri, 15 Sep 2023 16:29:32 +0000 Subject: [PATCH 7/8] docs: Update ADR --- docs/decisions/0001-pii-data-on-lti-profile.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/decisions/0001-pii-data-on-lti-profile.rst b/docs/decisions/0001-pii-data-on-lti-profile.rst index 83bb169..eb050a1 100644 --- a/docs/decisions/0001-pii-data-on-lti-profile.rst +++ b/docs/decisions/0001-pii-data-on-lti-profile.rst @@ -42,7 +42,6 @@ LTI profile modifications - Add a pii_data JSON field to the LTI profile model: pii_data = models.JSONField( - max_length=255, default={}, verbose_name=_('PII Data'), help_text=_('JSON with user PII data.'), From dd337400f1a33c327a853d6c71a3783b770bca6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Montilla?= Date: Fri, 15 Sep 2023 16:50:31 +0000 Subject: [PATCH 8/8] docs: Update ADR --- docs/decisions/0001-pii-data-on-lti-profile.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/decisions/0001-pii-data-on-lti-profile.rst b/docs/decisions/0001-pii-data-on-lti-profile.rst index eb050a1..3d8999a 100644 --- a/docs/decisions/0001-pii-data-on-lti-profile.rst +++ b/docs/decisions/0001-pii-data-on-lti-profile.rst @@ -39,12 +39,16 @@ represent a unique identity of a user executing a launch, being the sub LTI profile modifications ========================= +- Create a JSON schema validator to validate the pii_field data. This validator + will check that any known PII fields are of the correct type and structure + (Example: email field in PII data is a correct email address). - Add a pii_data JSON field to the LTI profile model: pii_data = models.JSONField( default={}, verbose_name=_('PII Data'), help_text=_('JSON with user PII data.'), + validators=[pii_data_schema_validator], ) - Modify the get_or_create_from_claims method to receive an optional pii_data @@ -129,6 +133,8 @@ LTI profile post-save signal User authentication using PII data ********************************** +NOTE: THIS IMPLEMENTATION IS STILL A WORK IN PROGRESS. + We could use the email received on the PII data to allow the creation of LTI profiles with users related to the requested email instead of the auto-generated LTI profile user. @@ -273,4 +279,5 @@ References ########## 1. LTI 1.3 User Identity claims: https://www.imsglobal.org/spec/lti/v1p3#user-identity-claims -2. LTI 1.3 Content Libraries LTI profile subject_url method: https://github.com/openedx/edx-platform/pull/27411/files#diff-36022deef8607c7a4647c8f2620b4d9ed283d5b41077e966bfd097585e0ebe7cR361 +2. JSON Schema Documentation: https://python-jsonschema.readthedocs.io/en/stable/ +3. LTI 1.3 Content Libraries LTI profile subject_url method: https://github.com/openedx/edx-platform/pull/27411/files#diff-36022deef8607c7a4647c8f2620b4d9ed283d5b41077e966bfd097585e0ebe7cR361