From b42ac0678b2c04ff33a2e1a7b7edb6874077d94f Mon Sep 17 00:00:00 2001 From: Karol Wypchlo Date: Mon, 21 Mar 2022 14:23:26 +0100 Subject: [PATCH] clean up cookie extraction --- docker/nginx/libs/skynet/account.lua | 10 ++-- docker/nginx/libs/utils.lua | 28 ++++++++++++ docker/nginx/libs/utils.spec.lua | 68 ++++++++++++++++++++++++++++ docker/nginx/nginx.conf | 7 --- 4 files changed, 103 insertions(+), 10 deletions(-) diff --git a/docker/nginx/libs/skynet/account.lua b/docker/nginx/libs/skynet/account.lua index d31ec57e..8003c60e 100644 --- a/docker/nginx/libs/skynet/account.lua +++ b/docker/nginx/libs/skynet/account.lua @@ -17,12 +17,16 @@ local anon_limits = { -- get all non empty authentication headers from request, we want to return -- all of them and let accounts service deal with validation and prioritisation function _M.get_auth_headers() + local utils = require("utils") local request_headers = ngx.req.get_headers() local headers = {} - -- if skynet_jwt is set, include it as a cookie - if ngx.var.skynet_jwt ~= "" then - headers["Cookie"] = "skynet-jwt=" .. ngx.var.skynet_jwt + -- try to extract skynet-jwt cookie from cookie header + local skynet_jwt_cookie = utils.extract_cookie(request_headers["Cookie"], "skynet[-]jwt") + + -- if skynet-jwt cookie is present, pass it as is + if skynet_jwt_cookie then + headers["Cookie"] = skynet_jwt_cookie end -- if authorization header is set, pass it as is diff --git a/docker/nginx/libs/utils.lua b/docker/nginx/libs/utils.lua index 83faf09b..6b392c99 100644 --- a/docker/nginx/libs/utils.lua +++ b/docker/nginx/libs/utils.lua @@ -9,4 +9,32 @@ function _M.is_table_empty(check) return next(check) == nil end +-- extract full cookie name and value by its name from cookie string +-- note: name matcher argument is a pattern so you will need to escape +-- any special characters, read more https://www.lua.org/pil/20.2.html +function _M.extract_cookie(cookie_string, name_matcher) + if cookie_string == nil then return nil end -- nil safeguard + + local start, stop = string.find(cookie_string, name_matcher .. "=[^;]+") + + if start then + return string.sub(cookie_string, start, stop) + end + + return nil +end + +-- extract just the cookie value by its name from cookie string +-- note: name matcher argument is a pattern so you will need to escape +-- any special characters, read more https://www.lua.org/pil/20.2.html +function _M.extract_cookie_value(cookie_string, name_matcher) + local cookie = _M.extract_cookie(cookie_string, name_matcher) + + if cookie == nil then return nil end + + local value_start = string.find(cookie, "=") + 1 + + return string.sub(cookie, value_start) +end + return _M diff --git a/docker/nginx/libs/utils.spec.lua b/docker/nginx/libs/utils.spec.lua index 6299d010..8dd68e6e 100644 --- a/docker/nginx/libs/utils.spec.lua +++ b/docker/nginx/libs/utils.spec.lua @@ -9,3 +9,71 @@ describe("is_table_empty", function() assert.is_false(utils.is_table_empty({ ["foo"] = "bar" })) end) end) + +describe("extract_cookie", function() + local cookie_string = "aaa=bbb; skynet-jwt=MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==; xxx=yyy" + + it("should return nil if cookie string is nil", function() + local cookie = utils.extract_cookie_value(nil, "aaa") + + assert.is_nil(cookie) + end) + + it("should return nil if cookie name is not found", function() + local cookie = utils.extract_cookie(cookie_string, "foo") + + assert.is_nil(cookie) + end) + + it("should return cookie if cookie_string starts with that cookie name", function() + local cookie = utils.extract_cookie(cookie_string, "aaa") + + assert.are.equals(cookie, "aaa=bbb") + end) + + it("should return cookie if cookie_string ends with that cookie name", function() + local cookie = utils.extract_cookie(cookie_string, "xxx") + + assert.are.equals(cookie, "xxx=yyy") + end) + + it("should return cookie with custom matcher", function() + local cookie = utils.extract_cookie(cookie_string, "skynet[-]jwt") + + assert.are.equals(cookie, "skynet-jwt=MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==") + end) +end) + +describe("extract_cookie_value", function() + local cookie_string = "aaa=bbb; skynet-jwt=MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==; xxx=yyy" + + it("should return nil if cookie string is nil", function() + local value = utils.extract_cookie_value(nil, "aaa") + + assert.is_nil(value) + end) + + it("should return nil if cookie name is not found", function() + local value = utils.extract_cookie_value(cookie_string, "foo") + + assert.is_nil(value) + end) + + it("should return value if cookie_string starts with that cookie name", function() + local value = utils.extract_cookie_value(cookie_string, "aaa") + + assert.are.equals(value, "bbb") + end) + + it("should return cookie if cookie_string ends with that cookie name", function() + local value = utils.extract_cookie_value(cookie_string, "xxx") + + assert.are.equals(value, "yyy") + end) + + it("should return cookie with custom matcher", function() + local value = utils.extract_cookie_value(cookie_string, "skynet[-]jwt") + + assert.are.equals(value, "MTY0NzUyr8jD-ytiWtspm0tGabKfooxeIDuWcXhJ3lnY0eEw==") + end) +end) diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf index 95bb61ac..3517a6bc 100644 --- a/docker/nginx/nginx.conf +++ b/docker/nginx/nginx.conf @@ -117,13 +117,6 @@ http { proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; - # skynet-jwt contains dash so we cannot use $cookie_skynet-jwt - # https://richardhart.me/2012/03/18/logging-nginx-cookies-with-dashes/ - map $http_cookie $skynet_jwt { - default ''; - ~skynet-jwt=(?[^\;]+) $match; - } - include /etc/nginx/conf.d/*.conf; include /etc/nginx/conf.extra.d/*.conf; }