Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
31 changes: 16 additions & 15 deletions apisix/plugins/openid-connect.lua
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ local function get_bearer_access_token(ctx)
local auth_header = core.request.header(ctx, "Authorization")
if not auth_header then
-- No Authorization header, get X-Access-Token header, maybe.
local access_token_header = core.request.header(ctx, "X-Access-Token")
local access_token_header = ctx.openid_connect_client_x_access_token
if not access_token_header then
-- No X-Access-Token header neither.
return false, nil, nil
Expand Down Expand Up @@ -573,20 +573,11 @@ end


local function add_access_token_header(ctx, conf, token)
if token then
-- Add Authorization or X-Access-Token header, respectively, if not already set.
if conf.set_access_token_header then
if conf.access_token_in_authorization_header then
if not core.request.header(ctx, "Authorization") then
-- Add Authorization header.
core.request.set_header(ctx, "Authorization", "Bearer " .. token)
end
else
if not core.request.header(ctx, "X-Access-Token") then
-- Add X-Access-Token header.
core.request.set_header(ctx, "X-Access-Token", token)
end
end
if token and conf.set_access_token_header then
if conf.access_token_in_authorization_header then
core.request.set_header(ctx, "Authorization", "Bearer " .. token)
else
core.request.set_header(ctx, "X-Access-Token", token)
end
end
end
Expand Down Expand Up @@ -626,6 +617,16 @@ end
function _M.rewrite(plugin_conf, ctx)
local conf = core.table.clone(plugin_conf)

-- Snapshot the client-supplied X-Access-Token (it doubles as a bearer
-- input via get_bearer_access_token) and clear the four headers this
-- plugin advertises as outputs so client-supplied values cannot bleed
-- through to the upstream.
ctx.openid_connect_client_x_access_token = core.request.header(ctx, "X-Access-Token")
core.request.set_header(ctx, "X-Access-Token", nil)
core.request.set_header(ctx, "X-Userinfo", nil)
core.request.set_header(ctx, "X-ID-Token", nil)
core.request.set_header(ctx, "X-Refresh-Token", nil)

-- Previously, we multiply conf.timeout before storing it in etcd.
-- If the timeout is too large, we should not multiply it again.
if not (conf.timeout >= 1000 and conf.timeout % 1000 == 0) then
Expand Down
168 changes: 168 additions & 0 deletions t/plugin/openid-connect-identity-headers.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
use t::APISIX 'no_plan';

repeat_each(1);
no_long_string();
no_root_location();

add_block_preprocessor(sub {
my ($block) = @_;

if ((!defined $block->error_log) && (!defined $block->no_error_log)) {
$block->set_value("no_error_log", "[error]");
}

if (!defined $block->request) {
$block->set_value("request", "GET /t");
}
});

run_tests();

__DATA__

