Skip to content

Commit

Permalink
Merge pull request #4 from GrantBirki/query-string-fixes
Browse files Browse the repository at this point in the history
Query string fixes
  • Loading branch information
GrantBirki authored Oct 16, 2024
2 parents c956615 + 22ec0d3 commit a8b3a5c
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 2 deletions.
30 changes: 30 additions & 0 deletions script/acceptance_tests/server.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,34 @@ get "/crest-client" do |env|
"Hi, %s! You sent a request that was successfully verified with HMAC auth for the crest-client" % env.kemal_authorized_client?
end

post "/submit" do |env|
"Hi, %s! I got your POST request" % env.kemal_authorized_client?
end

# catch-all routes for all other requests and methods
# ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]
get "/catch-all" do |env|
"Hi, %s! Welcome to catch-all" % env.kemal_authorized_client?
end

post "/catch-all" do |env|
"Hi, %s! Welcome to catch-all" % env.kemal_authorized_client?
end

put "/catch-all" do |env|
"Hi, %s! Welcome to catch-all" % env.kemal_authorized_client?
end

patch "/catch-all" do |env|
"Hi, %s! Welcome to catch-all" % env.kemal_authorized_client?
end

delete "/catch-all" do |env|
"Hi, %s! Welcome to catch-all" % env.kemal_authorized_client?
end

options "/catch-all" do |env|
"Hi, %s! Welcome to catch-all" % env.kemal_authorized_client?
end

Kemal.run
104 changes: 103 additions & 1 deletion script/acceptance_tests/tests.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@ require "crest"
require "http/client"
require "spec"

describe "All HTTP Methods" do
["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"].each do |method|
it "successfully validates a #{method} request" do
client = Kemal::Hmac::Client.new("my_standard_client", "my_secret_2")

path = "/catch-all"

headers = HTTP::Headers.new
client.generate_headers(path).each do |key, value|
headers.add(key, value)
end

response = HTTP::Client.get("http://localhost:3000#{path}", headers: headers)

request = HTTP::Request.new(
method,
"/api",
headers: headers,
)

response.status_code.should eq 200
response.body.should contain "Hi, my_standard_client!"
end
end
end

describe "crest" do
it "successfully sends a request with HMAC auth with the crest client to the crest-client endpoint" do
client = Kemal::Hmac::Client.new("my_crest_client", "my_secret")
Expand All @@ -18,10 +44,24 @@ describe "crest" do
response.body.should contain "Hi, my_crest_client!"
end

it "successfully sends a request with HMAC auth with the crest client to the crest-client endpoint with query string params" do
client = Kemal::Hmac::Client.new("my_crest_client", "my_secret")

path = "/crest-client"

response = Crest.get(
"http://localhost:3000#{path}",
headers: client.generate_headers(path)
)

response.status_code.should eq 200
response.body.should contain "Hi, my_crest_client!"
end

it "fails to send a request with HMAC auth with the crest client to the crest-client endpoint" do
client = Kemal::Hmac::Client.new("my_crest_client", "incorrect_secret")

path = "/crest-client"
path = "/crest-client?foo=bar&q=baz&operation=1/2"

