...
The goal of this project is to replace the current vendor for identity verification (IDV) on edx.org, Software Secure, with a new vendor, Persona. On edx.org, IDV is used solely for verifying certain name changes requested by certificate-bearing learners via the Name Affirmation feature in the frontend-app-account MFE, but IDV may be used for other purposes in the Open edX community (e.g. to block generation of a verified certificate).
We propose leveraging the various extensibility mechanisms that the platform supports, but we need guidance around how “pluggable” the solution must be and what IDV-related community needs must be met, particularly since 2U uses IDV for a smaller set of features than the platform currently supports.
Problem
The backend implementation of IDV is in the edx-platform verify_student Django application, and the frontend implementation of IDV and the Name Affirmation feature that uses IDV is in the frontend-app-learning MFE and frontend-app-account MFE, respectively. All . The backend implementation of Name Affirmation is in the edx-name-affirmation plugin. The first three repositories are in the openedx
GitHub organization and are a part of the Open edX platform.
We propose an integration approach that balances the needs of 2U and the community. We propose leveraging the various extensibility mechanisms that the platform supports, but we need guidance around how “pluggable” the solution must be and what IDV-related community needs must be met, particularly since 2U uses IDV for a smaller set of features than the platform currently supports.
There are also parts of the verify_student application that have an unclear purpose and may have limited need in the community save for an operator or two. For example, the ReverifyView does not appear to be used anywhere. We do not have the bandwidth to do deprecation at this time, but it would be helpful to know which parts of the codebase are core and which are unused legacy code.
Use Cases
...
edx-name-affirmation is in the edx
GitHub organization but it is installed into the platform.
The problem that we are solving is adding the necessary extensibility mechanism to the platform to make IDV generic such that additional IDV implementations can be added to the platform seamlessly and without disruption to the core.
Use Cases
As an Open edX operator or developer, I do not want to have to navigate through vendor or implementation specific IDV code in the core.
As an Open edX operator or developer, I need to be able to integrate an IDV implementation into the platform with no disruption to other Open edX instances or the core, because I need to verify learners' identities. I need to be able to integrate whichever IDV implementation that suits my needs.
As a learner who has earned a certificate, I need to be able to verify my identity after requesting a name change, because this validates that I am who I say I am. This maintains the value of a certificate and ensures that the certificate is attributable to me.
As a learner who has purchased a verifiable course mode, I need to be able to verify my identity so that I can receive a “verified certificate” when I meet the requirements for earning one.
As an Open edX installation operator, I need to be able to integrate an IDV implementation into the platform with no disruption to other Open edX instances, because I need to verify learners' identities so that they can earn verified certificates. I need to be able to integrate whichever IDV implementation that suits my needs.
Proposed Solution
Our proposed solution involves three categories of changes.
Proposed Solution
Our proposed solution involves three categories of changes.
Backend Extensibility Mechanisms
...
Generic Model
In order for the platform to continue to function with respect to the edx-platform verify_student Django application .
Filter Hooks
We propose integrating filter hooks into the IDVerificationService. The IDVerificationService serves as an interface to the verify_student Django application and is used throughout the platform. Callers of this service primarily use it to read data from the IDV related models and to get the URL to the IDV flow.
We propose the following two filters, which will enable full integration of the IDVerificationService with additional IDV implementations.
IDVerificationAttemptsRequested(verifications, uuids, users, statuses)
This filter hook will be used to read IDV records from plugins. This will allow Open edX operators to expose supplemental IDV records to the platform via the IDVerificationService.
The uuids
, users
, and statuses
parameters are intended to be iterables of values to filter the IDV records by, corresponding to the uuid
, user.id
and status
fields of the IDVerificationAttempt model, which is the abstract base class that SoftwareSecurePhotoVerification (via PhotoVerification), SSOVerification, and ManualVerification inherit from. As a note uuid
is not currently a field on the IDVerificationAttempt model; our proposal for its addition is discussed in Refactoring.
verifications
in intended to be an iterable of data class instances that represent IDV records. We propose replacing the use of model instances in the IDVerificationService with data classes. Using data classes will avoid exposing data models outside the verify_student Django application, as encouraged by OEP-49: Django App Patterns.
An app’s Django models and other internal data structures should not be exposed via its Python APIs (unless performance requires it).
Using data classes will also simplify the integration of additional IDV implementations by decoupling the verify_student data model from the data model of additional IDV implementations. Because plugins cannot and likely should not import the IDVerificationAttempt model to use as a parent class, if we continue to use model instances, any additional IDV models must replicate the database schema used by the IDVerificationAttempt model.
The IDVerificationService uses some additional database level filters (e.g. created_at__gt) that would not be supported by this filter. To avoid needing to support additional filter parameters, we propose only supporting querying by a select few fields and doing any additional querying in Python code. This will require some additional lightweight refactoring.
IDVerificationURLRequested(url)
This filter hook will be used to fetch the URL to the IDV flow. This will allow operators to override the URL to the IDV flow.
Event Hooks
We propose introducing event hooks related to the IDV attempt lifecycle. Taking the EXAM_ATTEMPT_*
Open edX events as a model, we propose introducing one Open edX event per IDV status.
IDV_ATTEMPT_CREATED
IDV_ATTEMPT_READY
IDV_ATTEMPT_SUBMITTED
IDV_ATTEMPT_MUST_RETRY
IDV_ATTEMPT_APPROVED
IDV_ATTEMPT_DENIED
It’s worth noting that the statuses of the IDVerificationAttempt model may not be entirely generic. The statuses are somewhat specific to Software Secure. As an example, they make the assumption that IDV is an asynchronous process (e.g. the distinction between ready
and submitted
). However, Persona, for example, performs IDV verifications within 5 seconds, so there is no valuable distinction between a ready
and submitted
state. These may not be the best statuses to use, but they map to the existing database states.
We could limit the set of events to more widely applicable ones.
IDV_ATTEMPT_CREATED
IDV_ATTEMPT_SUBMITTED
IDV_ATTEMPT_APPROVED
IDV_ATTEMPT_DENIED
The actual shape of the event data could be determined later.
Frontend Extensibility Mechanisms
We propose using the frontend-plugin-framework to integrate additional IDV implementations into the frontend-app-account MFE.
The current IDV flow is hosted in the frontend-app-account MFE. Although it works well, it is incompatible with Persona’s IDV flow. The Persona application collects all PII, government ID photos, and selfie photos (i.e. portrait photos) directly in the application, but edX’s current IDV flow performs all of those functions and submits the collected photos to Software Secure via the LMS.
For this reason, we need to replace the current IDV flow. In order to do this without modifying the current IDV flow hosted in the frontend-app-account MFE, we propose the addition of a PluginSlot from the frontend-plugin-framework to the frontend-app-account MFE. This PluginSlot would wrap the use of the IdVerificationPage in the id-verification
Route
. This would allow us to replace the entire IDV component with a new Persona integration component without needing to modify the route or the router.
There are a few other options for where to add a PluginSlot. These are documented in Alternative PluginSlot Locations.
Sample code is shown below for illustrative purposes.
Code Block |
---|
const IdVerificationPageSlot = () => (
<PluginSlot
id="id_verification_slot"
pluginProps={{
courseId,
}}
/>
<IdVerificationPage />
</PluginSlot>
)
...
subscribe(APP_READY, () => {
ReactDOM.render(
...
<Route path="/notifications/:courseId" element={<NotificationPreferences />} />
<Route path="/notifications" element={<NotificationCourses />} />
<Route path="/id-verification/*" element={<IdVerificationPageSlot />} />
<Route path="/" element={<AccountSettingsPage />} />
<Route path="/notfound" element={<NotFoundPage />} />
...
);
}); |
Refactoring
2U uses IDV on edx.org for the Name Affirmation feature, which verifies certain name changes requested by certificate-bearing learners using IDV. This is because a name change has the potential to change the name displayed on their certificate(s). On the backend, this is implemented by the edx-name-affirmation plugin, and, on the frontend, this is implemented by the NameChange component in the frontend-app-account MFE.
The VerifiedName model has a verification_attempt_id field, which currently stores the id
field of the corresponding SoftwareSecurePhotoVerification instance used to verify a particular name. This field poses a problem for the introduction of an additional IDV implementation because the value of this field on any given row could also refer to the id
field of a Persona IDV record. It would not be possible to determine whether a given id
value refers to a SoftwareSecurePhotoVerification model instance or a Persona IDV record model instance.
We propose amending the IDVerificationAttempt model to add a uuid
field, which would be unique across all IDV-related model instances. 2U would also add a uuid
field to the Persona IDV record model. This uuid
would become the ID that the edX platform uses to uniquely refer to IDV records. Some views and APIs would need to be updated as a result of this change.
...
while also enabling integration with other implementations of IDV, the platform needs a way to store generic, implementation-agnostic information about IDV attempts.
We will introduce a new model VerificationAttempt
to store this data. This model will hook into the IDVerificationService to expose these attempts across the platform.
The model will likely contain the following fields.
created
modified
user
name
status
expiration_datetime
The status
field will have four options - created
, pending
, approved
, and denied
. These statuses correspond to implementation-agnostic statuses that are sensible for use in the core.
Hooks
We propose using the hooks extension framework to integrate additional IDV implementations into the edx-platform verify_student Django application.
Filter Hooks
We propose integrating a filter hook into the IDVerificationService. The IDVerificationService serves as an interface to the verify_student Django application and is used throughout the platform. Callers of this service primarily use it to read data from the IDV related models and to get the URL to the IDV flow.
We propose the following filter, which will enable full integration of the IDVerificationService with additional IDV implementations.
url = IDVerificationURLRequested(url)
This filter hook will be used to fetch the URL to the IDV flow. This will allow operators to override the URL to the IDV flow.
Event Hooks
We propose introducing event hooks related to the IDV attempt lifecycle. Taking the EXAM_ATTEMPT_*
Open edX events as a model, we propose introducing one Open edX event per status of the generic VerificationAttempt
model.
IDV_ATTEMPT_CREATED
IDV_ATTEMPT_PENDING
IDV_ATTEMPT_APPROVED
IDV_ATTEMPT_DENIED
The actual shape of the event data could be determined later.
Frontend Extensibility Mechanisms
We propose using the frontend-plugin-framework to integrate additional IDV implementations into the frontend-app-account MFE.
The current IDV flow is hosted in the frontend-app-account MFE. Although it works well, it is incompatible with Persona’s IDV flow. The Persona application collects all PII, government ID photos, and selfie photos (i.e. portrait photos) directly in the application, but edX’s current IDV flow performs all of those functions and submits the collected photos to Software Secure via the LMS.
For this reason, we need to replace the current IDV flow. In order to do this without modifying the current IDV flow hosted in the frontend-app-account MFE, we propose the addition of a PluginSlot from the frontend-plugin-framework to the frontend-app-account MFE. This PluginSlot would wrap the use of the IdVerificationPage in the id-verification
Route
. This would allow us to replace the entire IDV component with a new Persona integration component without needing to modify the route or the router.
There are a few other options for where to add a PluginSlot. These are documented in Alternative PluginSlot Locations.
Sample code is shown below for illustrative purposes.
Code Block |
---|
const IdVerificationPageSlot = () => (
<PluginSlot
id="id_verification_slot"
pluginProps={{
courseId,
}}
/>
<IdVerificationPage />
</PluginSlot>
)
...
subscribe(APP_READY, () => {
ReactDOM.render(
...
<Route path="/notifications/:courseId" element={<NotificationPreferences />} />
<Route path="/notifications" element={<NotificationCourses />} />
<Route path="/id-verification/*" element={<IdVerificationPageSlot />} />
<Route path="/" element={<AccountSettingsPage />} />
<Route path="/notfound" element={<NotFoundPage />} />
...
);
}); |
Refactoring
2U uses IDV on edx.org for the Name Affirmation feature, which verifies certain name changes requested by certificate-bearing learners using IDV. This is because a name change has the potential to change the name displayed on their certificate(s). On the backend, this is implemented by the edx-name-affirmation plugin, and, on the frontend, this is implemented by the NameChange component in the frontend-app-account MFE.
IDV Attempt References
The VerifiedName model has a verification_attempt_id field, which currently stores the id
field of the corresponding SoftwareSecurePhotoVerification instance used to verify a particular name. This field poses a problem for the introduction of an additional IDV implementation because the value of this field on any given row could also refer to the id
field of a Persona IDV record. It would not be possible to determine whether a given id
value refers to a SoftwareSecurePhotoVerification model instance or a Persona IDV record model instance.
We propose amending the IDVerificationAttempt model to add a verification_attempt
field, which will be a ForeignKey
field to the generic VerificationAttempt
model described above.
Support Tools Verified Name Panel
The frontend-app-support-tools contains a VerifiedName panel for displaying a learner’s verified name and the history of previous verified names. In the modal that opens when viewing the history, each VerifiedName is displayed in a table, and the verification_attempt_id field described above is shown in the “IDV Attempt ID” column.
When hovering over an ID in the column, the status of the corresponding IDV attempt (i.e. of the SoftwareSecurePhotoVerification
modal instance) is shown. The status is retrieved from the IDVerificationSupportView view of the user_api Django application. This view uses the get_verification_details_by_id method of the IDVerificationService, which queries the SoftwareSecurePhotoVerification
, SSOVerification
, and ManualVerification
models by their id
. This works due to inheritance from the abstract base class IDVerificationAttempt
.
With the introduction of the VerificationAttempt
model, an id
cannot uniquely identify a instance of the VerificationAttempt
, SoftwareSecurePhotoVerification
, SSOVerification
, and ManualVerification
models. This means that the get_verification_details_by_id method of the IDVerificationService will no longer work, breaking the Support Tools.
As a solution, the VerifiedName panel will be refactored to pull the IDV attempt status from the edx-name-affirmation application. The edx-name-affirmation Django application will refactor its VerifiedNameHistoryView view to pull this data by querying the model associated with either the verification_attempt_id
or verification_attempt
fields. As a result, the use of the VerifiedNameHistoryView view and the get_verification_details_by_id method of the IDVerificationService can be removed.
Name Change Signal Handler
Currently, the edx-name-affirmation Django application associates VerifiedNames with IDV attempts via the verification_attempt_id field. This association is formed by a task that is triggered by a signal handler that listens for a signal emitted by the SoftwareSecurePhotoVerification model. This means that only Software Secure IDV attempts can change the status of VerifiedNames (e.g. approve or deny them).
We propose triggering this task on the event hooks listed above. The impact of this change is that any form of IDV can change the status of VerifiedNames (e.g. approve or deny them). For example, an instance of the ManualVerification
class can be used to approve or deny a VerifiedName.
To handle deletes, the idv_delete_handler will be connected to the VerificationAttempt
post_delete
signal as it is for the SoftwareSecurePhotoVerification model.
Name Change Modal
We propose modifying the copy in the name change modal to make the instructions more generic. Some IDV implementations do not support non-government IDs.
We propose the following text.
Enter your name as it appears on your identification card.
Other Approaches Considered
Backend
As alternative approaches, we considered Software Secure IDV deprecation, an edx-platform fork, and direct edx-platform modification
...
The current implementation of IDV using Software Secure has an unclear purpose in the platform. As is, it is our understanding that only 2U uses this integration. Based on relatively old threads in the Open edX Discuss forums, a few operators do use the Software Secure implementation but with modifications to suit their use cases (e.g. bypassing Software Secure to provide the ability for site operators to manually review photos). 2U, as the sole known user of this integration as it is currently implemented, no longer needs this integration, which could indicate deprecation of this integration.
Additional Discuss Forum Posts
Although Software Secure could be deprecated, the deprecation is not necessary to enable integration of additional IDV implementations. In fact, we believe that many, if not all, of the same extensibility mechanisms described above would be required. Additionally, because the Name Affirmation feature relies on Software Secure IDV, removal of Software Secure from the platform would also require us to consider how to remove the Name Affirmation feature. We fear that this will massively expand the scope of this project.
...
Code Block |
---|
<PluginSlot
id="routes_slot"
pluginProps={{
courseId,
}}
/>
<Routes>
<Route path="/notifications/:courseId" element={<NotificationPreferences />} />
<Route path="/notifications" element={<NotificationCourses />} />
<Route path="/id-verification/*" element={<IdVerificationPage />} />
<Route path="/" element={<AccountSettingsPage />} />
<Route path="/notfound" element={<NotFoundPage />} />
<Routes>
</PluginSlot> |
Server-Side Returned URL
In this option, a backend API on the LMS would return a Persona URL. The IDV URL is already exposed via the CoursewareMeta view, so a Django setting for the IDV URL could be introduced, which would be returned by the IDVerificationService.get_verify_location method.
However, the current use of the router that the frontend-app-account MFE uses for client-side routing does not allow routing to non-application pages. This would be need to refactored to allow this kind of navigation.
This option could work, but it results in changes to the platform that do not feel very extensible or reusable.
frontend-app-account MFE Fork
This approach is analogous to the edx-platform Fork option but for the frontend. The same judgments apply to this approach.
frontend-app-account MFE Modification
This approach is analogous to the edx-platform Modification option but for the frontend. The same judgments apply to this approach.
Competitive Research
This proposal is concerned with adding the extensibility mechanisms necessary to integrate another form of IDV into the platform, which is an Open edX platform problem, so we did not perform any competitive research.
Implementation Plan
2U will be responsible for implementation and delivery. This project is schedule to start as soon as possible. We estimate around 6-8 weeks for implementation.
Long-Term Ownership/Maintainership
The Cosmonauts team at 2U is the owning team of the IDV feature. The Cosmonauts team would continue to own and maintain the feature, complete with the aforementioned extensibility mechanisms.
Discovery
...
In a pluggable solution, what IDV features or integrations into the platform must be supported?
...
Are there any IDV features or integrations that can be ignored or not considered or that are planned to deprecation that we should be aware of?
...
How does the community use IDV? I asked in a Discuss thread but did not receive very much feedback.
...
What is the longterm role of IDV in the edx-platform?
...
Is it acceptable to build out extensibility mechanisms that are sufficient enough only to enable an integration with Persona and that may not support Software Secure or other IDV vendors?
For example, in the certificates generation logic, we may need to add a filter to “collect IDV attempts” so that we can add in our Persona records. 2U does not gate certificate generation on IDV, but some operators may choose to leverage that code path via the ENABLE_CERTIFICATES_IDV_REQUIREMENT Django setting. This means we may not need to add a filter to enable that certificates behavior.
...
path="/id-verification/*" element={<IdVerificationPage />} />
<Route path="/" element={<AccountSettingsPage />} />
<Route path="/notfound" element={<NotFoundPage />} />
<Routes>
</PluginSlot> |
Server-Side Returned URL
In this option, a backend API on the LMS would return a Persona URL. The IDV URL is already exposed via the CoursewareMeta view, so a Django setting for the IDV URL could be introduced, which would be returned by the IDVerificationService.get_verify_location method.
However, the current use of the router that the frontend-app-account MFE uses for client-side routing does not allow routing to non-application pages. This would be need to refactored to allow this kind of navigation.
This option could work, but it results in changes to the platform that do not feel very extensible or reusable.
frontend-app-account MFE Fork
This approach is analogous to the edx-platform Fork option but for the frontend. The same judgments apply to this approach.
frontend-app-account MFE Modification
This approach is analogous to the edx-platform Modification option but for the frontend. The same judgments apply to this approach.
Competitive Research
This proposal is concerned with adding the extensibility mechanisms necessary to integrate another form of IDV into the platform, which is an Open edX platform problem, so we did not perform any competitive research.
Implementation Plan
2U will be responsible for implementation and delivery. This project is schedule to start as soon as possible. We estimate around 6-8 weeks for implementation.
Long-Term Ownership/Maintainership
The Cosmonauts team at 2U is the owning team of the IDV feature. The Cosmonauts team would continue to own and maintain the feature, complete with the aforementioned extensibility mechanisms.
Discovery
In a pluggable solution, what IDV features or integrations into the platform must be supported?
Are there any IDV features or integrations that can be ignored or not considered or that are planned to deprecation that we should be aware of?
How does the community use IDV? I asked in a Discuss thread but did not receive very much feedback.
What is the longterm role of IDV in the edx-platform?
Is it acceptable to build out extensibility mechanisms that are sufficient enough only to enable an integration with Persona and that may not support Software Secure or other IDV vendors?
For example, in the certificates generation logic, we may need to add a filter to “collect IDV attempts” so that we can add in our Persona records. 2U does not gate certificate generation on IDV, but some operators may choose to leverage that code path via the ENABLE_CERTIFICATES_IDV_REQUIREMENT Django setting. This means we may not need to add a filter to enable that certificates behavior.
Is there guidance for where it is acceptable to use a
PluginSlot
on the frontend? What requirements exist? Can it be inserted anywhere?
Appendix
Uses of IDV on the Open edX Platform
Goal
The goal of this section is to identify dependencies on IDV across the Open edX platform.
Summary
Feature | Notes | Opportunity For Deprecation? |
---|---|---|
Proctoring Requirements Email | The | Yes. |
PayAndVerifyView Legacy Upgrade and Verify Flow | The PayAndVerifyView likely cannot be deprecated, but the use of the legacy IDV flow could be deprecated. | |
VerificationStatusAPIView | This is called by the Account MFE, but the data returned by the view does not appear to be used by the application. | Yes. |
ReverifyView | This view does not appear to be referenced. | Yes. |
Certificates | Certificates still make use of IDV to gate the generation of certificates. | Yes and no. This feels like a pretty core part of the platform, currently. It is gated by the |
Learner Dashboard (Legacy) | The IDVerificationService is used to define a set of IDV related variables that are passed to the dashboard template as context but not used. | Yes and no. This dependency could be deprecated on the dashboard course listing, but it would depend on Open edX needs, because Open edX installations may specify separate templates via the filter hook that could use these variables. However, the course verification status could be a required part of the platform. |
Support Tools: Program Enrollments | The Program Enrollments support tool references IDV. | Yes. The legacy support tools application could be deprecated in favor of the MFE-based support tools application and the IDV references could removed, as they are not in use in the MFE-based application. |
Support Tools: ID Verification Details | The Verified Name history modal references IDV. | No. This dependency cannot be deprecated, because it is used by the MFE-based support tools application to get information about the IDV attempt associated with a verified name. However, IDVerificationStatusView/getUserVerificationStatus and IDVerificationStatusDetailsView/getUserVerificationDetail could be deprecated. |
Date Summaries | This dependency could be deprecated. Although it is enabled if the | |
Instructor Dashboard: Course Grades Report | This data could be put behind the | Maybe. There may be a case to be made to remove references to IDV from this report. |
Instructor Dashboard: Data Download via Instructor Analytics | This data could be put behind the | Maybe. There may be a case to be made to remove references to IDV from this report. |
Course Home Progress Tab (Current) | Maybe. If an approved IDV attempt continues to be a requirement for a certificate, this seems like a useful feature. | |
Course Home Progress Page (Legacy) | Maybe. If an approved IDV attempt continues to be a requirement for a certificate, this seems like a useful feature. | |
Courseware API | This API is used by the frontend-app-learning MFE. Further investigation is necessary into the Segment events. | Maybe. If an approved IDV attempt continues to be a requirement for a certificate, this seems like a useful feature. |
Track Selection Page | No. | |
Configuration Dependencies | Some dependencies could be deprecated and other’s could not be. The references to Software Secure settings in the VERIFY_STUDENT edx-platform Django setting and the AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING feature toggle could be deprecated. | |
Indirect Dependencies - Name Affirmation | The VerifiedName model has an indirect dependency on the SoftwareSecurePhotoVerification model via the verification_attempt_id field. | No. This dependency cannot be deprecated because the Name Affirmation is a feature of the edx-platform, and we will need to maintain references to IDV attempts in the VerifiedName model. |
Miscellaneous Dependencies | Maybe. | |
frontend-app-account MFE | This is where the current IDV flow is implemented. | Yes. This dependency could be deprecated if a frontend extensibility is approved that would enable linking to an IDV flow implementation. This is because this flow is specific to the Software Secure integration. |
frontend-app-learning MFE | All references to IDV are gated by the | No. |
Support Tools | See Support Tools: Program Enrollments and Support Tools: ID Verification Details above. | Yes and no. See above. |
Unverified Certificates
A certificate is can enter into the
unverified
status only when the ENABLE_CERTIFICATES_IDV_REQUIREMENT Django setting is turned on. Installations of Open edX may enable or disable this feature.The ENABLE_CERTIFICATES_IDV_REQUIREMENT Django setting is used during the process of checking whether a “regular” certificate - as opposed to an “allowlist” certificate - can be created for a learner in _can_generate_certificate_common and during the process of creating an unverified certificate in _get_cert_status_common.
edX has tried to deprecate this status in the past, but there was a community need for it at the time. See this Discuss thread. Furthermore, edX deemed it too complex to make this behavior pluggable using Open edX hooks extension framework.
References to IDV in Backend Code
IDVerificationService
The IDVerificationService is an interface with the verify_student application that is used across the platform. You can think of it as a Python API that wrapped in a class. The majority of direct references to IDV occur via the use of this class, so that is where I focused my attention.
Proctoring Requirements Email
The generate_proctoring_requirements_email_context method of the email_helpers module of the edx-platform is used to collect context for proctoring requirement emails. It’s used by the update_enrollment method of the course_enrollment module of the student application, which sends proctoring requirements emails to learners when they enroll in a mode that requires proctoring (e.g. verified
) in a course that uses proctoring.
The update_enrollment method uses the IDVerificationService to get the IDV URL, which is passed to the template via the context as the id_verification_url
variable.
The following methods of the IDVerificationService are called.
Note that IDV references were removed in the proctoring template, so the id_verification_url
variable is no longer in use in the proctoring requirements email.
This dependency could be deprecated because the proctoring requirements template no longer uses the id_verification_url
variable.
PayAndVerifyView
The PayAndVerifyView is an upgrade and verify flow. It was used to enroll in a verified track of a course, which, in the past, required a learner to pay to upgrade and to perform IDV to verify - hence the term “verified certificate”.
The PayAndVerifyView redirects learners to a variety of destinations across the platform depending on the state they are in with respect to track selection, payment status, verification status, and how they entered the PayAndVerifyView flow. These destinations include the learner dashboard, the checkout page, the legacy IDV flow, the frontend-app-payment MFE-based IDV flow, etc.
Legacy IDV Flow
The main concern is the legacy IDV flow. There is a set of conditions that may be met that results in the learner falling through to the legacy IDV flow. The _redirect_if_necessary method redirects the learner elsewhere, but if a learner does not meet these conditions, they will be shown the legacy IDV flow.
It is difficult to understand when and how often this actually occurs and whether it’s of concern to Open edX.
This is the legacy flow. Note that the id-verification application of frontend-app-learner-account MFE replaces the legacy IDV flow.
The PayAndVerifyView uses the IDVerificationService in its _redirect_if_necessary method, which redirects learners to the IDV flow if they have already enrolled and paid for a course. The IDVerificationService is used to get the expiration date of a learner’s IDV attempt in the submitted
, approved
, or must_retry
statuses, if one exists, and to get whether the learner has a pending or approved IDV attempt.
The following methods of the IDVerificationService are called.
The verify_student/start-flow
URL slug is used by the edx-enterprise application in the LMS_START_PREMIUM_COURSE_FLOW_URL constant. This URL is used to
redirect the learner to the checkout flow in the HandleConsentEnrollment
redirect the learner to the checkout flow in the CourseEnrollmentView when data sharing consent is not required
The dependency on the legacy IDV flow could be deprecated, but it would depend on Open edX needs.
VerificationStatusAPIView
The VerificationStatusAPIView is used to get a learner’s IDV status. The IDVerificationService is used to get the learner’s IDV status and the expiration of their approved IDV attempt, if one exists.
The following methods of the IDVerificationService are called.
This view is used by the id-verification application of the frontend-app-account MFE in the getExistingIdVerification function. This is used to determine the existingIdVerification attribute of the IdVerificationContext
.
However, the existingIdVerification
variable does not appear to be used in the frontend-app-account MFE.
This dependency could be deprecated because the existingIdVerification
variable is not used anywhere.
ReverifyView
The ReverifyView is used to reverify learners whose IDV attempts have been rejected or expired. The IDVerificationService is used to get the IDV URL.
The following methods of the IDVerificationService are called.
There are many references to the concept of a “reverify view”, but this dependency could be deprecated because there appear to be no actual references to its URL.
Certificates
The certificates application in the edx-platform handles the generation of course certificates.
Certificate Generation Signal Handler
The listen_for_id_verification_status_changed signal handler listens to the LEARNER_NOW_VERIFIED
signal and generates a task to generate a certificate. This signal is emitted when a photo or SSO IDV attempt is approved.
The signal handler uses the IDVerificationService is to get the status of the learner’s most recent IDV attempt. Note that this includes records from the SoftwareSecurePhotoVerification
model, which is what we traditionally refer to as IDV, as well as records from the SSOVerification
and ManualVerification
models.
The following methods of the IDVerificationService are called.
The expected_verification_status
variable is used in a logging statement in the signal handler.
This dependency could be deprecated. The logging statement could be removed or moved elsewhere. I do not see a strong reason to maintain this dependency for a log. Alternatively, the deprecation and removal of the SoftwareSecurePhotoVerification
model would also be a reasonable approach.
Certificates Generation Handler
The _id_verification_enforced_and_missing function is used to determine whether a learner is missing IDV and whether IDV is a requirement to earn a certificate. This function is used in a few locations in that module. The function calls the user_is_verified method of the IDVerificationService.
The following methods of the IDVerificationService are called.
_id_verification_enforced_and_missing only calls user_is_verified when the ENABLE_CERTIFICATES_IDV_REQUIREMENT
feature is enabled.
This dependency could be deprecated, but it would depend on Open edX needs. Currently, requiring an approved IDV attempt to earn a certificate is part of the platform, gated by the ENABLE_CERTIFICATES_IDV_REQUIREMENT
feature condition. It would be possible to deprecate the reliance on the SoftwareSecurePhotoVerification
model, however.
Learner Dashboard (Legacy)
The student_dashboard view implements the legacy learner dashboard. Note that the frontend-app-learner-dashboard MFE replaces the legacy learner dashboard. This legacy view is redirected to from the student_dashboard view when the appropriate waffle flag is enabled.
The student_dashboard view uses the IDVerificationService to get the status of the learner’s most recent IDV attempt and to get any verification errors that should be displayed on the dashboard.
This data is used to render the following variables into the template via the context.
Code Block |
---|
'verification_display': verification_status['should_display'],
'verification_status': verification_status['status'],
'verification_expiry': verification_status['verification_expiry'],
'verification_status_by_course': verify_status_by_course,
'verification_errors': verification_errors, |
The student_dashboard view renders the dashboard.html template, which does not use any of the IDV related variables in the context. However, these variables may be used by other installations, because other installations can supply a different template via the filter hook.
The following methods of the IDVerificationService are called.
This dependency could be deprecated, but it would depend on Open edX needs, because Open edX installations may specify separate templates via the filter hook that could use these variables.
Dashboard Course Listing (Legacy)
The _dashboard_course_listing template, which is included in the dashboard.html template that is rendered by the student_dashboard view makes uses of the IDVerificationService to determine the value of a reverify_link.
The reverify_link is passed to the _dashboard_certificate_information template by the _dashboard_course_listing template. However, this variable is not used in this template. It was removed in #30146.
The following methods of the IDVerificationService are called.
This dependency could be deprecated because the references to reverify_link
in the _dashboard_course_listing template have been removed.
Course Verification Status (Legacy)
The student_dashboard view displays per-course IDV information on the dashboard. It calls the check_verify_status_by_course function to collect this information. The check_verify_status_by_course function makes a variety of calls to the IDVerificationService. You’ll note that this function short circuits when the ENABLE_INTEGRITY_SIGNATURE feature is enabled.
The following methods of the IDVerificationService are called.
A call to VerificationDeadline.deadlines_for_enrollments is also made; VerificationDeadline is a model that is related to IDV.
This dependency could not be deprecated because, if an approved IDV attempt is required to earn a certificate, then information about a learner’s IDV status is valuable to display within the learner dashboard. This feature is gated on the ENABLE_INTEGRITY_SIGNATURE
feature flag condition.
Support Tools: Program Enrollments
The support application in the edx-platform implements the views that power the platform's support tools. The IDVerificationService is used by two views related to program enrollments - ProgramEnrollmentsInspectorView and ProgramEnrollmentsInspectorAPIView.
The ProgramEnrollmentInspectorView is used by the legacy support application, and the ProgramEnrollmentsInspectorAPIView is used by the frontend-app-support-tools MFE.
There are two functions - _get_account_info and _get_external_user_info - that are used by both views and that use the IDVerificationService to get the status of the learner’s most recent IDV attempt.
The following methods of the IDVerificationService are called.
Support Tools (Legacy)
The legacy support tools view uses the id_verification
variable in the program enrollments inspector page, accessible via the ProgramEnrollmentsInspectorView.
This dependency could be deprecated. It is theoretically in use in the legacy view, but given that it’s not exposed by the MFE-based application, it’s implied that it’s not a necessary piece of information to expose. It would depend on Open edX needs
Support Tools (Current)
The frontend-app-support-tools MFE does not appear to use the id_verification
variable.
This dependency could be deprecated because the MFE-based support tools do not use the id_verification
variable.
Support Tools (Current): ID Verification Details
The verification_api module of the user_api application of the edx-platform contains a collection of APIs that expose IDV status information.
There are three views.
These views are used exclusively by the frontend-app-support-tools MFE. Although there are references to all three views in the repository, only the IDVerificationSupportView is used in the application.
View | Caller | In Use? |
---|---|---|
No. | ||
No. | ||
Yes, in the VerifiedName component. |
The IDVerificationSupportView is used by the VerifiedName component to get more information about the related IDV attempt
In the Verified Name Status
panel of the Support Tools, there is a link Show
. Clicking this button opens the Verified Name History
modal. This modal contains a table of all verified names. If there is an associated IDV attempt for a given verified name, the IDV details fetched from this endpoint are used to populate the information in the tool tip that is displayed on hovering over the ID. The information displayed is the status of the IDV attempt and the error message associated with the attempt, if there is one.
The following methods of the IDVerificationService are called.
This dependency cannot be deprecated, because it is used by the MFE-based support tools application to get information about the IDV attempt associated with a verified name.
Date Summaries
The date_summary module of the courseware application of the edx-platform implements date summary blocks for use on the course information page.
The only date summary block that uses the IDVerificationService is the VerificationDeadlineDate block. It uses the IDVerificationService to get the status of the learner’s most recent IDV attempt and to get the IDV URL.
The following methods of the IDVerificationService are called.
Each block implements an is_allowed
method, which is used by the courseware application to filter out blocks that are not allowed. The VerificationDeadlineDate’s is_allowed method returns False
if the ENABLE_INTEGRITY_SIGNATURE
feature is enabled, meaning that the block will not be rendered when this feature is enabled.
This dependency could be deprecated. Although it is enabled if the ENABLE_INTERGRITY_SIGNATURE
feature is not enabled, I do not believe this is a core functionality of the Open edX platform.
Instructor Dashboard: Course Grades Report
The instructor_task application in the edx-platform implements a variety of tasks that can be triggered from the Instructor Dashboard in the LMS.
One such task is the CourseGradeReport. This is used to generate grade information about learners. This report contains a column called Verification Status, which contains IDV information about the learner. The value of this cell is computed by _row_for_users, which calls _user_verification_mode, which then calls the verification_status_for_user method of the IDVerificationService.
Additionally, the IDVerificationService is used to determine some context. In the _EnrollmentBulkContext, the get_verified_user_ids method of the IDVerificationService is called. This context is used in the aforementioned call to verification_status_for_user, accessible via the bulk context.
The following methods of the IDVerificationService are called.
The course grade report task can be triggered from a few places by calling the calculate_grades_csv function.
I am not sure if this dependency could be deprecated.
Instructor Dashboard: Data Download via Instructor Analytics
The instructor_analytics application of the edx-platform defines common utilities for getting learner and course information for instructors via the Instructor Dashboard.
The IDVerificationService is used for a handful of reports exposed via the Data Download tab of the Instructor Dashboard. The Data Download tab contains options to trigger asynchronous tasks that generate CSV reports of learner information. The Data Download tab has two different versions - v1 and v2 - both of which make use of tasks that use the IDVerificationService.
The IDVerificationService is used to get a learner's ID verification status, which is exposed via the enrolled_students_features function. This function is used to populate the CSV created by the upload_students_csv task. This task is created by the submit_calculate_students_features_csv API method. The only way to invoke the task creation is by using the get_students_features view. The URL configuration is here.
This view is called in a few places on the Instructor Dashboard, which is implemented by the instructor_dashboard_2 view. When a user has the data researcher permission, the instructor_dashboard_2 view adds adds a Data Download section to the Instructor Dashboard by calling _section_data_download and adding it to the sections variable. This _section_data_download contains a variable get_student_features_url, which is a reference to the get_students_features view. The instructor_dashboard_2 view sets the instructor_template to instructor/instructor_dashboard_2/instructor_dashboard_2.html, which, by default, will be the template used for rendering the Instructor Dashboard 2. This template pulls in and renders all section templates defined in the sections variable. Depending on whether the data_download_v2_is_enabled, one of two templates for the Data Download section will be rendered.
Template | Use of get_student_features_url | Conditions? | |
---|---|---|---|
Yes. | The variable is used in the data_download2/reports.html template, which is included here. | These buttons are only rendered if | |
No. | These buttons are only rendered if |
A quick note about the templates. The instructor_dashboard_2 view makes use of the InstructorDashboardRenderStarted Open edX filter hook, which allows installations to override the template and context are used for rendering the Instructor Dashboard. What this means is that there may be installations using the get_student_features_url attribute in other ways, so it is not straightforward to deprecate this use of the IDVerificationService.
The following methods of the IDVerificationService are called.
I am not sure if this dependency could be deprecated. There may be a case to be made to remove references to IDV from this report or put them behind the ENABLE_INTEGRITY_SIGNATURE
feature.
Course Home Progress Tab (Current)
The ProgressTabView of the course_home_api application of the edx-platform is used by the frontend-app-learning MFE progress-tab application to render a progress tab.
The ProgressTabView uses the IDVerificationService to get the status of the learner’s most recent IDV attempt and to get the IDV URL. This data is included in the response in the verification_data key.
The following methods of the IDVerificationService are called.
verification_data
is used by the CertificateStatus component in the frontend-app-learning MFE to render an ID verification reminder to learners when they have a certificate in the unverified
state.
Certificates do not enter the unverified
state if the ENABLE_CERTIFICATES_IDV_REQUIREMENT setting is not enabled. See Unverified Certificates for more details.
I am not sure if this dependency could be deprecated. If an approved IDV attempt continues to be a requirement for a certificate, this seems like a useful feature.
Course Home Progress Page (Legacy)
The progress view of the courseware application in the edx-platform implements the legacy progress view.
Note that the course_home application of frontend-app-learning MFE replaces the legacy progress page.
This view indirectly uses the IDVerificationService.
The legacy progress view gets certificate data via the get_cert_data method. The get_cert_data method calls _certificate_message, which calls _missing_required_verification. _missing_required_verification determines whether a learner is missing IDV and the ENABLE_CERTIFICATES_IDV_REQUIREMENT
Django setting is enabled, which enables an IDV requirement for verified certificates.
The following methods of the IDVerificationService are called.
I am not sure if this dependency could be deprecated. If an approved IDV attempt continues to be a requirement for a certificate, this seems like a useful feature.
Courseware API
The CoursewareInformation API of the courseware_api application of the edx-platform is an endpoint used by the frontend-app-learning MFE to get course details via CoursewareMeta.
This API exposes two IDV related attributes.
The following methods of the IDVerificationService are called.
verifyIdentityUrl is used by the CourseCelebration component to render a notice to learners to verify at course completion time when their certificate is in the unverified
state. The CourseCelebration component also uses verificationStatus as part of this code. Certificates do not enter the unverified
state if the ENABLE_CERTIFICATES_IDV_REQUIREMENT setting is not enabled. See Unverified Certificates for more details.
verificationStatus is used in three components.
It’s used in the CourseCelebration component as described above.
It is also used by the NotificationTray and the NotificationWidget components. Both components use verificationStatus in an object that is included in calls to sendTrackEvent, which sends events to Segment.
Component | Link | Segment Event |
---|---|---|
| ||
|
There are no references to these Segment events in the codebase, but it’s possible there are queries, dashboards, and other forms of reporting that rely on this event attribute.
I am not sure if this dependency could be deprecated. If an approved IDV attempt continues to be a requirement for a certificate, this seems like a useful feature.
Track Selection Page
The ChooseModeView of the course_modes application of the edx-platform handles the track selection page.
GET handler
The GET handler of the ChooseModeView displays the track selection page. When the learner accesses the track selection page, the course has a professional
or no-id-professional
mode, the learner does not already have an active enrollment in one of the aforementioned modes, and the ecommerce service is either not enabled or the mode is misconfigured (i.e. no sku
value), then the view redirects the learner to the IDV flow instead of rendering the track selection page. It uses the IDVerificationService to get the IDV URL, which will send the learner to the MFE-based IDV flow.
The view redirects this way because the assumption is that a professional
or no-id-professional
mode will be the only mode in a course, so there is no course mode selection needed.
POST handler
The POST handler of the ChooseModeView handles submissions from the track selection page. When the learner has permission to enroll in a course, the mode they selected is a valid mode in the course, and the “indicated contribution amount is valid and above the minimum” contribution amount, then they are redirected to IDV. The view uses the IDVerificationService to get the IDV URL, which will send the learner to the MFE-based IDV flow.
As a note, the track selection page is linked to from a few places on the platform. This is not exhaustive.
What is this? There is some indication that this may be deprecated.
The primary use of the track selection page seems to be for programs.
I don’t see an actual use of
track_selection_url
ortrackSelectionUrl
, however.
The following methods of the IDVerificationService are called.
This dependency cannot be deprecated.
...
Configuration Dependencies
VERIFY_STUDENT edx-platform Django setting
an object that contains various settings
This setting cannot be deprecated because it contains generic IDV settings. The Software Secure settings could be deprecated.
EXPLICIT_QUEUES edx-platform Django setting - specifies mapping of task to “alternate worker queue to be used when routing” and includes the following tasks.
lms.djangoapps.verify_student.tasks.send_verification_status_email
lms.djangoapps.verify_student.tasks.send_request_to_ss_for_user
This dependency could be deprecated. These tasks could be removed.
AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING feature toggle, which bypasses posting submissions to Software Secure when enabled.
This dependency could be deprecated, as it is specific to the Software Secure integration.
PIPELINE['JAVASCRIPT'] edx-platform Django setting - defines elements of the static asset bundling pipeline, which uses django-pipeline.
references to aforementioned lists in PIPELINE['JAVASCRIPT']
This dependency could be deprecated if the legacy IDV flow in the PayAndVerifyView view is deprecated. Otherwise, it cannot be deprecated.
VerifyStudentConfig - referenced in
INSTALLED_APPS
This dependency cannot be deprecated. The verify_student application should continue to be an installed application of the platform.
Indirect Dependencies
Name Affirmation
The VerifiedName model contains a reference to an instance of the SoftwareSecurePhotoVerification model via the id
field.
This will pose a problem, because we will need to store a reference to other IDV objects. Because I don’t believe we can or should reuse the SoftwareSecurePhotoVerification model, we will need to create a new model per IDV implementation. As is, this will cause issues, because it will not be clear which model a given id
refers to.
This dependency cannot be deprecated because the Name Affirmation is a feature of the edx-platform, and we will need to maintain references to IDV attempts in the VerifiedName model.
Miscellaneous Dependencies
references in openedx-documentation
This dependency could be deprecated because the documentation is out of date.
references in edx-proctoring set up docs
This dependency could be deprecated because it’s out of date and incorrect.
PayAndVerifyView specific references
edx-platform JavaScript test (i.e.
spec
) filesedx-platform translation files
i18n-tools mock underscore template, translation files, and mako templates
edx-platform SCSS class for payment buttons in
make_payment_step.underscore
edx-platform certificates app diagram DSL
Certain parts of this dependency could be deprecated if the legacy IDV flow in the PayAndVerifyView view is deprecated. Otherwise, it cannot be deprecated.
...
References to IDV in Frontend Code
frontend-app-account MFE
The frontend-app-account MFE is home to the MFE-based IDV flow. This is in contrast to the legacy PayAndVerify flow in the LMS.
The IdVerificationPage implements the MFE-based IDV flow. As part of the IDV flow, the application must fetch IDV attempts from the backend and write IDV attempts to the backend.
Frontend Function | Backend View | Method |
---|---|---|
GET | ||
POST |
This dependency could be deprecated if a frontend extensibility is approved that would enable linking to an IDV flow implementation. This is because this flow is specific to the Software Secure integration.
frontend-app-learning MFE
All the references below are only rendered/used when a learner has an unverified
certificate. Certificates do not enter the unverified
state if the ENABLE_CERTIFICATES_IDV_REQUIREMENT setting is not enabled. See Unverified Certificates for more details. See Unverified Certificates.
verifyIdentityUrl attribute
See Courseware API for a discussion of the use of the
verify_identity_url
attribute.
SUPPORT_URL_ID_VERIFICATION frontend setting, which is used for two purposes.
This setting is used by the IdVerficationSupportLink component.
This component is used in the CourseCelebration component CTA to verify at course completion time.
This component is used by a certificate status component in the progress tab, which prompts the user to verify when their certificate is in the
unverified
state.
This setting is used by the CertificateStatusAlert component, which is an alert that is displayed on the course outline tab and which prompts the user to verify when their certificate is in the
unverified
state.
I am not sure if this dependency could be deprecated. If an approved IDV attempt continues to be a requirement for a certificate, this seems like a useful feature.
Support Tools
See Support Tools: Program Enrollments and Support Tools (Current): ID Verification Details.