=== TEST 1: Set up route with unauth_action = "pass" so unauthenticated requests pass through.
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"openid-connect": {
"client_id": "kbyuFDidLLm280LIwVFiazOqjO3ty8KH",
"client_secret": "60Op4HFM0I8ajz0WdiStAbziZ-VFQttXuxixHHs2R7r7-CW8GR79l-mmLqMhc-Sa",
"discovery": "https://samples.auth0.com/.well-known/openid-configuration",
"redirect_uri": "https://iresty.com",
"ssl_verify": false,
"timeout": 10,
"scope": "apisix",
"unauth_action": "pass",
"use_pkce": false,
"session": {
"secret": "jwcE5v3pM9VhqLxmxFOH9uZaLo8u7KQK"
}
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/uri"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed



=== TEST 2: Access route without authentication. Client-supplied X-Userinfo / X-ID-Token / X-Refresh-Token / X-Access-Token must not reach upstream.
--- request
GET /uri HTTP/1.1
--- more_headers
X-Userinfo: client-supplied-userinfo
X-ID-Token: client-supplied-id-token
X-Refresh-Token: client-supplied-refresh-token
X-Access-Token: client-supplied-access-token
--- response_body
uri: /uri
host: localhost
x-real-ip: 127.0.0.1
--- error_code: 200



=== TEST 3: Update route to bearer_only with embedded RS256 public key.
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{ "plugins": {
"openid-connect": {
"client_id": "kbyuFDidLLm280LIwVFiazOqjO3ty8KH",
"client_secret": "60Op4HFM0I8ajz0WdiStAbziZ-VFQttXuxixHHs2R7r7-CW8GR79l-mmLqMhc-Sa",
"discovery": "https://samples.auth0.com/.well-known/openid-configuration",
"redirect_uri": "https://iresty.com",
"ssl_verify": false,
"timeout": 10,
"bearer_only": true,
"scope": "apisix",
"public_key": "-----BEGIN PUBLIC KEY-----\n]] ..
[[MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw86xcJwNxL2MkWnjIGiw\n]] ..
[[94QY78Sq89dLqMdV/Ku2GIX9lYkbS0VDGtmxDGJLBOYW4cKTX+pigJyzglLgE+nD\n]] ..
[[z3VJf2oCqSV74gTyEdi7sw9e1rCyR6dR8VA7LEpIHwmhnDhhjXy1IYSKRdiVHLS5\n]] ..
[[sYmaAGckpUo3MLqUrgydGj5tFzvK/R/ELuZBdlZM+XuWxYry05r860E3uL+VdVCO\n]] ..
[[oU4RJQknlJnTRd7ht8KKcZb6uM14C057i26zX/xnOJpaVflA4EyEo99hKQAdr8Sh\n]] ..
[[G70MOLYvGCZxl1o8S3q4X67MxcPlfJaXnbog2AOOGRaFar88XiLFWTbXMCLuz7xD\n]] ..
[[zQIDAQAB\n]] ..
[[-----END PUBLIC KEY-----",
"token_signing_alg_values_expected": "RS256",
"set_id_token_header": false,
"set_userinfo_header": false,
"claim_validator": {
"issuer": {
"valid_issuers": ["Mysoft corp"]
}
}
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/uri"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- response_body
passed



=== TEST 4: Access route with valid bearer token and a client-supplied X-Access-Token. Upstream must see the validated token, not the client value.
--- request
GET /uri HTTP/1.1
--- more_headers
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhMSI6IkRhdGEgMSIsImlhdCI6MTU4NTEyMjUwMiwiZXhwIjoxOTAwNjk4NTAyLCJhdWQiOiJodHRwOi8vbXlzb2Z0Y29ycC5pbiIsImlzcyI6Ik15c29mdCBjb3JwIiwic3ViIjoic29tZUB1c2VyLmNvbSJ9.Vq_sBN7nH67vMDbiJE01EP4hvJYE_5ju6izjkOX8pF5OS4g2RWKWpL6h6-b0tTkCzG4JD5BEl13LWW-Gxxw0i9vEK0FLg_kC_kZLYB8WuQ6B9B9YwzmZ3OLbgnYzt_VD7D-7psEbwapJl5hbFsIjDgOAEx-UCmjUcl2frZxZavG2LUiEGs9Ri7KqOZmTLgNDMWfeWh1t1LyD0_b-eTInbasVtKQxMlb5kR0Ln_Qg5092L-irJ7dqaZma7HItCnzXJROdqJEsMIBAYRwDGa_w5kIACeMOdU85QKtMHzOenYFkm6zh_s59ndziTctKMz196Y8AL08xuTi6d1gEWpM92A
X-Access-Token: client-supplied-access-token
--- response_body
uri: /uri
authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhMSI6IkRhdGEgMSIsImlhdCI6MTU4NTEyMjUwMiwiZXhwIjoxOTAwNjk4NTAyLCJhdWQiOiJodHRwOi8vbXlzb2Z0Y29ycC5pbiIsImlzcyI6Ik15c29mdCBjb3JwIiwic3ViIjoic29tZUB1c2VyLmNvbSJ9.Vq_sBN7nH67vMDbiJE01EP4hvJYE_5ju6izjkOX8pF5OS4g2RWKWpL6h6-b0tTkCzG4JD5BEl13LWW-Gxxw0i9vEK0FLg_kC_kZLYB8WuQ6B9B9YwzmZ3OLbgnYzt_VD7D-7psEbwapJl5hbFsIjDgOAEx-UCmjUcl2frZxZavG2LUiEGs9Ri7KqOZmTLgNDMWfeWh1t1LyD0_b-eTInbasVtKQxMlb5kR0Ln_Qg5092L-irJ7dqaZma7HItCnzXJROdqJEsMIBAYRwDGa_w5kIACeMOdU85QKtMHzOenYFkm6zh_s59ndziTctKMz196Y8AL08xuTi6d1gEWpM92A
host: localhost
x-access-token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhMSI6IkRhdGEgMSIsImlhdCI6MTU4NTEyMjUwMiwiZXhwIjoxOTAwNjk4NTAyLCJhdWQiOiJodHRwOi8vbXlzb2Z0Y29ycC5pbiIsImlzcyI6Ik15c29mdCBjb3JwIiwic3ViIjoic29tZUB1c2VyLmNvbSJ9.Vq_sBN7nH67vMDbiJE01EP4hvJYE_5ju6izjkOX8pF5OS4g2RWKWpL6h6-b0tTkCzG4JD5BEl13LWW-Gxxw0i9vEK0FLg_kC_kZLYB8WuQ6B9B9YwzmZ3OLbgnYzt_VD7D-7psEbwapJl5hbFsIjDgOAEx-UCmjUcl2frZxZavG2LUiEGs9Ri7KqOZmTLgNDMWfeWh1t1LyD0_b-eTInbasVtKQxMlb5kR0Ln_Qg5092L-irJ7dqaZma7HItCnzXJROdqJEsMIBAYRwDGa_w5kIACeMOdU85QKtMHzOenYFkm6zh_s59ndziTctKMz196Y8AL08xuTi6d1gEWpM92A
x-real-ip: 127.0.0.1
--- error_code: 200
Loading