Skip to content

Commit

Permalink
GFCV-102 Remove checksum authentication functionality & update docume…
Browse files Browse the repository at this point in the history
…ntation
  • Loading branch information
agileware-fj authored and agileware-dev committed Aug 29, 2024
1 parent 561e0eb commit 769e84b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 61 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Use the following steps to set up a _Newsletter Subscription_ form using the exa
1. [Action Provider](https://lab.civicrm.org/extensions/action-provider)
2. [Form Processor](https://lab.civicrm.org/extensions/form-processor)
3. [API Key Management](https://lab.civicrm.org/extensions/apikey)
3. In CiviCRM, locate the CiviCRM "System User" Contact. This is the user account used to execute CiviCRM cron and scheduled jobs. If you do not have such a user, then best to create one now as this will be used by default for processing the form submissions. This user must have a corresponding WordPress user account.
3. In CiviCRM, locate the CiviCRM "System User" Contact. This is the user account used to execute CiviCRM cron and scheduled jobs. If you do not have such a user, then best to create one is now as this will be used by default for processing the form submissions; this user must have a corresponding WordPress user account.
4. Open this CiviCRM Contact and click on the **API Key** tab.
5. Generate a **User API Key** and copy the **Site API Key**.
6. In WordPress, open Gravity Forms and import the example Gravity Form, [gravityforms-newsletter_subscribe.json](example/gravityforms-newsletter_subscribe.json)
Expand Down Expand Up @@ -81,7 +81,7 @@ If you set defaults for the Form Processor input used as a "CiviCRM Source", the

# Processing form submissions as a specific Contact

Any form processor that should record actions as a specific Contact should implement checksum validation as part of the processor
Any form processor that should record actions as a specific Contact must implement checksum validation as part of the processor

1. Include fields in the form processor that are used for the checksum validation
- `cid` for the Contact ID
Expand All @@ -102,10 +102,10 @@ An example of this setup is available,

This method is preferred to the previously documented `{civicrm_api_key}` merge tag to use the API Key of the user viewing the form, due to impracticalities discovered in the latter workflow.

## **Deprecated** - "Allow authentication with checksum"
## **Removed** - "Allow authentication with checksum"

Previous versions presented a checkbox on the CiviCRM settings tab to masquerade as a logged in user based on passed in `cid` and `cs` URL parameters. We have found that in some circumstances this workflow can permanently hijack the logged in user's session, **which could result in privilege escalation**.
The option is no longer allowed for forms that do not already have it set, and in places it was in use, we **strongly recommend** replacing the functionality with the above workflow and unchecking the option. The functionality is scheduled to be removed in a future release in August 2024.
Previous versions presented a checkbox on the CiviCRM settings tab to masquerade as a logged in user based on passed in `cid` and `cs` URL parameters. We found that in some circumstances this workflow could permanently hijack the logged in user's session, **which could result in privilege escalation**.
The option is no longer allowed; the functionality has been removed from the plugin and an alternative method of checksum authentication can be implemented according to [Processing form submissions as a specific Contact](#processing-form-submissions-as-a-specific-contact) above

# Troubleshooting

Expand Down
75 changes: 20 additions & 55 deletions class-gf-civicrm-fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,6 @@ public function init_admin() {
], 10, 2);
}

public function init_frontend() {
parent::init_frontend();

add_action( 'gform_pre_render', [ $this, 'maybe_authenticate' ], 9, 1 );
}

public function init() {
parent::init();

Expand Down Expand Up @@ -141,50 +135,6 @@ public function switchIsDelayed($is_delayed, $form, $entry, $addon_slug) {
return $is_delayed;
}

public function maybe_authenticate( $form ) {
$settings = $this->get_form_settings( $form ) ?: [];

$auth_checksum = $settings['civicrm_auth_checksum'] ?? false;

if ( ! $auth_checksum || ! civicrm_initialize() ) {
return $form;
}

$contact_id = rgget( 'cid' );
$checksum = rgget( 'cs' );

if ( empty( $contact_id ) || empty( $checksum ) ) {
return $form;
}

try {
if ( \CRM_Core_Session::getLoggedInContactID() ) {
return $form;
}

$session = \CRM_Core_Session::useFakeSession();

$validator = Contact::validateChecksum( false )
->setContactId( $contact_id )
->setChecksum( $checksum )
->execute()
->first();

if ( ! $validator['valid'] ) {
// Checksum invalid, so don't load the form
return false;
}

// Checksum validated! Pretend we're logged in.
$session->set( 'userID', $contact_id );
$session->set( 'authSrc', \CRM_Core_Permission::AUTH_SRC_CHECKSUM );
} catch ( \CRM_Core_Exception $e ) {
// ...
}

return $form;
}

public function warn_auth_checksum($wrapper = '<div class="notice notice-warning is-dismissible">%s</div>') {
$forms = GFAPI::get_forms();

Expand All @@ -194,13 +144,16 @@ public function warn_auth_checksum($wrapper = '<div class="notice notice-warning
$settings = $this->get_form_settings($form);
if (!empty($settings['civicrm_auth_checksum'])) {
$settings_link = admin_url( 'admin.php?page=gf_edit_forms&view=settings&subview=gf-civicrm&id=' . $form['id'] );
$warnings[] = sprintf( __( 'The Gravity Form "%s" has the CiviCRM auth checksum setting enabled. <a href="%s">Click here to edit the form settings.</a>', 'text-domain' ), esc_html( $form['title'] ), esc_url( $settings_link ) );
$warnings[] = sprintf( __( 'The Gravity Form "%s" has the <strong>nonfunctional</strong> CiviCRM auth checksum setting enabled. <a href="%s">Click here to edit the form settings.</a>', 'text-domain' ), esc_html( $form['title'] ), esc_url( $settings_link ) );
}
}

if(!empty($warnings)) {
$notice_heading = __( 'Legacy setting enabled for form(s)' );
return sprintf( $wrapper, "<h3>$notice_heading</h3><ul>" . implode( '', $warnings ) . '</ul>' );
$notice_footer = sprintf(
__( 'For details on setting up an alternative method for checksum authentication, see the README section on <a target="_blank" href="%1$s">Processing form submissions as a specific Contact</a>' ),
'https://github.com/agileware/gf-civicrm/blob/main/README.md#processing-form-submissions-as-a-specific-contact' );
return sprintf( $wrapper, '<h3>' . $notice_heading . '</h3><ul>' . implode( '', $warnings ) . '</ul><p>' . $notice_footer . '</p>' );
} else {
return NULL;
}
Expand Down Expand Up @@ -258,20 +211,32 @@ public function styles() {
return array_merge(parent::styles(), $styles);
}

/**
* Add form settings tab, *only if* legacy settings are already set.
*/
public function add_form_settings_menu( $tabs, $form_id ) {
$settings = $this->get_form_settings( $form_id );

if ( ! empty( $settings['civicrm_auth_checksum'] ) ) {
return parent::add_form_settings_menu( $tabs, $form_id );
} else {
return $tabs;
}
}

public function form_settings_fields( $form ) {
$settings = $this->get_form_settings( $form ) ?: [];

$fields = [];

// Legacy field, don't allow for new forms.
// @TODO Add documentation for alternative approach.
if($settings['civicrm_auth_checksum']) {
if ( ! empty( $settings['civicrm_auth_checksum'] ) ) {
$fields[] = [
// 'label' => esc_html__( 'Allow authentication with checksum', 'gf-civicrm' ),
'type' => 'checkbox',
'name' => 'civicrm_auth_checksum',
'description' => wp_kses(sprintf(__(
'<strong>Deprecated</strong>: This option is not recommended and <strong>poses a hypothetical security risk</strong>. Switch to the replacement workflow using Form Processor capabilities outlined <a target="_blank" href="%s">in the README</a>.',
'<strong>Nonfunctional</strong>: This option is no longer functional due to a <strong>security risk</strong>. Switch to the replacement workflow using Form Processor capabilities outlined <a target="_blank" href="%s">in the README</a>.',
'gf-civicrm'
), 'https://github.com/agileware/gf-civicrm/tree/main?tab=readme-ov-file#processing-form-submissions-as-a-specific-contact'), 'data'),
'choices' => [
Expand Down
2 changes: 1 addition & 1 deletion gf-civicrm.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Description: Extends Gravity Forms to get option lists and defaults from linked CiviCRM Form Processors
* Author: Agileware
* Author URI: https://agileware.com.au
* Version: 1.8.1
* Version: 1.9.0
* Text Domain: gf-civicrm
*
* Copyright (c) Agileware Pty Ltd (email : [email protected])
Expand Down

0 comments on commit 769e84b

Please sign in to comment.