Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(plugins): multiple auth fix in an OR scenario #2222

Merged
merged 5 commits into from
Apr 20, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions kong/plugins/basic-auth/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,15 @@ local function do_authentication(conf)
return true
end


function _M.execute(conf)

if ngx.ctx.authenticated_credential and conf.anonymous ~= "" then
-- we're already authenticated, and we're configured for using anonymous,
-- hence we're in a logical OR between auth methods and we're already done.
return
end

local ok, err = do_authentication(conf)
if not ok then
if conf.anonymous ~= "" then
Expand All @@ -164,4 +172,5 @@ function _M.execute(conf)
end
end


return _M
9 changes: 9 additions & 0 deletions kong/plugins/hmac-auth/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,15 @@ local function do_authentication(conf)
return true
end


function _M.execute(conf)

if ngx.ctx.authenticated_credential and conf.anonymous ~= "" then
-- we're already authenticated, and we're configured for using anonymous,
-- hence we're in a logical OR between auth methods and we're already done.
return
end

local ok, err = do_authentication(conf)
if not ok then
if conf.anonymous ~= "" then
Expand All @@ -230,4 +238,5 @@ function _M.execute(conf)
end
end


return _M
8 changes: 8 additions & 0 deletions kong/plugins/jwt/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,16 @@ local function do_authentication(conf)
return true
end


function JwtHandler:access(conf)
JwtHandler.super.access(self)

if ngx.ctx.authenticated_credential and conf.anonymous ~= "" then
-- we're already authenticated, and we're configured for using anonymous,
-- hence we're in a logical OR between auth methods and we're already done.
return
end

local ok, err = do_authentication(conf)
if not ok then
if conf.anonymous ~= "" then
Expand All @@ -187,4 +194,5 @@ function JwtHandler:access(conf)
end
end


return JwtHandler
8 changes: 8 additions & 0 deletions kong/plugins/key-auth/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,16 @@ local function do_authentication(conf)
return true
end


function KeyAuthHandler:access(conf)
KeyAuthHandler.super.access(self)

if ngx.ctx.authenticated_credential and conf.anonymous ~= "" then
-- we're already authenticated, and we're configured for using anonymous,
-- hence we're in a logical OR between auth methods and we're already done.
return
end

local ok, err = do_authentication(conf)
if not ok then
if conf.anonymous ~= "" then
Expand All @@ -144,4 +151,5 @@ function KeyAuthHandler:access(conf)
end
end


return KeyAuthHandler
31 changes: 24 additions & 7 deletions kong/plugins/ldap-auth/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,28 @@ local function load_consumer(consumer_id, anonymous)
end

local function set_consumer(consumer, credential)

if consumer then
-- this can only be the Anonymous user in this case
ngx_set_header(constants.HEADERS.CONSUMER_ID, consumer.id)
ngx_set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
ngx_set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
end
ngx.ctx.authenticated_consumer = consumer
if credential then
ngx_set_header(constants.HEADERS.CREDENTIAL_USERNAME, credential.username)
ngx.ctx.authenticated_credential = credential
ngx_set_header(constants.HEADERS.ANONYMOUS, nil) -- in case of auth plugins concatenation
else
ngx_set_header(constants.HEADERS.ANONYMOUS, true)
ngx.ctx.authenticated_consumer = consumer
return
end

-- here we have been authenticated by ldap
ngx_set_header(constants.HEADERS.CREDENTIAL_USERNAME, credential.username)
ngx.ctx.authenticated_credential = credential

-- in case of auth plugins concatenation, remove remnants of anonymous
ngx.ctx.authenticated_consumer = nil
ngx_set_header(constants.HEADERS.ANONYMOUS, nil)
ngx_set_header(constants.HEADERS.CONSUMER_ID, nil)
ngx_set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, nil)
ngx_set_header(constants.HEADERS.CONSUMER_USERNAME, nil)

end

local function do_authentication(conf)
Expand Down Expand Up @@ -148,7 +156,15 @@ local function do_authentication(conf)
return true
end


function _M.execute(conf)

if ngx.ctx.authenticated_credential and conf.anonymous ~= "" then
-- we're already authenticated, and we're configured for using anonymous,
-- hence we're in a logical OR between auth methods and we're already done.
return
end

local ok, err = do_authentication(conf)
if not ok then
if conf.anonymous ~= "" then
Expand All @@ -165,4 +181,5 @@ function _M.execute(conf)
end
end


return _M
11 changes: 11 additions & 0 deletions kong/plugins/oauth2/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,17 @@ local function do_authentication(conf)
return true
end


function _M.execute(conf)

if ngx.ctx.authenticated_credential and conf.anonymous ~= "" then
-- we're already authenticated, and we're configured for using anonymous,
-- hence we're in a logical OR between auth methods and we're already done.
return
end

