hubzero / hubzero-cms

Platform for Scientific Collaboration
https://hubzero.org
GNU General Public License v2.0
47 stars 57 forks source link

[NCN-440] Update validation for one-click access #1704

Closed jsperhac closed 4 months ago

jsperhac commented 5 months ago

Dependencies

This work is part of Epic NCN-434, whose PRs are as follows:

Summary

Move and adapt custom code from Nanohub (com_reply) into the core CMS component, com_newsletter.

Then, update access validation for one-click links to use the secrets (hub, user, and campaign) created in the Epic mentioned above, NCN-434.

NOTE that all PRs mentioned above are already merged into this branch. All of them have been reviewed and tested.

Jira cards (for this PR):

What's the point again?

Nanohub team wants to be able to send emails to their users with secure, unique links that enable users one-click access to their editable profile details or to a survey. This work ensures that we can selectively reset or expire codes for individual users or for a campaign. In order to provide access we maintain unique secret codes for each user; for each "campaign"; and for the Hub. The three of these must be hashed together and the expiration date validated for access to be granted.

If this solution seems weirdly incomplete, it is. The Nanohub team uses a Salesforce instance to do their mailings. This requires only that they hit a replica of the Nanohub database to query for the needed campaign id, username, and hashed access code. Those are pulled into Salesforce, which handles the mailing part.

However, it was thought that this functionality might be generally useful so this work moves it into core.

Previous PRs provide admin user interfaces for Hub-side management of:

Use

The one-click access code is generated by a call to stored procedure hash_access_code as follows:

SELECT hash_access_code(campaignId, username);

Here's a partial example of what that looks like:

the-hash

Page access

Example format of the secure page-access URLs provided to users:

https://hub.hubzero.org/newsletter/pages/2?campaign=CAMPAIGNID&user=USERNAME&code=CODE_FROM_hash_access_code

Subscription access

https://hub.hubzero.org/newsletter/email-subscriptions?campaign=CAMPAIGNID&user=USERNAME&code=CODE_FROM_hash_access_code

Management of the one-click pages, subscriptions, and related tables is no different than it was on nanoHUB, except that any hardcoding of the Hub name was replaced. Management of pages is largely manual and no change to that was scoped in this work (see README section below).

This is an example of the one-click "email subscription" page following successful validation:

example-one-click-page

Testing

This work was tested on a developer AWS instance. At the stage of this PR, testing concentrated on behavior when different URLs were provided. In particular:

Generation of codes via the stored procedure was also tested.

The README

The following is the updated README taken from the custom com_reply component. I reproduce it here to provide context on the work that was done.

Reply functionality: single-click validation

Use Case

"Reply" functionality allows users to submit survey responses or update their preferences without first completing the primary hub authentication procedure.

This feature provides user authentication via hashes of randomly-generated codes that are associated with the user's CMS record, the campaign, and the Hub.

This functionality is now part of the com_newsletter core component. It was originally found in custom component com_reply.

Related features:

All management of these features is found under the Hub's administrator interface.

Install

  1. Run the migrations e.g. via muse migration run ...

Adding a Page

It is assumed that all users providing correct credentials will have access to all pages.

To add a form-based page:

  1. Add a record to jos_reply_pages
  2. Create a view for the page in site/views/pages

Adding an Email Subscription Option

  1. Create or confirm name of the corresponding profile field
  2. Add a record to jos_email_subscriptions
  3. Create a view (content to appear beneath label) if desired
  4. Set the email page ID in secrets/code.php, using secrets/code_example.php as a model.
    • The page ID key is referenced in CodeHelper.php validateEmailSubscriptionsCode().

Gotchas

Component-Specific Tables

Access-Related Tables

Integrations

The email subscription update functionality integrates with the core user profile data.

Generating Access Codes

The stored procedure hash_access_code is used to generate and verify codes for page access. Codes are used in URLs as shown below.

Example URLs

Here:

pages

Format of links for page access:

https://jsperhac.aws.hubzero.org/newsletter/pages/2?campaign=CAMPAIGNID&user=USERNAME&code=CODE_FROM_hash_access_code

subscriptions

Format of links for so-called subscription access:

https://jsperhac.aws.hubzero.org/newsletter/email-subscriptions?campaign=CAMPAIGNID&user=USERNAME&code=CODE_FROM_hash_access_code

jsperhac commented 4 months ago

I've addressed your blocking change requests:

While doing this I saw a couple of things that needed to be addressed:

  1. Three migration files create and/or modify tables that are not in use in the code. These have been removed and the README.md (documentation) updated. (commit b850c84)
  2. Display campaign id in admin UI, so admin user can easily determine it (commit acf60c7)

I've tested all this stuff on my AWS instance.