Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support App Bridge 2.0 in shopify_app #1241

Merged
merged 2 commits into from
Apr 19, 2021
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
15 changes: 14 additions & 1 deletion docs/Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* [My app is still using cookies to authenticate](#my-app-is-still-using-cookies-to-authenticate)
* [My app can't make requests to the Shopify API](#my-app-cant-make-requests-to-the-shopify-api)

[Migrating to App Bridge 2.0](#migrating-to-app-bridge-2.0)

## Generators

### The shopify_app:install generator hangs
Expand Down Expand Up @@ -138,4 +140,15 @@ _Example:_ If your embedded app cannot handle server-side XHR redirects, then co
X-Shopify-API-Request-Failure-Unauthorized: true
```

Then, use the [Shopify App Bridge Redirect](https://shopify.dev/tools/app-bridge/actions/navigation/redirect) action to redirect your app frontend to the app login URL if this header is set.
Then, use the [Shopify App Bridge Redirect](https://shopify.dev/tools/app-bridge/actions/navigation/redirect) action to redirect your app frontend to the app login URL if this header is set.

## Migrating to App Bridge 2.0

In order to upgrade your embedded app to the latest App Bridge 2.0 version, please refer to the [migration guide](https://shopify.dev/tutorials/migrate-your-app-to-app-bridge-2).

To ensure that your app's embedded layout doesn't import App Bridge 2.0 before fully migrating, make the following change to bind it to v1.x.

```diff
- <script src="https://unpkg.com/@shopify/app-bridge"></script>
+ <script src="https://unpkg.com/@shopify/app-bridge@1"></script>
```
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

// Save a session token for future requests
window.sessionToken = await new Promise((resolve) => {
app.subscribe(SessionToken.ActionType.RESPOND, (data) => {
app.subscribe(SessionToken.Action.RESPOND, (data) => {
resolve(data.sessionToken || "");
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ class HomeController < ApplicationController

def index
@shop_origin = current_shopify_domain
@host = params[:host]
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@

<%= render 'layouts/flash_messages' %>

<script src="https://unpkg.com/@shopify/app-bridge@1"></script>
<script src="https://unpkg.com/@shopify/app-bridge@2"></script>

<%= content_tag(:div, nil, id: 'shopify-app-init', data: {
api_key: ShopifyApp.configuration.api_key,
shop_origin: @shop_origin || (@current_shopify_session.domain if @current_shopify_session),
host: @host,
debug: Rails.env.development?
} ) %>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ document.addEventListener('DOMContentLoaded', () => {
var createApp = AppBridge.default;
window.app = createApp({
apiKey: data.apiKey,
shopOrigin: data.shopOrigin,
host: data.host,
});

var actions = AppBridge.actions;
Expand Down
12 changes: 10 additions & 2 deletions lib/shopify_app/controller_concerns/login_protection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ module LoginProtection

class ShopifyDomainNotFound < StandardError; end

class ShopifyHostNotFound < StandardError; end

included do
after_action :set_test_cookie
rescue_from ActiveResource::UnauthorizedAccess, with: :close_session
Expand Down Expand Up @@ -103,6 +105,12 @@ def jwt_shopify_user_id
request.env['jwt.shopify_user_id']
end

def host
return params[:host] if params[:host].present?

raise ShopifyHostNotFound
end

def redirect_to_login
if request.xhr?
head(:unauthorized)
Expand Down Expand Up @@ -216,8 +224,8 @@ def sanitized_params

def return_address
return base_return_address unless ShopifyApp.configuration.allow_jwt_authentication
return_address_with_params(shop: current_shopify_domain)
rescue ShopifyDomainNotFound
return_address_with_params(shop: current_shopify_domain, host: host)
rescue ShopifyDomainNotFound, ShopifyHostNotFound
Comment on lines +227 to +228
Copy link
Contributor

Choose a reason for hiding this comment

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

This is needed because of the following:

def respond_successfully
if jwt_request?
head(:ok)
else
redirect_to(return_address)
end
end

Copy link
Contributor

Choose a reason for hiding this comment

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

Things I'm unsure about here:

  • Right now, there are two known places that use return_address in this code base. Is raising when host isn't found the the correct move here?
  • What other tests are affected by this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Considering we currently throw a similar exception for the domain, it makes sense to me to continue to throw here.

base_return_address
end

Expand Down
4 changes: 2 additions & 2 deletions test/controllers/callback_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,9 @@ class CallbackControllerTest < ActionController::TestCase
ShopifyApp.configuration.allow_jwt_authentication = true
mock_shopify_omniauth

get :callback, params: { shop: 'shop' }
get :callback, params: { shop: 'shop', host: 'test-host' } # host is required for App Bridge 2.0

assert_redirected_to "/?shop=#{TEST_SHOPIFY_DOMAIN}"
assert_redirected_to "/?host=test-host&shop=#{TEST_SHOPIFY_DOMAIN}"
end

test "#callback performs install_webhook job after JWT authentication" do
Expand Down