if ngx.req.get_method() == "POST" then

local from, _, err = ngx.re.find(ngx.var.uri, [[\/oauth2\/token]], "oj")
if err then
ngx.log(ngx.ERR, "could not search for token path segment: ", err)
Expand Down Expand Up @@ -559,10 +568,12 @@ function _M.execute(conf)
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
end
set_consumer(consumer, nil, nil)

else
return responses.send(err.status, err.message, err.headers)
end
end
end


return _M
195 changes: 195 additions & 0 deletions spec/03-plugins/10-key-auth/02-access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,198 @@ describe("Plugin: key-auth (access)", function()
end)
end)
end)


describe("Plugin: key-auth (access)", function()

local client, user1, user2, anonymous

setup(function()
local api1 = assert(helpers.dao.apis:insert {
name = "api-1",
hosts = { "logical-and.com" },
upstream_url = "http://mockbin.org/request"
})
assert(helpers.dao.plugins:insert {
name = "basic-auth",
api_id = api1.id
})
assert(helpers.dao.plugins:insert {
name = "key-auth",
api_id = api1.id
})

anonymous = assert(helpers.dao.consumers:insert {
username = "Anonymous"
})
user1 = assert(helpers.dao.consumers:insert {
username = "Mickey"
})
user2 = assert(helpers.dao.consumers:insert {
username = "Aladdin"
})

local api2 = assert(helpers.dao.apis:insert {
name = "api-2",
hosts = { "logical-or.com" },
upstream_url = "http://mockbin.org/request"
})
assert(helpers.dao.plugins:insert {
name = "basic-auth",
api_id = api2.id,
config = {
anonymous = anonymous.id
}
})
assert(helpers.dao.plugins:insert {
name = "key-auth",
api_id = api2.id,
config = {
anonymous = anonymous.id
}
})

assert(helpers.dao.keyauth_credentials:insert {
key = "Mouse",
consumer_id = user1.id
})
assert(helpers.dao.basicauth_credentials:insert {
username = "Aladdin",
password = "OpenSesame",
consumer_id = user2.id
})

assert(helpers.start_kong())
client = helpers.proxy_client()
end)


teardown(function()
if client then client:close() end
helpers.stop_kong()
end)

describe("multiple auth without anonymous, logical AND", function()

it("passes with all credentials provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-and.com",
["apikey"] = "Mouse",
["Authorization"] = "Basic QWxhZGRpbjpPcGVuU2VzYW1l",
}
})
assert.response(res).has.status(200)
assert.request(res).has.no.header("x-anonymous-consumer")
local id = assert.request(res).has.header("x-consumer-id")
assert.not_equal(id, anonymous.id)
assert(id == user1.id or id == user2.id)
end)

it("fails 401, with only the first credential provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-and.com",
["apikey"] = "Mouse",
}
})
assert.response(res).has.status(401)
end)

it("fails 401, with only the second credential provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-and.com",
["Authorization"] = "Basic QWxhZGRpbjpPcGVuU2VzYW1l",
}
})
assert.response(res).has.status(401)
end)

it("fails 401, with no credential provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-and.com",
}
})
assert.response(res).has.status(401)
end)

end)

describe("multiple auth with anonymous, logical OR", function()

it("passes with all credentials provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-or.com",
["apikey"] = "Mouse",
["Authorization"] = "Basic QWxhZGRpbjpPcGVuU2VzYW1l",
}
})
assert.response(res).has.status(200)
assert.request(res).has.no.header("x-anonymous-consumer")
local id = assert.request(res).has.header("x-consumer-id")
assert.not_equal(id, anonymous.id)
assert(id == user1.id or id == user2.id)
end)

it("passes with only the first credential provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-or.com",
["apikey"] = "Mouse",
}
})
assert.response(res).has.status(200)
assert.request(res).has.no.header("x-anonymous-consumer")
local id = assert.request(res).has.header("x-consumer-id")
assert.not_equal(id, anonymous.id)
assert.equal(user1.id, id)
end)

it("passes with only the second credential provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-or.com",
["Authorization"] = "Basic QWxhZGRpbjpPcGVuU2VzYW1l",
}
})
assert.response(res).has.status(200)
assert.request(res).has.no.header("x-anonymous-consumer")
local id = assert.request(res).has.header("x-consumer-id")
assert.not_equal(id, anonymous.id)
assert.equal(user2.id, id)
end)

it("passes with no credential provided", function()
local res = assert(client:send {
method = "GET",
path = "/request",
headers = {
["Host"] = "logical-or.com",
}
})
assert.response(res).has.status(200)
assert.request(res).has.header("x-anonymous-consumer")
local id = assert.request(res).has.header("x-consumer-id")
assert.equal(id, anonymous.id)
end)

end)

end)
Loading