Skip to content

Commit

Permalink
[memberships] Remove token from url (#33561)
Browse files Browse the repository at this point in the history
* Remove sending token as GET param and refactor

* Create add-memberships-remove-token-from-url

* Amend $email_confirmation_pending to retrieve the data from the token

Fix issue when subscription is pending and do not rely on subscribe=success

* Fix for tests
  • Loading branch information
millerf authored Oct 16, 2023
1 parent d75eaf6 commit 3d71a28
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: enhancement

Subscriptions: Do not display token in URL
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ public function initialize() {
public function get_and_set_token_from_request() {
// URL token always has a precedence, so it can overwrite the cookie when new data available.
$token = $this->token_from_request();

if ( null !== $token ) {
$this->set_token_cookie( $token );
return $token;
}

return $token;
return $this->token_from_cookie();
}

/**
Expand All @@ -74,30 +74,14 @@ public function visitor_can_view_content( $valid_plan_ids, $access_level ) {
global $current_user;
$old_user = $current_user; // backup the current user so we can set the current user to the token user for paywall purposes

// URL token always has a precedence, so it can overwrite the cookie when new data available.
$token = $this->token_from_request();
if ( $token ) {
$this->set_token_cookie( $token );
} else {
$token = $this->token_from_cookie();
}

$is_valid_token = true;

if ( empty( $token ) ) {
// no token, no access.
$is_valid_token = false;
} else {
$payload = $this->decode_token( $token );
if ( empty( $payload ) ) {
$is_valid_token = false;
}
$token = $this->get_and_set_token_from_request();
$payload = $this->decode_token( $token );
$is_valid_token = ! empty( $payload );

if ( $is_valid_token && isset( $payload['user_id'] ) ) {
// set the current user to the payload's user id
if ( isset( $payload['user_id'] ) ) {
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$current_user = get_user_by( 'id', $payload['user_id'] );
}
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$current_user = get_user_by( 'id', $payload['user_id'] );
}

$is_blog_subscriber = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,7 @@
import './view.scss';
import {
setPurchaseResultCookie,
reloadPageWithPremiumContentQueryString,
} from '../../../extensions/shared/memberships';
import { handleIframeResult } from '../../../extensions/shared/memberships';

document.addEventListener( 'DOMContentLoaded', function () {
let premiumContentJWTToken = '';

/**
* @typedef globalThis
* @param {globalThis.Event} eventFromIframe - message event that gets emitted in the checkout iframe.
* @listens window#message
*/
function handleIframeResult( eventFromIframe ) {
if ( eventFromIframe.origin === 'https://subscribe.wordpress.com' && eventFromIframe.data ) {
const data = JSON.parse( eventFromIframe.data );
if ( data && data.result && data.result.jwt_token ) {
// We save the token for now, doing nothing.
premiumContentJWTToken = data.result.jwt_token;
setPurchaseResultCookie( premiumContentJWTToken );
}
if ( data && data.action === 'close' && premiumContentJWTToken ) {
reloadPageWithPremiumContentQueryString( premiumContentJWTToken );
}
}
}

if ( typeof window !== 'undefined' ) {
window.addEventListener( 'message', handleIframeResult, false );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

use Automattic\Jetpack\Blocks;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Jetpack_Token_Subscription_Service;
use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\Token_Subscription_Service;
use Automattic\Jetpack\Extensions\Premium_Content\Subscription_Service\WPCOM_Token_Subscription_Service;
use Automattic\Jetpack\Status;
use Automattic\Jetpack\Status\Host;
use Jetpack;
Expand Down Expand Up @@ -926,7 +928,14 @@ function add_paywall( $the_content ) {

$post_access_level = Jetpack_Memberships::get_post_access_level();

$paywalled_content = get_paywall_content( $post_access_level, isset( $_GET['subscribe'] ) && 'success' === $_GET['subscribe'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
require_once JETPACK__PLUGIN_DIR . 'extensions/blocks/premium-content/_inc/subscription-service/include.php';
$token_service = is_wpcom() ? new WPCOM_Token_Subscription_Service() : new Jetpack_Token_Subscription_Service();
$token = $token_service->get_and_set_token_from_request();
$payload = $token_service->decode_token( $token );
$is_valid_token = ! empty( $payload );
$email_confirmation_pending = $is_valid_token && isset( $payload['blog_sub'] ) && $payload['blog_sub'] === 'pending';

$paywalled_content = get_paywall_content( $post_access_level, $email_confirmation_pending ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

if ( has_block( \Automattic\Jetpack\Extensions\Paywall\BLOCK_NAME ) ) {
if ( strpos( $the_content, \Automattic\Jetpack\Extensions\Paywall\BLOCK_HTML ) ) {
Expand Down Expand Up @@ -1101,7 +1110,7 @@ function get_paywall_blocks( $newsletter_access_level ) {
* @return string
*/
function get_paywall_blocks_subscribe_pending() {
$access_heading = esc_html__( 'Verify your email and continue reading', 'jetpack' );
$access_heading = esc_html__( 'Verify your email to continue reading', 'jetpack' );

$subscribe_text = esc_html__( 'Please check your inbox to confirm your subscription.', 'jetpack' );

Expand Down
31 changes: 2 additions & 29 deletions projects/plugins/jetpack/extensions/blocks/subscriptions/view.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
/* global tb_show, tb_remove */
/* global tb_show */

import './view.scss';
import '../../shared/memberships.scss';

import domReady from '@wordpress/dom-ready';
import {
setPurchaseResultCookie,
reloadPageWithPremiumContentQueryString,
} from '../../../extensions/shared/memberships';
import { handleIframeResult } from '../../../extensions/shared/memberships';

domReady( function () {
const form = document.querySelector( '.wp-block-jetpack-subscriptions__container form' );
if ( ! form ) {
return;
}
let premiumContentJWTToken = '';
if ( ! form.payments_attached ) {
form.payments_attached = true;
form.addEventListener( 'submit', function ( event ) {
Expand Down Expand Up @@ -46,29 +42,6 @@ domReady( function () {
window.scrollTo( 0, 0 );
tb_show( null, url + '&TB_iframe=true', null );

//TODO: Unify this code across premium content, subscribe and payment button.
const handleIframeResult = function ( eventFromIframe ) {
if (
eventFromIframe.origin === 'https://subscribe.wordpress.com' &&
eventFromIframe.data
) {
const data = JSON.parse( eventFromIframe.data );
if ( data && data.result && data.result.jwt_token ) {
// We save the token for now, doing nothing.
premiumContentJWTToken = data.result.jwt_token;
setPurchaseResultCookie( premiumContentJWTToken );
} else if ( data && data.action === 'close' && premiumContentJWTToken ) {
// The token was set during the purchase flow, we want to relead the whole page with token in query string so it recognizes that the user is logged in.
reloadPageWithPremiumContentQueryString( premiumContentJWTToken, {
subscribe: 'success',
} );
} else if ( data && data.action === 'close' ) {
// User just aborted.
window.removeEventListener( 'message', handleIframeResult );
tb_remove();
}
}
};
window.addEventListener( 'message', handleIframeResult, false );
const tbWindow = document.querySelector( '#TB_window' );
tbWindow.classList.add( 'jetpack-memberships-modal' );
Expand Down
22 changes: 16 additions & 6 deletions projects/plugins/jetpack/extensions/shared/memberships.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
/* global tb_show, tb_remove */

let premiumContentJWTTokenForCookie = '';

/**
* Since "close" button is inside our checkout iframe, in order to close it, it has to pass a message to higher scope to close the modal.
*
* @param {event} eventFromIframe - message event that gets emmited in the checkout iframe.
* @typedef globalThis
* @param {globalThis.Event} eventFromIframe - message event that gets emitted in the checkout iframe.
* @listens window#message
*/
function handleIframeResult( eventFromIframe ) {
export function handleIframeResult( eventFromIframe ) {
if ( eventFromIframe.origin === 'https://subscribe.wordpress.com' && eventFromIframe.data ) {
const data = JSON.parse( eventFromIframe.data );
if ( data && data.action === 'close' ) {
if ( data && data.result && data.result.jwt_token ) {
// We save the token for now, doing nothing.
premiumContentJWTTokenForCookie = data.result.jwt_token;
setPurchaseResultCookie( premiumContentJWTTokenForCookie );
}
if ( data && data.action === 'close' && premiumContentJWTTokenForCookie ) {
// The token was set during the purchase flow, we want to reload the whole page so the content is displayed
window.location.reload();
} else if ( data && data.action === 'close' ) {
// User just aborted.
window.removeEventListener( 'message', handleIframeResult );
tb_remove();
tb_remove && tb_remove();
}
}
}
Expand Down

0 comments on commit 3d71a28

Please sign in to comment.