Skip to content

Commit 0709abf

Browse files
emojemoj
authored andcommitted
updating to allow multi-authentication and working against kong 1.X+
1 parent f0c573c commit 0709abf

File tree

3 files changed

+113
-64
lines changed

3 files changed

+113
-64
lines changed

.github/ ISSUE_TEMPLATE.md

Lines changed: 0 additions & 9 deletions
This file was deleted.

kong/plugins/oidc/handler.lua

Lines changed: 75 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,63 @@ local utils = require("kong.plugins.oidc.utils")
44
local filter = require("kong.plugins.oidc.filter")
55
local session = require("kong.plugins.oidc.session")
66

7-
local singletons = require "kong.singletons"
87
local constants = require "kong.constants"
9-
local responses = require "kong.tools.responses"
108

11-
OidcHandler.PRIORITY = 1000
9+
local kong = kong
1210

11+
OidcHandler.PRIORITY = 1002
12+
13+
local function internal_server_error(err)
14+
kong.log.err(err)
15+
return kong.response.exit(500, { message = "An unexpected error occurred" })
16+
end
17+
18+
local function set_consumer(consumer, credential, token)
19+
local set_header = kong.service.request.set_header
20+
local clear_header = kong.service.request.clear_header
21+
22+
if consumer and consumer.id then
23+
set_header(constants.HEADERS.CONSUMER_ID, consumer.id)
24+
else
25+
clear_header(constants.HEADERS.CONSUMER_ID)
26+
end
27+
28+
if consumer and consumer.custom_id then
29+
set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
30+
else
31+
clear_header(constants.HEADERS.CONSUMER_CUSTOM_ID)
32+
end
33+
34+
if consumer and consumer.username then
35+
set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
36+
else
37+
clear_header(constants.HEADERS.CONSUMER_USERNAME)
38+
end
39+
40+
kong.client.authenticate(consumer, credential)
41+
42+
if credential then
43+
if token.scope then
44+
set_header("x-authenticated-scope", token.scope)
45+
else
46+
clear_header("x-authenticated-scope")
47+
end
48+
49+
if token.authenticated_userid then
50+
set_header("x-authenticated-userid", token.authenticated_userid)
51+
else
52+
clear_header("x-authenticated-userid")
53+
end
54+
55+
clear_header(constants.HEADERS.ANONYMOUS) -- in case of auth plugins concatenation
56+
57+
else
58+
set_header(constants.HEADERS.ANONYMOUS, true)
59+
clear_header("x-authenticated-scope")
60+
clear_header("x-authenticated-userid")
61+
end
62+
63+
end
1364

1465
function OidcHandler:new()
1566
OidcHandler.super.new(self, "oidc")
@@ -18,7 +69,7 @@ end
1869
function OidcHandler:access(config)
1970
OidcHandler.super.access(self)
2071

21-
if ngx.ctx.authenticated_credential and config.anonymous ~= "" then
72+
if config.anonymous and kong.client.get_credential() then
2273
-- we're already authenticated, and we're configured for using anonymous,
2374
-- hence we're in a logical OR between auth methods and we're already done.
2475
return
@@ -49,6 +100,10 @@ function handle(oidcConfig)
49100
response = make_oidc(oidcConfig)
50101
if response then
51102
if (response.user) then
103+
local tmp_user = response.user
104+
tmp_user.id = response.user.sub
105+
tmp_user.username = response.user.preferred_username
106+
set_consumer(tmp_user, nil, nil)
52107
utils.injectUser(response.user)
53108
end
54109
if (response.access_token) then
@@ -69,19 +124,20 @@ function make_oidc(oidcConfig)
69124
ngx.log(ngx.DEBUG, "Entering recovery page: " .. oidcConfig.recovery_page_path)
70125
ngx.redirect(oidcConfig.recovery_page_path)
71126
end
72-
if oidcConfig.anonymous ~= "" then
127+
if oidcConfig.anonymous then
73128
-- get anonymous user
74-
local consumer_cache_key = singletons.db.consumers:cache_key(oidcConfig.anonymous)
75-
local consumer, err = singletons.cache:get(consumer_cache_key, nil,
76-
load_consumer_into_memory,
77-
oidcConfig.anonymous, true)
129+
local consumer_cache_key = kong.db.consumers:cache_key(oidcConfig.anonymous)
130+
local consumer, err = kong.cache:get(consumer_cache_key, nil,
131+
load_consumer_into_memory,
132+
oidcConfig.anonymous, true)
78133
if err then
79-
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
134+
return internal_server_error(err)
80135
end
136+
81137
set_consumer(consumer, nil, nil)
82138

