Skip to content
This repository has been archived by the owner on Sep 25, 2024. It is now read-only.

koa-shopify-auth: update redirection page to use App Bridge action #1242

Merged
merged 1 commit into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/koa-shopify-auth/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]

- Updated redirect script to use App Bridge [1242](https://github.com/Shopify/quilt/pull/1242)

## 3.1.37 - 2019-09-23

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import createTopLevelRedirect from './create-top-level-redirect';

import {TEST_COOKIE_NAME} from './index';

export default function createEnableCookiesRedirect(path: string) {
const redirect = createTopLevelRedirect(path);
export default function createEnableCookiesRedirect(
apiKey: string,
path: string,
) {
const redirect = createTopLevelRedirect(apiKey, path);

return function topLevelOAuthRedirect(ctx: Context) {
// This is to avoid a redirect loop if the app doesn't use verifyRequest or set the test cookie elsewhere.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import createTopLevelRedirect from './create-top-level-redirect';

import {TOP_LEVEL_OAUTH_COOKIE_NAME} from './index';

export default function createTopLevelOAuthRedirect(path: string) {
const redirect = createTopLevelRedirect(path);
export default function createTopLevelOAuthRedirect(
apiKey: string,
path: string,
) {
const redirect = createTopLevelRedirect(apiKey, path);

return function topLevelOAuthRedirect(ctx: Context) {
ctx.cookies.set(TOP_LEVEL_OAUTH_COOKIE_NAME, '1');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Context} from 'koa';

import redirectionPage from './redirection-page';

export default function createTopLevelRedirect(path: string) {
export default function createTopLevelRedirect(apiKey: string, path: string) {
return function topLevelRedirect(ctx: Context) {
const {host, query} = ctx;
const {shop} = query;
Expand All @@ -13,8 +13,9 @@ export default function createTopLevelRedirect(path: string) {
const queryString = querystring.stringify(params);

ctx.body = redirectionPage({
origin: `https://${shop}`,
origin: shop,
redirectTo: `https://${host}${path}?${queryString}`,
apiKey,
});
};
}
10 changes: 8 additions & 2 deletions packages/koa-shopify-auth/src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,17 @@ export default function createShopifyAuth(options: OAuthStartOptions) {
const oAuthCallback = createOAuthCallback(config);

const inlineOAuthPath = `${prefix}/auth/inline`;
const topLevelOAuthRedirect = createTopLevelOAuthRedirect(inlineOAuthPath);
const topLevelOAuthRedirect = createTopLevelOAuthRedirect(
config.apiKey,
inlineOAuthPath,
);

const enableCookiesPath = `${oAuthStartPath}/enable_cookies`;
const enableCookies = createEnableCookies(config);
const enableCookiesRedirect = createEnableCookiesRedirect(enableCookiesPath);
const enableCookiesRedirect = createEnableCookiesRedirect(
config.apiKey,
enableCookiesPath,
);

return async function shopifyAuth(ctx: Context, next: NextFunction) {
if (ctx.path === oAuthStartPath && !hasCookieAccess(ctx)) {
Expand Down
17 changes: 10 additions & 7 deletions packages/koa-shopify-auth/src/auth/redirection-page.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
export default function redirectionScript({origin, redirectTo}) {
export default function redirectionScript({origin, redirectTo, apiKey}) {
return `
<script type="text/javascript">
<script src="https://unpkg.com/@shopify/app-bridge@^1"></script> <script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
if (window.top === window.self) {
// If the current window is the 'parent', change the URL by setting location.href
window.location.href = '${redirectTo}';
} else {
// If the current window is the 'child', change the parent's URL with postMessage
data = JSON.stringify({
message: 'Shopify.API.remoteRedirect',
data: { location: '${redirectTo}' }
var AppBridge = window['app-bridge'];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, is there any tests for this util?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing for this particular script, all this file does is render a route with this script to redirect the user out of the iframe in Safari so we can set a cookie.

var createApp = AppBridge.default;
var Redirect = AppBridge.actions.Redirect;
var app = createApp({
apiKey: '${apiKey}',
shopOrigin: '${origin}',
});

window.parent.postMessage(data, '${origin}');
var redirect = Redirect.create(app);
redirect.dispatch(Redirect.Action.REMOTE, '${redirectTo}');
}
});
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ const query = querystring.stringify.bind(querystring);
const baseUrl = 'myapp.com/auth';
const shop = 'shop1.myshopify.io';
const path = '/auth/enable_cookies';
const apiKey = 'somekey';

describe('CreateEnableCookiesRedirect', () => {
it('sets the test cookie', () => {
const enableCookiesRedirect = createEnableCookiesRedirect(path);
const enableCookiesRedirect = createEnableCookiesRedirect(apiKey, path);
const ctx = createMockContext({
url: `https://${baseUrl}?${query({shop})}`,
});
Expand All @@ -28,14 +29,14 @@ describe('CreateEnableCookiesRedirect', () => {
});

it('sets up and calls the top level redirect', () => {
const enableCookiesRedirect = createEnableCookiesRedirect(path);
const enableCookiesRedirect = createEnableCookiesRedirect(apiKey, path);
const ctx = createMockContext({
url: `https://${baseUrl}?${query({shop})}`,
});

enableCookiesRedirect(ctx);

expect(createTopLevelRedirect).toHaveBeenCalledWith(path);
expect(createTopLevelRedirect).toHaveBeenCalledWith(apiKey, path);
expect(mockTopLevelRedirect).toHaveBeenCalledWith(ctx);
});
});
2 changes: 2 additions & 0 deletions packages/koa-shopify-auth/src/auth/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('Index', () => {
await shopifyAuth(ctx, nextFunction);

expect(createEnableCookiesRedirect).toHaveBeenCalledWith(
'myapikey',
'/auth/enable_cookies',
);
expect(mockEnableCookiesRedirect).toHaveBeenCalledWith(ctx);
Expand All @@ -64,6 +65,7 @@ describe('Index', () => {
await shopifyAuth(ctx, nextFunction);

expect(createTopLevelOAuthRedirect).toHaveBeenCalledWith(
'myapikey',
'/auth/inline',
);
expect(mockTopLevelOAuthRedirect).toHaveBeenCalledWith(ctx);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ const query = querystring.stringify.bind(querystring);
const baseUrl = 'myapp.com/auth';
const shop = 'shop1.myshopify.io';
const path = '/auth/inline';
const apiKey = 'somekey';

describe('CreateTopLevelOAuthRedirect', () => {
it('sets the test cookie', () => {
const topLevelOAuthRedirect = createTopLevelOAuthRedirect(path);
const topLevelOAuthRedirect = createTopLevelOAuthRedirect(apiKey, path);
const ctx = createMockContext({
url: `https://${baseUrl}?${query({shop})}`,
});
Expand All @@ -28,14 +29,14 @@ describe('CreateTopLevelOAuthRedirect', () => {
});

it('sets up and calls the top level redirect', () => {
const topLevelOAuthRedirect = createTopLevelOAuthRedirect(path);
const topLevelOAuthRedirect = createTopLevelOAuthRedirect(apiKey, path);
const ctx = createMockContext({
url: `https://${baseUrl}?${query({shop})}`,
});

topLevelOAuthRedirect(ctx);

expect(createTopLevelRedirect).toHaveBeenCalledWith(path);
expect(createTopLevelRedirect).toHaveBeenCalledWith(apiKey, path);
expect(mockTopLevelRedirect).toHaveBeenCalledWith(ctx);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ const query = querystring.stringify.bind(querystring);
const baseUrl = 'myapp.com/auth';
const path = '/path';
const shop = 'shop1.myshopify.io';
const shopOrigin = 'https://shop1.myshopify.io';
const shopOrigin = 'shop1.myshopify.io';
const apiKey = 'fakekey';

describe('TopLevelRedirect', () => {
it('redirects to the provided path with shop parameter', () => {
const topLevelRedirect = createTopLevelRedirect(path);
const topLevelRedirect = createTopLevelRedirect(apiKey, path);
const ctx = createMockContext({
url: `https://${baseUrl}?${query({shop})}`,
});
Expand All @@ -24,6 +25,7 @@ describe('TopLevelRedirect', () => {
redirectionPage({
redirectTo: `https://myapp.com/path?${query({shop})}`,
origin: shopOrigin,
apiKey,
}),
);
});
Expand Down