Skip to content

Commit

Permalink
Use wpcc onboarding flow for account creation during oauth login by d…
Browse files Browse the repository at this point in the history
…efault (#83026)

* Use wpcc flow for account creation of oauth clients

* Use /start/account flow for all account creation from login with redirectTo

* Continue to support / ignore signupFlow param

* Add unit tests

* Add tests around jetpack connect

* Add test to confirm migraiton flow

* Handle signup_flow in an expected way

---------

Co-authored-by: DustyReagan <[email protected]>
  • Loading branch information
lsl and DustyReagan authored Oct 18, 2023
1 parent 6d85ba6 commit 7d8095f
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 16 deletions.
46 changes: 31 additions & 15 deletions client/lib/login/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function pathWithLeadingSlash( path ) {
}

export function getSignupUrl( currentQuery, currentRoute, oauth2Client, locale, pathname ) {
let signupUrl = config( 'signup_url' );
const signupUrl = config( 'signup_url' );

const redirectTo = get( currentQuery, 'redirect_to', '' );
const signupFlow = get( currentQuery, 'signup_flow' );
Expand Down Expand Up @@ -74,14 +74,11 @@ export function getSignupUrl( currentQuery, currentRoute, oauth2Client, locale,
* this case, the redirect_to will handle signups as part of the flow. Use the
* `redirect_to` parameter directly for signup.
*/
signupUrl = currentQuery.redirect_to;
} else {
signupUrl = '/jetpack/connect';
return currentQuery.redirect_to;
}
return '/jetpack/connect';
} else if ( '/jetpack-connect' === pathname ) {
signupUrl = '/jetpack/connect';
} else if ( signupFlow ) {
signupUrl += '/' + signupFlow;
return '/jetpack/connect';
}

if ( isAkismetOAuth2Client( oauth2Client ) || isIntenseDebateOAuth2Client( oauth2Client ) ) {
Expand All @@ -90,12 +87,12 @@ export function getSignupUrl( currentQuery, currentRoute, oauth2Client, locale,
oauth2_client_id: oauth2Client.id,
oauth2_redirect: redirectTo,
} );
signupUrl = `${ signupUrl }/${ oauth2Flow }?${ oauth2Params.toString() }`;
return `${ signupUrl }/${ oauth2Flow }?${ oauth2Params.toString() }`;
}

