Skip to content

Commit

Permalink
Closes #448
Browse files Browse the repository at this point in the history
  • Loading branch information
subnetmarco committed Aug 7, 2015
1 parent 8a4b222 commit f48a924
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 2 deletions.
21 changes: 20 additions & 1 deletion kong/plugins/oauth2/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ local GRANT_TYPE = "grant_type"
local GRANT_AUTHORIZATION_CODE = "authorization_code"
local GRANT_CLIENT_CREDENTIALS = "client_credentials"
local GRANT_REFRESH_TOKEN = "refresh_token"
local GRANT_PASSWORD = "password"
local ERROR = "error"
local AUTHENTICATED_USERID = "authenticated_userid"

Expand Down Expand Up @@ -205,7 +206,10 @@ local function issue_token(conf)
local state = parameters[STATE]

local grant_type = parameters[GRANT_TYPE]
if not (grant_type == GRANT_AUTHORIZATION_CODE or grant_type == GRANT_REFRESH_TOKEN or (conf.enable_client_credentials and grant_type == GRANT_CLIENT_CREDENTIALS)) then
if not (grant_type == GRANT_AUTHORIZATION_CODE or
grant_type == GRANT_REFRESH_TOKEN or
(conf.enable_client_credentials and grant_type == GRANT_CLIENT_CREDENTIALS) or
(conf.enable_password_grant and grant_type == GRANT_PASSWORD)) then
response_params = {[ERROR] = "invalid_request", error_description = "Invalid "..GRANT_TYPE}
end

Expand Down Expand Up @@ -240,6 +244,21 @@ local function issue_token(conf)
else
response_params = generate_token(conf, client, nil, table.concat(scopes, " "), state)
end
elseif grant_type == GRANT_PASSWORD then
-- Check that it comes from the right client
if conf.provision_key ~= parameters.provision_key then
response_params = {[ERROR] = "invalid_provision_key", error_description = "Invalid Kong provision_key"}
elseif not parameters.authenticated_userid or stringy.strip(parameters.authenticated_userid) == "" then
response_params = {[ERROR] = "invalid_authenticated_userid", error_description = "Missing authenticated_userid parameter"}
else
-- Check scopes
local ok, scopes = retrieve_scopes(parameters, conf)
if not ok then
response_params = scopes -- If it's not ok, then this is the error message
else
response_params = generate_token(conf, client, nil, table.concat(scopes, " "), state)
end
end
elseif grant_type == GRANT_REFRESH_TOKEN then
local refresh_token = parameters[REFRESH_TOKEN]
local token = refresh_token and dao.oauth2_tokens:find_by_keys({refresh_token = refresh_token})[1] or nil
Expand Down
1 change: 1 addition & 0 deletions kong/plugins/oauth2/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ return {
enable_authorization_code = { required = true, type = "boolean", default = true },
enable_implicit_grant = { required = true, type = "boolean", default = false },
enable_client_credentials = { required = true, type = "boolean", default = false },
enable_password_grant = { required = true, type = "boolean", default = false },
hide_credentials = { type = "boolean", default = false }
}
}
2 changes: 1 addition & 1 deletion spec/integration/proxy/api_resolver_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ describe("Resolver", function()
it("should return the correct Server and Via headers when the request was proxied", function()
local _, status, headers = http_client.get(STUB_GET_URL, nil, { host = "mockbin.com"})
assert.equal(200, status)
assert.equal("cloudflare-nginx", headers.server)
assert.equal("Cowboy", headers.server)
assert.equal(constants.NAME.."/"..constants.VERSION, headers.via)
end)

Expand Down
82 changes: 82 additions & 0 deletions spec/plugins/oauth2/access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe("Authentication Plugin", function()
{ name = "tests oauth2 with path", public_dns = "mockbin-path.com", target_url = "http://mockbin.com", path = "/somepath/" },
{ name = "tests oauth2 with hide credentials", public_dns = "oauth2_3.com", target_url = "http://mockbin.com" },
{ name = "tests oauth2 client credentials", public_dns = "oauth2_4.com", target_url = "http://mockbin.com" },
{ name = "tests oauth2 password grant", public_dns = "oauth2_5.com", target_url = "http://mockbin.com" }
},
consumer = {
{ username = "auth_tests_consumer" }
Expand All @@ -52,6 +53,7 @@ describe("Authentication Plugin", function()
{ name = "oauth2", value = { scopes = { "email", "profile" }, mandatory_scope = true, provision_key = "provision123", token_expiration = 5, enable_implicit_grant = true }, __api = 2 },
{ name = "oauth2", value = { scopes = { "email", "profile" }, mandatory_scope = true, provision_key = "provision123", token_expiration = 5, enable_implicit_grant = true, hide_credentials = true }, __api = 3 },
{ name = "oauth2", value = { scopes = { "email", "profile" }, mandatory_scope = true, provision_key = "provision123", token_expiration = 5, enable_client_credentials = true, enable_authorization_code = false }, __api = 4 },
{ name = "oauth2", value = { scopes = { "email", "profile" }, mandatory_scope = true, provision_key = "provision123", token_expiration = 5, enable_password_grant = true, enable_authorization_code = false }, __api = 5 }
},
oauth2_credential = {
{ client_id = "clientid123", client_secret = "secret123", redirect_uri = "http://google.com/kong", name="testapp", __consumer = 1 }
Expand Down Expand Up @@ -307,6 +309,86 @@ describe("Authentication Plugin", function()
end)

end)

describe("Password Grant", function()

it("should return an error when client_secret is not sent", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { client_id = "clientid123", scope = "email", response_type = "token" }, {host = "oauth2_5.com"})
local body = cjson.decode(response)
assert.are.equal(400, status)
assert.are.equal(2, utils.table_size(body))
assert.are.equal("invalid_request", body.error)
assert.are.equal("Invalid client_secret", body.error_description)
end)

it("should return an error when client_secret is not sent", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { client_id = "clientid123", client_secret="secret123", scope = "email", response_type = "token" }, {host = "oauth2_5.com"})
local body = cjson.decode(response)
assert.are.equal(400, status)
assert.are.equal(2, utils.table_size(body))
assert.are.equal("invalid_request", body.error)
assert.are.equal("Invalid grant_type", body.error_description)
end)

it("should fail when no provision key is being sent", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { client_id = "clientid123", client_secret="secret123", scope = "email", grant_type = "password" }, {host = "oauth2_5.com"})
local body = cjson.decode(response)
assert.are.equal(400, status)
assert.are.equal(2, utils.table_size(body))
assert.are.equal("invalid_provision_key", body.error)
assert.are.equal("Invalid Kong provision_key", body.error_description)
end)

