Skip to content

Commit

Permalink
add allowed_drift config option, pass to use Guardian, note in RE…
Browse files Browse the repository at this point in the history
…ADME (#63)

* session tokens encoded on client may have future `nbf` value
* Guardian correctly returns `{:error, :token_not_yet_valid}`
* Shopify-official python package added 10s of "leeway":
  Shopify/shopify_python_api#609
  • Loading branch information
kenichi authored Apr 28, 2023
1 parent ced666a commit 05282ee
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ config :shopifex,
scopes: "read_inventory,write_inventory,read_products,write_products,read_orders",
api_key: "shopifyapikey123",
secret: "shopifyapisecret456",
webhook_topics: ["app/uninstalled"] # These are automatically subscribed on a store upon install
webhook_topics: ["app/uninstalled"], # These are automatically subscribed on a store upon install
allowed_drift: 10_000 # session token exp/nbf tolerance in ms (defaults to 10s)
```

Update your `endpoint.ex` to include the custom body parser. This is necessary for HMAC validation to work.
Expand Down
9 changes: 8 additions & 1 deletion lib/shopifex/guardian.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
defmodule Shopifex.Guardian do
# AppBridge frequently sends future `nbf`, and it causes `{:error, :token_not_yet_valid}`.
# Accept few seconds clock skew to avoid this error.
#
# see: https://github.com/Shopify/shopify_python_api/blob/master/shopify/session_token.py#L58-L60
@allowed_drift Application.compile_env(:shopifex, :allowed_drift, 10_000)

use Guardian,
otp_app: :shopifex,
issuer: {Application, :get_env, [:shopifex, :app_name]},
secret_key: {Application, :get_env, [:shopifex, :secret]},
allowed_algos: ["HS512", "HS256"]
allowed_algos: ["HS512", "HS256"],
allowed_drift: @allowed_drift

def subject_for_token(shop, _claims), do: {:ok, Shopifex.Shops.get_url(shop)}

Expand Down
49 changes: 49 additions & 0 deletions test/shopifex/guardian_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
defmodule Shopifex.GuardianTest do
use ExUnit.Case

describe "allowed_drift defaults" do
test "accepts tokens with nbf up to 10s in the future" do
future =
DateTime.utc_now()
|> DateTime.add(9)
|> DateTime.to_unix()

{:ok, jwt} = Guardian.Token.Jwt.create_token(Shopifex.Guardian, %{"nbf" => future})

assert {:ok, _claims} = Shopifex.Guardian.decode_and_verify(jwt)
end

test "accepts tokens with exp up to 10s in the past" do
past =
DateTime.utc_now()
|> DateTime.add(-9)
|> DateTime.to_unix()

{:ok, jwt} = Guardian.Token.Jwt.create_token(Shopifex.Guardian, %{"exp" => past})

assert {:ok, _claims} = Shopifex.Guardian.decode_and_verify(jwt)
end

test "rejects tokens with nbf more than 10s in the future" do
future =
DateTime.utc_now()
|> DateTime.add(11)
|> DateTime.to_unix()

{:ok, jwt} = Guardian.Token.Jwt.create_token(Shopifex.Guardian, %{"nbf" => future})

assert {:error, :token_not_yet_valid} = Shopifex.Guardian.decode_and_verify(jwt)
end

test "rejects tokens with exp more than 10s in the past" do
past =
DateTime.utc_now()
|> DateTime.add(-11)
|> DateTime.to_unix()

{:ok, jwt} = Guardian.Token.Jwt.create_token(Shopifex.Guardian, %{"exp" => past})

assert {:error, :token_expired} = Shopifex.Guardian.decode_and_verify(jwt)
end
end
end

0 comments on commit 05282ee

Please sign in to comment.