// Gravatar powered clients signup via the magic login page
if ( isGravPoweredOAuth2Client( oauth2Client ) ) {
signupUrl = login( {
// Gravatar powered clients signup via the magic login page
return login( {
locale,
twoFactorAuthType: 'link',
oauth2ClientId: oauth2Client.id,
Expand All @@ -109,7 +106,7 @@ export function getSignupUrl( currentQuery, currentRoute, oauth2Client, locale,
oauth2_client_id: oauth2Client.id,
oauth2_redirect: redirectTo,
} );
signupUrl = `${ signupUrl }/${ oauth2Flow }?${ oauth2Params.toString() }`;
return `${ signupUrl }/${ oauth2Flow }?${ oauth2Params.toString() }`;
}

if ( oauth2Client && isWooOAuth2Client( oauth2Client ) ) {
Expand All @@ -120,26 +117,45 @@ export function getSignupUrl( currentQuery, currentRoute, oauth2Client, locale,
if ( wccomFrom ) {
oauth2Params.set( 'wccom-from', wccomFrom );
}
signupUrl = `${ signupUrl }/wpcc?${ oauth2Params.toString() }`;
return `${ signupUrl }/wpcc?${ oauth2Params.toString() }`;
}

if ( oauth2Client && isJetpackCloudOAuth2Client( oauth2Client ) ) {
const oauth2Params = new URLSearchParams( {
oauth2_client_id: oauth2Client.id,
oauth2_redirect: redirectTo,
} );
signupUrl = `${ signupUrl }/wpcc?${ oauth2Params.toString() }`;
return `${ signupUrl }/wpcc?${ oauth2Params.toString() }`;
}

if ( oauth2Client ) {
const oauth2Params = new URLSearchParams( {
oauth2_client_id: oauth2Client.id,
oauth2_redirect: redirectTo,
} );
return `${ signupUrl }/wpcc?${ oauth2Params.toString() }`;
}

if ( signupFlow ) {
if ( redirectTo ) {
const params = new URLSearchParams( {
redirect_to: redirectTo,
} );
return `${ signupUrl }/${ signupFlow }?${ params.toString() }`;
}
return `${ signupUrl }/${ signupFlow }`;
}

if (
isFromMigrationPlugin ||
isFromPublicAPIConnectFlow ||
( includes( redirectTo, 'action=jetpack-sso' ) && includes( redirectTo, 'sso_nonce=' ) )
( includes( redirectTo, 'action=jetpack-sso' ) && includes( redirectTo, 'sso_nonce=' ) ) ||
redirectTo
) {
const params = new URLSearchParams( {
redirect_to: redirectTo,
} );
signupUrl = `/start/account?${ params.toString() }`;
return `${ signupUrl }/account?${ params.toString() }`;
}

return signupUrl;
Expand Down
189 changes: 188 additions & 1 deletion client/lib/login/test/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { pathWithLeadingSlash } from 'calypso/lib/login';
import { pathWithLeadingSlash, getSignupUrl } from 'calypso/lib/login';

describe( 'pathWithLeadingSlash', () => {
test( 'should add leading slash', () => {
Expand All @@ -20,3 +20,190 @@ describe( 'pathWithLeadingSlash', () => {
}
} );
} );

jest.mock( '@automattic/calypso-config', () => ( {
__esModule: true,
default: jest.fn( ( key ) => {
switch ( key ) {
case 'signup_url':
return '/start';
default:
return null;
}
} ),
} ) );

describe( 'getSignupUrl', () => {
test( 'should work for /log-in route', () => {
const currentRoute = '/log-in';
expect( getSignupUrl( undefined, currentRoute, null, 'en', '' ) ).toEqual( '/start' );
} );

test( 'should work for /log-in route with redirect_to', () => {
const currentQuery = {
redirect_to: '/me/',
};
const currentRoute = '/log-in';
expect( getSignupUrl( currentQuery, currentRoute, null, 'en', '' ) ).toEqual(
'/start/account?redirect_to=%2Fme%2F'
);
} );

test( 'should work for VaultPress route', () => {
const currentQuery = {
client_id: '930',
redirect_to:
'https://public-api.wordpress.com/oauth2/authorize?client_id=930&response_type=code&blog_id=0&state=1234&redirect_uri=https%3A%2F%2Fvaultpress.com%2Flogin%2F%3Faction%3Drequest_access_token&from-calypso=1',
};
const currentRoute = '/log-in';
const oauth2Client = {
id: 930,
name: 'vaultpress',
title: 'VaultPress',
icon: 'https://vaultpress.com/images/vaultpress-wpcc-nav-2x.png',
url: 'http://vaultpress.com/',
};
expect( getSignupUrl( currentQuery, currentRoute, oauth2Client, 'en', '' ) ).toEqual(
'/start/wpcc?oauth2_client_id=930&oauth2_redirect=https%3A%2F%2Fpublic-api.wordpress.com%2Foauth2%2Fauthorize%3Fclient_id%3D930%26response_type%3Dcode%26blog_id%3D0%26state%3D1234%26redirect_uri%3Dhttps%253A%252F%252Fvaultpress.com%252Flogin%252F%253Faction%253Drequest_access_token%26from-calypso%3D1'
);
} );

test( 'should work for IntenseDebate route', () => {
const currentQuery = {
client_id: '2665',
redirect_to:
'https://public-api.wordpress.com/oauth2/authorize?client_id=2665&response_type=code&blog_id=0&state=1234&redirect_uri=https%3A%2F%2Fintensedebate.com%2Fconnect%2F%3Faction%3Drequest_access_token&from-calypso=1',
};
const currentRoute = '/log-in';
const oauth2Client = {
id: 2665,
name: 'intensedebate',
title: 'IntenseDebate',
icon: 'https://intensedebate.com/images/svg/intensedebate-logo.svg',
url: 'https://intensedebate.com/',
};
expect( getSignupUrl( currentQuery, currentRoute, oauth2Client, 'en', '' ) ).toEqual(
'/start/wpcc?oauth2_client_id=2665&oauth2_redirect=https%3A%2F%2Fpublic-api.wordpress.com%2Foauth2%2Fauthorize%3Fclient_id%3D2665%26response_type%3Dcode%26blog_id%3D0%26state%3D1234%26redirect_uri%3Dhttps%253A%252F%252Fintensedebate.com%252Fconnect%252F%253Faction%253Drequest_access_token%26from-calypso%3D1'
);
} );

test( 'should work for Gravatar route', () => {
const currentQuery = {
redirect_to:
'https://public-api.wordpress.com/oauth2/authorize?client_id=1854&response_type=code&blog_id=0&state=1234&redirect_uri=https%3A%2F%2Fgravatar.com%2Fconnect%2F%3Faction%3Drequest_access_token&from-calypso=1',
client_id: '1854',
};
const currentRoute = '/log-in';
const oauth2Client = {
id: 1854,
name: 'gravatar',
title: 'Gravatar',
icon: 'https://gravatar.com/images/grav-logo-blue.svg',
favicon: 'https://gravatar.com/favicon.ico',
url: 'https://gravatar.com/',
};
expect( getSignupUrl( currentQuery, currentRoute, oauth2Client, 'en', '' ) ).toEqual(
'/log-in/link?redirect_to=https%3A%2F%2Fpublic-api.wordpress.com%2Foauth2%2Fauthorize%3Fclient_id%3D1854%26response_type%3Dcode%26blog_id%3D0%26state%3D1234%26redirect_uri%3Dhttps%253A%252F%252Fgravatar.com%252Fconnect%252F%253Faction%253Drequest_access_token%26from-calypso%3D1&client_id=1854'
);
} );

test( 'should work for WooCommmerce route', () => {
const currentQuery = {
client_id: '50916',
redirect_to:
'https://public-api.wordpress.com/oauth2/authorize/?response_type=code&client_id=50916&state=1234&redirect_uri=https%3A%2F%2Fwoocommerce.com%2Fwc-api%2Fwpcom-signin%3Fnext%3D%252F&blog_id=0&wpcom_connect=1&wccom-from&calypso_env=production&from-calypso=1',
};
const currentRoute = '/log-in';
const oauth2Client = {
id: 50916,
name: 'woo',
title: 'WooCommerce.com',
icon: 'https://woocommerce.com/wp-content/themes/woo/images/[email protected]',
url: 'https://woocommerce.com',
};
expect( getSignupUrl( currentQuery, currentRoute, oauth2Client, 'en', '' ) ).toEqual(
'/start/wpcc?oauth2_client_id=50916&oauth2_redirect=https%3A%2F%2Fpublic-api.wordpress.com%2Foauth2%2Fauthorize%2F%3Fresponse_type%3Dcode%26client_id%3D50916%26state%3D1234%26redirect_uri%3Dhttps%253A%252F%252Fwoocommerce.com%252Fwc-api%252Fwpcom-signin%253Fnext%253D%25252F%26blog_id%3D0%26wpcom_connect%3D1%26wccom-from%26calypso_env%3Dproduction%26from-calypso%3D1'
);
} );

test( 'should work for Jetpack Cloud route', () => {
const currentQuery = {
client_id: '69040',
redirect_to:
'https://public-api.wordpress.com/oauth2/authorize?response_type=token&client_id=69040&redirect_uri=https%3A%2F%2Fcloud.jetpack.com%2Fconnect%2Foauth%2Ftoken%3Fnext%3D%252Fpricing&scope=global&blog_id=0&from-calypso=1',
};
const currentRoute = '/log-in';
const oauth2Client = {
id: 69040,
name: 'jetpack-cloud',
title: 'Jetpack.com Staging',
url: 'https://jetpack.com',
};
expect( getSignupUrl( currentQuery, currentRoute, oauth2Client, 'en', '' ) ).toEqual(
'/start/wpcc?oauth2_client_id=69040&oauth2_redirect=https%3A%2F%2Fpublic-api.wordpress.com%2Foauth2%2Fauthorize%3Fresponse_type%3Dtoken%26client_id%3D69040%26redirect_uri%3Dhttps%253A%252F%252Fcloud.jetpack.com%252Fconnect%252Foauth%252Ftoken%253Fnext%253D%25252Fpricing%26scope%3Dglobal%26blog_id%3D0%26from-calypso%3D1'
);
} );

test( 'signup_flow modifies /start base', () => {
expect( getSignupUrl( { signup_flow: 'test' }, '/log-in', null, 'en', '' ) ).toEqual(
'/start/test'
);
expect(
getSignupUrl(
{ signup_flow: 'test', redirect_to: 'https://example.com' },
'/log-in',
null,
'en',
''
)
).toEqual( '/start/test?redirect_to=https%3A%2F%2Fexample.com' );
expect(
getSignupUrl(
{ signup_flow: 'account', redirect_to: 'https://example.com' },
'/log-in',
null,
'en',
''
)
).toEqual( '/start/account?redirect_to=https%3A%2F%2Fexample.com' );
} );

test( '/log-in/jetpack uses /jetpack/connect', () => {
expect( getSignupUrl( {}, '/log-in/jetpack', null, 'en', '' ) ).toEqual( '/jetpack/connect' );
expect( getSignupUrl( {}, '/log-in/jetpack/es', null, 'es', '' ) ).toEqual(
'/jetpack/connect'
);
} );

test( '/log-in/jetpack?redirect_to with nonce uses redirect_to', () => {
expect(
getSignupUrl(
{ redirect_to: 'https://example.com/jetpack/connect/authorize?&_wp_nonce=example' },
'/log-in/jetpack',
null,
'en',
''
)
).toEqual( 'https://example.com/jetpack/connect/authorize?&_wp_nonce=example' );
} );

test( '/log-in/jetpack?redirect_to without nonce uses /jetpack/connect', () => {
expect(
getSignupUrl( { redirect_to: 'https://example.com' }, '/log-in/jetpack', null, 'en', '' )
).toEqual( '/jetpack/connect' );
} );

test( 'redirect_to=public.api/connect/?action=verify uses /start/account with ?redirect_to passthrough', () => {
expect(
getSignupUrl(
{ redirect_to: 'https://public-api.wordpress.com/public.api/connect/?action=verify' },
'/log-in',
null,
'en',
''
)
).toEqual(
'/start/account?redirect_to=https%3A%2F%2Fpublic-api.wordpress.com%2Fpublic.api%2Fconnect%2F%3Faction%3Dverify'
);
} );
} );

0 comments on commit 7d8095f

Please sign in to comment.