83139
else
84-
utils.exit(500, err, ngx.HTTP_INTERNAL_SERVER_ERROR)
140+
return kong.response.exit(err.status, err.message, err.headers)
85141
end
86142
end
87143
return res
@@ -93,19 +149,20 @@ function introspect(oidcConfig)
93149
if err then
94150
if oidcConfig.bearer_only == "yes" then
95151
ngx.header["WWW-Authenticate"] = 'Bearer realm="' .. oidcConfig.realm .. '",error="' .. err .. '"'
96-
if oidcConfig.anonymous ~= "" then
152+
if oidcConfig.anonymous then
97153
-- get anonymous user
98-
local consumer_cache_key = singletons.db.consumers:cache_key(oidcConfig.anonymous)
99-
local consumer, err = singletons.cache:get(consumer_cache_key, nil,
100-
load_consumer_into_memory,
101-
oidcConfig.anonymous, true)
154+
local consumer_cache_key = kong.db.consumers:cache_key(oidcConfig.anonymous)
155+
local consumer, err = kong.cache:get(consumer_cache_key, nil,
156+
load_consumer_into_memory,
157+
oidcConfig.anonymous, true)
102158
if err then
103-
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
159+
return internal_server_error(err)
104160
end
161+
105162
set_consumer(consumer, nil, nil)
106163

107164
else
108-
utils.exit(ngx.HTTP_UNAUTHORIZED, err, ngx.HTTP_UNAUTHORIZED)
165+
return kong.response.exit(err.status, err.message, err.headers)
109166
end
110167

111168
end
@@ -119,21 +176,5 @@ end
119176

120177
-- TESTING
121178

122-
local function set_consumer(consumer, credential, token)
123-
ngx_set_header(constants.HEADERS.CONSUMER_ID, consumer.id)
124-
ngx_set_header(constants.HEADERS.CONSUMER_CUSTOM_ID, consumer.custom_id)
125-
ngx_set_header(constants.HEADERS.CONSUMER_USERNAME, consumer.username)
126-
ngx.ctx.authenticated_consumer = consumer
127-
if credential then
128-
ngx_set_header("x-authenticated-scope", token.scope)
129-
ngx_set_header("x-authenticated-userid", token.authenticated_userid)
130-
ngx.ctx.authenticated_credential = credential
131-
ngx_set_header(constants.HEADERS.ANONYMOUS, nil) -- in case of auth plugins concatenation
132-
else
133-
ngx_set_header(constants.HEADERS.ANONYMOUS, true)
134-
end
135-
136-
end
137-
138179

139180
return OidcHandler

kong/plugins/oidc/schema.lua

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,41 @@
1+
local typedefs = require "kong.db.schema.typedefs"
2+
3+
local function validate_flows(config)
4+
5+
return true
6+
7+
end
8+
19
return {
2-
no_consumer = true,
10+
name = "oidc",
311
fields = {
4-
anonymous = { type = "string", uuid = true, legacy = true },
5-
client_id = { type = "string", required = true },
6-
client_secret = { type = "string", required = true },
7-
discovery = { type = "string", required = true, default = "https://.well-known/openid-configuration" },
8-
introspection_endpoint = { type = "string", required = false },
9-
timeout = { type = "number", required = false },
10-
introspection_endpoint_auth_method = { type = "string", required = false },
11-
bearer_only = { type = "string", required = true, default = "no" },
12-
realm = { type = "string", required = true, default = "kong" },
13-
redirect_uri_path = { type = "string" },
14-
scope = { type = "string", required = true, default = "openid" },
15-
response_type = { type = "string", required = true, default = "code" },
16-
ssl_verify = { type = "string", required = true, default = "no" },
17-
token_endpoint_auth_method = { type = "string", required = true, default = "client_secret_post" },
18-
session_secret = { type = "string", required = false },
19-
recovery_page_path = { type = "string" },
20-
logout_path = { type = "string", required = false, default = '/logout' },
21-
redirect_after_logout_uri = { type = "string", required = false, default = '/' },
22-
filters = { type = "string" }
23-
}
12+
{ consumer = typedefs.no_consumer },
13+
{ config = {
14+
type = "record",
15+
fields = {
16+
{ anonymous = { type = "string", uuid = true, legacy = true }, },
17+
{client_id = { type = "string", required = true, default = "konglocal" }},
18+
{client_secret = { type = "string", required = true, default = "kongapigateway" }},
19+
{discovery = { type = "string", required = true, default = "https://cas.example.org:8453/cas/oidc/.well-known/openid-configuration" }},
20+
{introspection_endpoint = { type = "string", required = false }},
21+
{timeout = { type = "number", required = false }},
22+
{introspection_endpoint_auth_method = { type = "string", required = false }},
23+
{bearer_only = { type = "string", required = true, default = "no" }},
24+
{realm = { type = "string", required = true, default = "kong" }},
25+
{redirect_uri_path = { type = "string" }},
26+
{inject_base_path = { type = "string" }},
27+
{scope = { type = "string", required = true, default = "openid" }},
28+
{response_type = { type = "string", required = true, default = "code" }},
29+
{ssl_verify = { type = "string", required = true, default = "no" }},
30+
{token_endpoint_auth_method = { type = "string", required = true, default = "client_secret_post" }},
31+
{session_secret = { type = "string", required = false }},
32+
{recovery_page_path = { type = "string" }},
33+
{logout_path = { type = "string", required = false, default = '/logout' }},
34+
{redirect_after_logout_uri = { type = "string", required = false, default = '/' }},
35+
{filters = { type = "string" }}
36+
},
37+
custom_validator = validate_flows,
38+
},
39+
},
40+
},
2441
}

0 commit comments

Comments
 (0)