From 65e4794d579d38ffcb5f28aeabafb0f207fc3c29 Mon Sep 17 00:00:00 2001 From: Nate Plumm Date: Thu, 18 Jan 2024 17:11:53 -0700 Subject: [PATCH] #345 handle the userinfo response as JWT --- lib/resty/openidc.lua | 11 +++++++++++ tests/spec/test_support.lua | 9 +++++++++ tests/spec/userinfo_spec.lua | 23 +++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/lib/resty/openidc.lua b/lib/resty/openidc.lua index 1f3854e..e7b8872 100644 --- a/lib/resty/openidc.lua +++ b/lib/resty/openidc.lua @@ -623,6 +623,17 @@ function openidc.call_userinfo_endpoint(opts, access_token) log(DEBUG, "userinfo response: ", res.body) + -- handle if the response type is a jwt/signed payload + local responseType = string.lower(res.headers["Content-Type"]) + if string.find(responseType, "application/jwt") then + local json, err = openidc.jwt_verify(res.body, opts) + if err then + err = "userinfo jwt could not be verified: " .. err + return nil, err + end + return json + end + -- parse the response from the user info endpoint return openidc_parse_json_response(res) end diff --git a/tests/spec/test_support.lua b/tests/spec/test_support.lua index fb1d229..cca73e2 100644 --- a/tests/spec/test_support.lua +++ b/tests/spec/test_support.lua @@ -326,6 +326,15 @@ http { } } + location /user-info-signed { + content_by_lua_block { + local auth = ngx.req.get_headers()["Authorization"] + ngx.header.content_type = 'application/jwt;charset=UTF-8' + local signed_userinfo = test_globals.create_jwt(USERINFO) + ngx.print(signed_userinfo) + } + } + location /introspection { content_by_lua_block { ngx.req.read_body() diff --git a/tests/spec/userinfo_spec.lua b/tests/spec/userinfo_spec.lua index 800a84a..856a237 100644 --- a/tests/spec/userinfo_spec.lua +++ b/tests/spec/userinfo_spec.lua @@ -169,3 +169,26 @@ describe("when userinfo endpoint doesn't return proper JSON", function() assert.error_log_contains("JSON decoding failed") end) end) + +describe("when userinfo endpoint returns a JWT", function() + test_support.start_server({ + oidc_opts = { + discovery = { + userinfo_endpoint = "http://127.0.0.1/user-info-signed", + token_endpoint_auth_methods_supported = { "private_key_jwt" }, + }, + token_endpoint_auth_method = "private_key_jwt", + client_rsa_private_key = test_support.load("/spec/private_rsa_key.pem"), + public_key = test_support.load("/spec/public_rsa_key.pem"), + }, + }) + teardown(test_support.stop_server) + local _, status = test_support.login() + it("login succeeds", function() + assert.are.equals(302, status) + end) + it("an error has not been logged", function() + assert.is_not.error_log_contains("JSON decoding failed") + assert.is_not.error_log_contains("userinfo jwt could not be verified") + end) +end)