begin
Crest.get(
Expand All @@ -33,6 +73,36 @@ describe "crest" do
ex.response.body.should contain "Unauthorized: HMAC token does not match"
end
end

it "fails to send a request with HMAC auth to an endpoint using the POST HTTP verb" do
client = Kemal::Hmac::Client.new("my_crest_client", "incorrect_secret")

path = "/submit"

begin
Crest.post(
"http://localhost:3000#{path}",
headers: client.generate_headers(path)
)
rescue ex : Crest::Unauthorized
ex.response.status_code.should eq 401
ex.response.body.should contain "Unauthorized: HMAC token does not match"
end
end

it "successfully sends a request with HMAC auth with the crest client an endpoint using the POST HTTP verb" do
client = Kemal::Hmac::Client.new("my_crest_client", "my_secret")

path = "/submit"

response = Crest.post(
"http://localhost:3000#{path}",
headers: client.generate_headers(path)
)

response.status_code.should eq 200
response.body.should contain "Hi, my_crest_client! I got your POST request"
end
end

describe "http/client" do
Expand All @@ -52,6 +122,38 @@ describe "http/client" do
response.body.should contain "Hi, my_standard_client!"
end

it "successfully sends a request with HMAC auth with the http-client to an endpoint using the POST HTTP verb" do
client = Kemal::Hmac::Client.new("my_standard_client", "my_secret_2")

path = "/submit"

headers = HTTP::Headers.new
client.generate_headers(path).each do |key, value|
headers.add(key, value)
end

response = HTTP::Client.post("http://localhost:3000#{path}", headers: headers)

response.status_code.should eq 200
response.body.should contain "Hi, my_standard_client! I got your POST request"
end

it "successfully sends a request with HMAC auth with the http-client to the http-client endpoint with query string params" do
client = Kemal::Hmac::Client.new("my_standard_client", "my_secret_2")

path = "/http-client?foo=bar&q=baz&operation=1/2"

headers = HTTP::Headers.new
client.generate_headers(path).each do |key, value|
headers.add(key, value)
end

response = HTTP::Client.get("http://localhost:3000#{path}", headers: headers)

response.status_code.should eq 200
response.body.should contain "Hi, my_standard_client!"
end

it "fails to send a request with HMAC auth with the http-client to the http-client endpoint" do
client = Kemal::Hmac::Client.new("my_standard_client", "bad_secret")

Expand Down
50 changes: 50 additions & 0 deletions spec/kemal-hmac/kemal-hmac_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,56 @@ describe "Kemal::Hmac" do
context.kemal_authorized_client?.should eq(client)
end

it "uses a custom handler and correct HMAC auth and the request flows through successfully with query string params" do
client = "valid-octo-client"
hmac_handler = SpecAuthHandler.new(
hmac_secrets: {client => ["octo-secret-blue", "octo-secret-green"]},
)

hmac_client = Kemal::Hmac::Client.new(client, "octo-secret-green", "SHA256")
headers = hmac_client.generate_headers("/api")

request = HTTP::Request.new(
"GET",
"/api?foo=bar&moon=star",
headers: HTTP::Headers{
"hmac-client" => headers["hmac-client"],
"hmac-timestamp" => headers["hmac-timestamp"],
"hmac-token" => headers["hmac-token"],
},
)

io, context = create_request_and_return_io_and_context(hmac_handler, request)
response = HTTP::Client::Response.from_io(io, decompress: false)
response.status_code.should eq 404
context.kemal_authorized_client?.should eq(client)
end

it "uses a custom handler and correct HMAC auth and the request flows through successfully with query string params incorrecty in the client" do
client = "valid-octo-client"
hmac_handler = SpecAuthHandler.new(
hmac_secrets: {client => ["octo-secret-blue", "octo-secret-green"]},
)

hmac_client = Kemal::Hmac::Client.new(client, "octo-secret-green", "SHA256")
headers = hmac_client.generate_headers("/api?cat=dog&moon=star&q=1")

request = HTTP::Request.new(
"GET",
"/api?foo=bar&moon=star",
headers: HTTP::Headers{
"hmac-client" => headers["hmac-client"],
"hmac-timestamp" => headers["hmac-timestamp"],
"hmac-token" => headers["hmac-token"],
},
)

io, context = create_request_and_return_io_and_context(hmac_handler, request)
response = HTTP::Client::Response.from_io(io, decompress: false)
response.status_code.should eq 404
context.kemal_authorized_client?.should eq(client)
end

it "uses a custom handler and explicit hmac algo successfully" do
client = "valid-octo-client"
hmac_handler = SpecAuthHandler.new(
Expand Down
2 changes: 1 addition & 1 deletion src/kemal-hmac/client.cr
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module Kemal::Hmac
# :return: a Hash of the HMAC headers
def generate_headers(path : String) : Hash(String, String)
timestamp = Time::Format::ISO_8601_DATE_TIME.format(Time.utc)
hmac_token = Kemal::Hmac::Token.new(@client, path, timestamp, @algorithm).hexdigest(@secret)
hmac_token = Kemal::Hmac::Token.new(@client, path.split("?").first, timestamp, @algorithm).hexdigest(@secret)

return {
HMAC_CLIENT_HEADER => @client,
Expand Down

0 comments on commit a8b3a5c

Please sign in to comment.