-
Notifications
You must be signed in to change notification settings - Fork 699
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #951 from Shopify/jwt-callback
Implement JWT callback endpoint
- Loading branch information
Showing
9 changed files
with
226 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
module ShopifyApp | ||
class JWTMiddleware | ||
TOKEN_REGEX = /^Bearer\s+(.*?)$/ | ||
|
||
def initialize(app) | ||
@app = app | ||
end | ||
|
||
def call(env) | ||
return call_next(env) unless authorization_header(env) | ||
|
||
token = extract_token(env) | ||
return call_next(env) unless token | ||
|
||
set_env_variables(token, env) | ||
call_next(env) | ||
end | ||
|
||
private | ||
|
||
def call_next(env) | ||
@app.call(env) | ||
end | ||
|
||
def authorization_header(env) | ||
env['HTTP_AUTHORIZATION'] | ||
end | ||
|
||
def extract_token(env) | ||
match = authorization_header(env).match(TOKEN_REGEX) | ||
match && match[1] | ||
end | ||
|
||
def set_env_variables(token, env) | ||
jwt = ShopifyApp::JWT.new(token) | ||
|
||
env['jwt.shopify_domain'] = jwt.shopify_domain | ||
env['jwt.shopify_user_id'] = jwt.shopify_user_id | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# frozen_string_literal: true | ||
require 'test_helper' | ||
|
||
class ShopifyApp::JWTMiddlewareTest < ActiveSupport::TestCase | ||
def simple_app | ||
lambda { |env| | ||
[200, { "Content-Type" => "text/yaml" }, env['jwt.shopify_domain'] || ''] | ||
} | ||
end | ||
|
||
def app | ||
Rack::Lint.new(ShopifyApp::JWTMiddleware.new(simple_app)) | ||
end | ||
|
||
test 'does not change env if no authorization header' do | ||
env = Rack::MockRequest.env_for('https://example.com') | ||
|
||
app.call(env) | ||
|
||
assert_nil env['jwt.shopify_domain'] | ||
end | ||
|
||
test 'does not change env if no bearer token' do | ||
env = Rack::MockRequest.env_for('https://example.com') | ||
env['HTTP_AUTHORIZATION'] = 'something' | ||
|
||
app.call(env) | ||
|
||
assert_nil env['jwt.shopify_domain'] | ||
end | ||
|
||
test 'does not add the shop to the env if nil shop value' do | ||
jwt_mock = Struct.new(:shopify_domain, :shopify_user_id).new(nil, 1) | ||
ShopifyApp::JWT.stubs(:new).with('abc').returns(jwt_mock) | ||
|
||
env = Rack::MockRequest.env_for('https://example.com') | ||
env['HTTP_AUTHORIZATION'] = 'Bearer abc' | ||
|
||
app.call(env) | ||
|
||
assert_nil env['jwt.shopify_domain'] | ||
assert_equal 1, env['jwt.shopify_user_id'] | ||
end | ||
|
||
test 'does not add the user to the env if nil user value' do | ||
jwt_mock = Struct.new(:shopify_domain, :shopify_user_id).new('example.myshopify.com', nil) | ||
ShopifyApp::JWT.stubs(:new).with('abc').returns(jwt_mock) | ||
|
||
env = Rack::MockRequest.env_for('https://example.com') | ||
env['HTTP_AUTHORIZATION'] = 'Bearer abc' | ||
|
||
app.call(env) | ||
|
||
assert_equal 'example.myshopify.com', env['jwt.shopify_domain'] | ||
assert_nil env['jwt.shopify_user_id'] | ||
end | ||
|
||
test 'sets shopify_domain and shopify_user_id if non-nil values' do | ||
jwt_mock = Struct.new(:shopify_domain, :shopify_user_id).new('example.myshopify.com', 1) | ||
ShopifyApp::JWT.stubs(:new).with('abc').returns(jwt_mock) | ||
|
||
env = Rack::MockRequest.env_for('https://example.com') | ||
env['HTTP_AUTHORIZATION'] = 'Bearer abc' | ||
|
||
app.call(env) | ||
|
||
assert_equal 'example.myshopify.com', env['jwt.shopify_domain'] | ||
assert_equal 1, env['jwt.shopify_user_id'] | ||
end | ||
|
||
test 'sets the jwt values before calling the next middleware' do | ||
jwt_mock = Struct.new(:shopify_domain, :shopify_user_id).new('example.myshopify.com', 1) | ||
ShopifyApp::JWT.stubs(:new).with('abc').returns(jwt_mock) | ||
|
||
env = Rack::MockRequest.env_for('https://example.com') | ||
env['HTTP_AUTHORIZATION'] = 'Bearer abc' | ||
|
||
_, _, body = ShopifyApp::JWTMiddleware.new(simple_app).call(env) | ||
|
||
assert_equal 'example.myshopify.com', body | ||
end | ||
end |