Skip to content

Commit

Permalink
Merge pull request #602 from Mashape/hmac-username-fix
Browse files Browse the repository at this point in the history
hmac GH issues# 600 fix
  • Loading branch information
shashiranjan84 committed Oct 12, 2015
2 parents 7109c6a + dd4bfe7 commit 0d93be7
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 3 deletions.
8 changes: 6 additions & 2 deletions kong/plugins/hmac-auth/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ local ngx_parse_time = ngx.parse_http_time
local ngx_sha1 = ngx.hmac_sha1
local ngx_set_header = ngx.req.set_header
local ngx_set_headers = ngx.req.get_headers
local ngx_log = ngx.log

local split = stringy.split

Expand All @@ -28,13 +29,13 @@ local function retrieve_hmac_fields(request, headers, header_name, conf)
if authorization_header then
local iterator, iter_err = ngx_gmatch(authorization_header, "\\s*[Hh]mac\\s*username=\"(.+)\",\\s*algorithm=\"(.+)\",\\s*headers=\"(.+)\",\\s*signature=\"(.+)\"")
if not iterator then
ngx.log(ngx.ERR, iter_err)
ngx_log(ngx.ERR, iter_err)
return
end

local m, err = iterator()
if err then
ngx.log(ngx.ERR, err)
ngx_log(ngx.ERR, err)
return
end

Expand Down Expand Up @@ -151,6 +152,9 @@ function _M.execute(conf)

-- validate signature
local secret = load_secret(hmac_params.username)
if not secret then
responses.send_HTTP_FORBIDDEN(SIGNATURE_NOT_VALID)
end
hmac_params.secret = secret.secret
if not validate_signature(ngx.req, hmac_params, headers) then
ngx.ctx.stop_phases = true -- interrupt other phases of this request
Expand Down
92 changes: 91 additions & 1 deletion spec/plugins/hmac-auth/access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,97 @@ describe("Authentication Plugin", function()
it("should pass with GET with request-line", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bob", algorithm="hmac-sha1", headers="date content-md5 request-line",signature="]]..encodedSignature..[["]]
local hmacAuth = [["hmac username="bob", algorithm="hmac-sha1", headers="date content-md5 request-line", signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
assert.equal(200, status)
local parsed_response = cjson.decode(response)
assert.equal("hello", parsed_response.headers["authorization"])
end)

it("should not pass with GET with wrong username", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bobb", algorithm="hmac-sha1", headers="date content-md5 request-line", signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
local body = cjson.decode(response)
assert.equal(403, status)
assert.equal(SIGNATURE_NOT_VALID, body.message)
end)

it("should not pass with GET with username blank", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="", algorithm="hmac-sha1", headers="date content-md5 request-line", signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
local body = cjson.decode(response)
assert.equal(403, status)
assert.equal(SIGNATURE_NOT_VALID, body.message)
end)

it("should not pass with GET with username missing", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac algorithm="hmac-sha1", headers="date content-md5 request-line", signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
local body = cjson.decode(response)
assert.equal(403, status)
assert.equal(SIGNATURE_NOT_VALID, body.message)
end)

it("should not pass with GET with wrong hmac headers field name", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bob", algorithm="hmac-sha1", header="date content-md5 request-line", signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
local body = cjson.decode(response)
assert.equal(403, status)
assert.equal(SIGNATURE_NOT_VALID, body.message)
end)

it("should not pass with GET with wrong hmac signature field name", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bob", algorithm="hmac-sha1", headers="date content-md5 request-line", signatures="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
local body = cjson.decode(response)
assert.equal(403, status)
assert.equal(SIGNATURE_NOT_VALID, body.message)
end)

it("should not pass with GET with malformed hmac signature field", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bob", algorithm="hmac-sha1" headers="date content-md5 request-line",signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
local body = cjson.decode(response)
assert.equal(403, status)
assert.equal(SIGNATURE_NOT_VALID, body.message)
end)

it("should not pass with GET with malformed hmac headers field", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bob", algorithm="hmac-sha1" headers=" date content-md5 request-line",signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
local body = cjson.decode(response)
assert.equal(403, status)
assert.equal(SIGNATURE_NOT_VALID, body.message)
end)

it("should pass with GET with no space or space between hmac signatures fields", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha1", headers="date content-md5 request-line",signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
assert.equal(200, status)
local parsed_response = cjson.decode(response)
assert.equal("hello", parsed_response.headers["authorization"])
end)

it("should pass with GET with wrong algorithm", function()
local date = os.date("!%a, %d %b %Y %H:%M:%S GMT")
local encodedSignature = base64.encode(hmac_sha1_binary("secret", "date: "..date.."\n".."content-md5: md5".."\nGET /request? HTTP/1.1"))
local hmacAuth = [["hmac username="bob",algorithm="hmac-sha256", headers="date content-md5 request-line",signature="]]..encodedSignature..[["]]
local response, status = http_client.get(STUB_GET_URL, {}, {host = "hmacauth.com", date = date, ["proxy-authorization"] = hmacAuth, authorization = "hello", ["content-md5"] = "md5"})
assert.equal(200, status)
local parsed_response = cjson.decode(response)
Expand Down

0 comments on commit 0d93be7

Please sign in to comment.