it("should fail when no provision key is being sent", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { client_id = "clientid123", client_secret="secret123", scope = "email", grant_type = "password" }, {host = "oauth2_5.com"})
local body = cjson.decode(response)
assert.are.equal(400, status)
assert.are.equal(2, utils.table_size(body))
assert.are.equal("invalid_provision_key", body.error)
assert.are.equal("Invalid Kong provision_key", body.error_description)
end)

it("should fail when no authenticated user id is being sent", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { provision_key = "provision123", client_id = "clientid123", client_secret="secret123", scope = "email", grant_type = "password" }, {host = "oauth2_5.com"})
local body = cjson.decode(response)
assert.are.equal(400, status)
assert.are.equal(2, utils.table_size(body))
assert.are.equal("invalid_authenticated_userid", body.error)
assert.are.equal("Missing authenticated_userid parameter", body.error_description)
end)

it("should return success", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { provision_key = "provision123", authenticated_userid = "id123", client_id = "clientid123", client_secret="secret123", scope = "email", grant_type = "password" }, {host = "oauth2_5.com"})
local body = cjson.decode(response)
assert.are.equal(200, status)
assert.are.equals(4, utils.table_size(body))
assert.truthy(body.refresh_token)
assert.truthy(body.access_token)
assert.are.equal("bearer", body.token_type)
assert.are.equal(5, body.expires_in)
end)

it("should return success with authorization header", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { provision_key = "provision123", authenticated_userid = "id123", scope = "email", grant_type = "password" }, {host = "oauth2_5.com", authorization = "Basic Y2xpZW50aWQxMjM6c2VjcmV0MTIz"})
local body = cjson.decode(response)
assert.are.equal(200, status)
assert.are.equals(4, utils.table_size(body))
assert.truthy(body.refresh_token)
assert.truthy(body.access_token)
assert.are.equal("bearer", body.token_type)
assert.are.equal(5, body.expires_in)
end)

it("should return an error with a wrong authorization header", function()
local response, status = http_client.post(PROXY_URL.."/oauth2/token", { provision_key = "provision123", authenticated_userid = "id123", scope = "email", grant_type = "password" }, {host = "oauth2_5.com", authorization = "Basic Y2xpZW50aWQxMjM6c2VjcmV0MTI0"})
local body = cjson.decode(response)
assert.are.equal(400, status)
assert.are.equal(2, utils.table_size(body))
assert.are.equal("invalid_request", body.error)
assert.are.equal("Invalid client_secret", body.error_description)
end)

end)
end)

describe("OAuth2 Access Token", function()
Expand Down

0 comments on commit f48a924

Please sign in to comment.