Skip to content

Commit c5b141a

Browse files
author
Bogdan Degtyariov
committed
WL#16435 - JDBC: OpenID authentication support
Change-Id: I55a3a65fc006372d465d9d5753e13556c68e6dc1
1 parent 94322a5 commit c5b141a

12 files changed

+198
-1
lines changed

jdbc/cppconn/connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
#define OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE \
139139
"OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE"
140140
#define OPT_OCI_CLIENT_CONFIG_PROFILE "OPT_OCI_CLIENT_CONFIG_PROFILE"
141+
#define OPT_OPENID_TOKEN_FILE "OPT_OPENID_TOKEN_FILE"
141142

142143
/*
143144
Telemetry options

jdbc/driver/mysql_connection.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797

9898

9999
bool oci_plugin_is_loaded = false;
100+
bool openid_plugin_is_loaded = false;
100101

101102

102103
#ifdef DEFAULT_PLUGIN_DIR
@@ -1313,7 +1314,25 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
13131314
OPT_AUTHENTICATION_KERBEROS_CLIENT_MODE);
13141315
}
13151316
#endif // defined(_WIN32)
1317+
} else if (!it->first.compare(OPT_OPENID_TOKEN_FILE)) {
1318+
try {
1319+
p_s= (it->second).get<sql::SQLString>();
1320+
} catch (sql::InvalidArgumentException&) {
1321+
throw sql::InvalidArgumentException("Wrong type passed for OPT_OPENID_TOKEN_FILE. Expected sql::SQLString.");
1322+
}
13161323

1324+
try {
1325+
proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
1326+
"authentication_openid_connect_client",
1327+
"id-token-file",
1328+
*p_s);
1329+
openid_plugin_is_loaded = true;
1330+
} catch (sql::InvalidArgumentException &e) {
1331+
throw ::sql::SQLUnsupportedOptionException(
1332+
"Failed to set token file for authentication_openid_connect_client plugin",
1333+
OPT_OPENID_TOKEN_FILE
1334+
);
1335+
}
13171336
} else if (!it->first.compare(OPT_PLUGIN_DIR)) {
13181337
// Nothing to do here: this option was handeld before the loop
13191338

@@ -1368,6 +1387,21 @@ void MySQL_Connection::init(ConnectOptionsMap & properties)
13681387

13691388
}
13701389

1390+
if (openid_plugin_is_loaded) {
1391+
if (properties.find(OPT_OPENID_TOKEN_FILE) == properties.end()) {
1392+
// If OpenID plugin is loaded, but OPT_OPENID_TOKEN_FILE is not explicitly set
1393+
// the option value needs resetting.
1394+
try {
1395+
proxy->plugin_option(MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
1396+
"authentication_openid_connect_client",
1397+
"id-token-file",
1398+
nullptr);
1399+
} catch (sql::InvalidArgumentException &) {
1400+
// Do nothing, the exception is expected.
1401+
}
1402+
}
1403+
}
1404+
13711405
#undef PROCESS_CONNSTR_OPTION
13721406

13731407
for(auto h : uri)

jdbc/test/unit/classes/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,26 @@ IF(WIN32)
205205
ENDIF(WIN32)
206206

207207
add_unit_test(variant)
208+
209+
# Install tokens for OpenID authentication
210+
foreach (token
211+
openid_token_correct.txt
212+
openid_token_empty.txt
213+
openid_token_expired.txt
214+
openid_token_invalid.txt
215+
openid_token_issuer2.txt
216+
openid_token_key2.txt
217+
openid_token_user2.txt
218+
)
219+
# Copy tokens to build dir
220+
file(COPY tokens/${token} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
221+
222+
# Install tokens
223+
install(
224+
FILES ${token}
225+
DESTINATION tests/jdbc
226+
COMPONENT JDBCTests
227+
EXCLUDE_FROM_ALL
228+
)
229+
230+
endforeach()

jdbc/test/unit/classes/connection.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <list>
4444
#include <memory>
4545
#include <thread>
46+
#include <filesystem>
4647

4748
#ifdef _WIN32
4849
#pragma warning (disable : 4996)
@@ -4310,5 +4311,131 @@ void connection::macro_version()
43104311
#endif
43114312
}
43124313

4314+
void connection::openid_token()
4315+
{
4316+
try {
4317+
stmt->execute("UNINSTALL PLUGIN authentication_openid_connect");
4318+
} catch (...) {}
4319+
4320+
bool plugin_installed = false;
4321+
4322+
// Try every known shared lib extension. If any of them succeeds
4323+
// we can go with the test.
4324+
for (sql::SQLString extension : { ".so", ".dylib", ".sl", ".dll", "" }) {
4325+
try {
4326+
stmt->execute("INSTALL PLUGIN authentication_openid_connect "
4327+
"SONAME 'authentication_openid_connect" + extension + "'");
4328+
4329+
// Plugin is installed if the execution reached these lines.
4330+
// So, the loop can be exited.
4331+
plugin_installed = true;
4332+
break;
4333+
} catch (...) { }
4334+
}
4335+
4336+
if (!plugin_installed)
4337+
SKIP("Server doesn't support auth test plugin authentication_openid_connect");
4338+
4339+
std::cout << "Plugin installed\n";
4340+
4341+
#define L1Q "\""
4342+
#define L2Q "\\\""
4343+
#define L3Q "\\\\\\\""
4344+
4345+
stmt->execute("SET GLOBAL authentication_openid_connect_configuration = "
4346+
L1Q "JSON://{"
4347+
L2Q "myissuer" L2Q ":" L2Q "{"
4348+
L3Q "kid" L3Q ":" L3Q "b50071d7-e2f0-4e5e-9ae8-c71ac21d16bd" L3Q ","
4349+
L3Q "kty" L3Q ":" L3Q "RSA" L3Q ","
4350+
L3Q "alg" L3Q ":" L3Q "RS256" L3Q ","
4351+
L3Q "use" L3Q ":" L3Q "sig" L3Q ","
4352+
L3Q "e" L3Q ":" L3Q "AQAB" L3Q ","
4353+
L3Q "name" L3Q ":" L3Q "https://myissuer.com" L3Q ","
4354+
L3Q "n" L3Q ":" L3Q "09bia-SkqQHWNDZzYoHQtOLUDESzzsjU0rqnyen9o9LG"
4355+
"DNLGFCFiz0XDOTQhu5ZL7XcHB_IEY9kFdewIC7Kcm8pDJOp7hkXMOeopNP3SlH_lg"
4356+
"nVSjf6OSWdtAdeL4oW_8zryGoCCy2IksNY53lOF_zDg3DH1qSvCl1VXK50MIwe0BW"
4357+
"jT71VX_tkK_iXPzMxEPXol8hKU5djWfxGRjaKDqsffDt_UJudOHIH_O81oMpT82UQ"
4358+
"SOzmZBCwcf6jemLAWKDDo6mBxwXAHp8is_mvbisuU9QgKKjsG6FXmIQaj-jXR4IHg"
4359+
"lhV-aN_jqi8Y9ab0EANpDqAqbwdBQeL9BTp9fsW32gOTY_a7_gLOwZpCIBkalrGW9"
4360+
"E6zA0pBiypSuA0Ag5lB8dddRE486zsxxFYIBpDhMzK_CQ9Kq-3B44yJOheBdRRHYo"
4361+
"EXWfuXTKIbzDoctVw_TBBD3Qh3cV5FSs9lTUAU_eFhbYdoTR9FyTXHMDCo8Axxc66"
4362+
"IU6EdyUk6xLV9PtyCVWGoM_mFBvEwf7-btJYo73Xqw74T3eVZeTdLAHPHTojMybc5"
4363+
"OYt_UhpwDlI2lDGUAEEWsn5_XBhJeXc_GEGdEOowieWdwcRYgNFERkvH6-XSbZ0ii"
4364+
"Zxyi_Ri4DrYK1pm-WDxrFB-RuG1evcLG7rmacIDo1LPApMtpnHkYxc" L3Q
4365+
"}" L2Q
4366+
"}" L1Q ";"
4367+
);
4368+
4369+
std::cout << "Server configured\n";
4370+
4371+
stmt->execute("DROP USER IF EXISTS 'MySQLUser'@'%'");
4372+
4373+
stmt->execute("CREATE USER 'MySQLUser'@'%' IDENTIFIED WITH "
4374+
"'authentication_openid_connect' AS "
4375+
"'{\"identity_provider\" : \"myissuer\", \"user\" : \"mysubj\"}'");
4376+
4377+
std::cout << "User created\n";
4378+
4379+
sql::SQLString cur_path = std::filesystem::current_path().string() +
4380+
std::string(1, std::filesystem::path::preferred_separator);
4381+
4382+
// If token parameter is not specified it will be given via map
4383+
// as a non-path (non-string parameter)
4384+
auto connect_func = [&cur_path, this](sql::SQLString *token, bool is_ok,
4385+
sql::ConnectOptionsMap map = {})
4386+
{
4387+
sql::ConnectOptionsMap opts = map;
4388+
opts[OPT_USERNAME] = "MySQLUser";
4389+
opts["hostName"] = url;
4390+
4391+
if (getenv("PLUGIN_DIR"))
4392+
opts[OPT_PLUGIN_DIR] = getenv("PLUGIN_DIR");
4393+
4394+
4395+
if (token)
4396+
{
4397+
if (token->length()) {
4398+
opts[OPT_OPENID_TOKEN_FILE] = cur_path + *token;
4399+
std::cout << "Using token " << *token << std::endl;
4400+
} else {
4401+
std::cout << "Token not given" << std::endl;
4402+
}
4403+
} else {
4404+
std::cout << "Using token which is not a path" << std::endl;
4405+
}
4406+
4407+
try{
4408+
Connection con(driver->connect(opts));
4409+
if (!is_ok)
4410+
FAIL("Connection was expected to fail");
4411+
} catch(sql::SQLException &e) {
4412+
if (is_ok)
4413+
throw e;
4414+
}
4415+
};
4416+
4417+
sql::SQLString correct_token = "openid_token_correct.txt";
4418+
4419+
// OK with correct token
4420+
connect_func(&correct_token, true);
4421+
4422+
// FAIL with correct token, but disabled SSL
4423+
connect_func(&correct_token, false,
4424+
{{OPT_SSL_MODE , sql::SSL_MODE_DISABLED}});
4425+
4426+
// FAIL with token not being a path
4427+
connect_func(nullptr, false,
4428+
{{OPT_OPENID_TOKEN_FILE, 100}});
4429+
4430+
// FAIL with all token values
4431+
for (sql::SQLString t : { "", "non_existing", "openid_token_empty.txt",
4432+
"openid_token_invalid.txt", "openid_token_user2.txt",
4433+
"openid_token_key2.txt", "openid_token_issuer2.txt",
4434+
"openid_token_expired.txt"}) {
4435+
connect_func(&t, false);
4436+
}
4437+
4438+
}
4439+
43134440
} /* namespace connection */
43144441
} /* namespace testsuite */

jdbc/test/unit/classes/connection.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class connection : public unit_fixture
6262
* TODO: enable it when DNS+SRV works in docker
6363
TEST_CASE(checkDnsSrv);
6464
*/
65+
TEST_CASE(openid_token);
6566
TEST_CASE(getClientInfo);
6667
TEST_CASE(getClientOption);
6768
TEST_CASE(getSessionVariable);
@@ -103,7 +104,6 @@ class connection : public unit_fixture
103104
TEST_CASE(webauthn_test);
104105
TEST_CASE(normalize_ssl_options);
105106
TEST_CASE(macro_version);
106-
107107
}
108108

109109
/**
@@ -330,6 +330,12 @@ class connection : public unit_fixture
330330
*
331331
*/
332332
void macro_version();
333+
334+
/*
335+
* Test OPT_OPENID_TOKEN_FILE option.
336+
*
337+
*/
338+
void openid_token();
333339
};
334340

335341
REGISTER_FIXTURE(connection);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJteXN1YmoiLCJpc3MiOiJodHRwczovL215aXNzdWVyLmNvbSIsImV4cCI6MjE0MTE5OTA0OH0.giP_mwjDhr-FvcNBJzzQsSqEUOJLm3nJRWOSFRQiywZaRutap8y4vJC9DJWiM4hNngE3jtMd3SkR1ScYqTkZ6TuyOfBZE76lt5e6U-0mVHwPHjyTVaUPZ6izJMv_itITVh3BQYEPYvW42t8o0xZcMPTtE7bEr3ozFiVJSq8kQu34wThGYnT-Ro2ZRKwtowHXwcOA7rj09BeuR21Yk0YZXM5eYkL6eAGAUhWkdv4ary5tGTovWMJ3x5wmEG9RwzGd5F_DcecZFlTGKWE0UINa0p7sHE0HSfZKvW_vB7C5sEgSEQ1bOxu9Gm0UuLWOTjplTScSclJjMqUEkGQoSkYJFD3We-6JmrpvambzYY5OyGVZ71aPErb2Qv2VKUMKr0X-dmYF-kfbR4cS7Ba1PvqL4NsxidotqKivxdr0KtqOBpxTIF0cBWPewarvXbTj7ImH4i6mrKUBBRM6dYYr9x2pCdJRJ3OAwRoOmg1bFY5EJl5Ren43dVdIvfVEnLqmtrLc1MiGdrSz1jKM4ZHEhSP_PKgNcx3c2Q8fqS7KnmXZiLNPwTQ57ogEFmWR_5KTJnN3Xw6ecyhHIOmVzpjF6pYb3QTMvJHVfGkiUdaaYA6ZpU5FmAOEWmhfuqlLNYj7ZabPHyoIR0KfhB_PVB05ITIBWdTVckjh2S5qOMGl4C0UkV4

jdbc/test/unit/classes/tokens/openid_token_empty.txt

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJteXN1YmoiLCJpc3MiOiJodHRwczovL215aXNzdWVyLmNvbSIsImV4cCI6MTcyMTE5OTEzMH0.QabeeIDGvIoWPzHO8lXi6vzeR0Appq0RVQXNHQBDjMvTfcwyaPjr7cA1JTO36aNZkAO0fdHxKRkG76gteudSKhkg-jGq5C5rkyLjQ-Uau3ZQPt2cgYTYVR13eIMkXGwDrK-Pq6n7P_GtdWs5pgT3cVSJu5QjKby5DFt1MSVTGqr35ZijGcDuBU_E9MV7ypligU8tp9-dzbqtJy8W_0F_LBQstEIZsWTDedEpuoYVPopyReB229t-OGxrWe16q1oOXxKGWDe248-ztXSDnM_89dp_j26w0WXA-lE4uIbx6xVR0EpP9orSjz4ue0m2vvBdyqdGygUJHkoHcM60JPVkl6k2nuZWfJlxTB6ynzqgQfGOaFsOh3VPQ7ONT9H0vr0zAD7psTdK834Oz3aL6fnfbyVH4k8Kk6GQUbOsxcpRxptFCk6D2KmSPnN0U9PX6PKFSyJMLSq_pwA8BuE7lLZUaffwxUPvve0X_0FwMCLo3bJMJewPVoJHe0cEK9PaUWjixj4F0LDD8BpW_et7WO-fozZT0IgDI6J6UdEVNFwiKFrKGMDZ48Gbanve761zfEFEG6ZpPYpgTXC2WYk59_joo1MJlddyh5SUlJd2L-z9YBgv5p2bGB2H7MDCxV14aJBTnxeGbwNfsRYmwxQA6WtFtj58b4EBUK_S9t0Rf2z366w
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hjkGHTJRHNGBFAHJ$^&EHRTGBSDHGMJ#$^%WHGBSNDHGFBVFHGJEHNSFBGHMG
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJteXN1YmoiLCJpc3MiOiJodHRwczovL215aXNzdWVyMi5jb20iLCJleHAiOjIxNDExOTkyODl9.X6xCRzw_FDC4NJ6PEb11JJdsyb7bpkqsXBvOUkjvLfKzDtuFpZ5gGETUz_65pOraXsZAlwD_r645_AczL0MJgA880JtHmWqzzEORT-rNIwlHdZ2BZH4A6BCj-xslWwDKgzkETKe2AEQ5X8aHFO0fF1QwwyPxUUGR0TFaGyOrzL7e02Q0bsu8zvpusx1-WcJSxBRfLDUJN3M-eJo-daU2YZSelj8OxSLZ6FpedJPPrBBWLHwj_jxITp5OkJLsvdivPyuVMdu2acN5gB97P9a3A0Wr0G-uyPNyUj7N2ru0C0bC_B4wUqbPLdrT9U3bFPVA3OCFnt3PzlubU5JYVQUHIXQpZinIpkQQs5zia-e82YghW7Q6GLtWkWTbxOQ3Zgc2jYM_qbTuN8iL4sgmagFgZNV1Zd7rCew2cbTRaL1McdI8H4swkh5i5gfV55bj_t7X9Ow93LmMdayMnm-fQMs8qrp7PXMS2D1YImkg01443wxqAnpdqXHNLxXE_EyfnxbSNTG7y15_-B3CPfbX8srBJQVO9OdrwfLEmP4N6uon2EuNt29kyJtbA7QrEUVT7fNjcdl4FL-Arcc5N9uViPC6W4WerrgkUgHIsgOjfGICr4OY0P9pIX62n7GUrse2HmHpTFcMIwOuqs3nEW_c6JEtfUuDpXwKCMI_Xu7I1k4oAQg
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJteXN1YmoiLCJpc3MiOiJodHRwczovL215aXNzdWVyLmNvbSIsImV4cCI6MjE0MTE5OTQxOH0.IZtN1cTBTN2gWf7OjUwNwWe0C1E2zgcTh-3E27CIG2NXofk1KgoqhVEs2lqmcHfl8vnYLKOBpxNWuS6sXgsO-HaGVksbDv-N-XeuM4_EJXq5Dx4QxQkDMS2d99yR7o-xTlKf8IS5iRvw6Lgh5U35fOIQeeRWfWwPIz2EQ2Bpwr8IPttkUPy0-n6uFLIhsO8nhZopXGZdWW5WIL96qsPDgnw-P-ogdPAwOMPXwxIkMsngNkE_1dApwnkfwW4e-woox_OpIglt8vTHZGYjJZtFJEJFL0KFlmzRwjZ4gnxyluaiG9dn4F2FoiuPcLwJcEQn0U7m31Cj-dYSIGdPlBxQt229usXXO1Cw7Ls6sEz4sIpyPqZu_UIU-SHwHDIp5duJJakvzy97WicF8hd3iaVbepXKo3B41SWC8zqXfE8J1OZUnwS9JIi1Sfa9T8307q94DM6j76QJ3IhJYwFVmCI9gYoRuxlvmYyS7Y_4lBHRX1_bCaVZPKJyW7IK1GNOTR7SXbGh9ZXotL24ATtCQXploAxjK7JZzqLnI1_aIZbCTK90m9Ty90AW2SU-LkEYhqTToxSCUxC5uBWJvM6gFscfp_bx0fH8uBmXg5hejoMsZjQtPHs2LfaYpTwHOW2uG_zfik2D95Nc5J_Y6hZiCaZW6H1Mps6oyv9nZgK3TIY7_N4
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJteXN1YmoyIiwiaXNzIjoiaHR0cHM6Ly9teWlzc3Vlci5jb20iLCJleHAiOjIxNDExOTkzMzl9.PIeiYp0eS3dO2QBh2UAqq48zAxZ5C-snBQmXw1n4zvgc90ZnAfJnJWUeOQxkjU7uQoNA84QuMLH7UV0VXNefscx5YIimOygIh9vwC4stxqUu9sdd3uUiZ-TBABKINz5Li18rRpDpSxWaOYTQ3gkg71BCJ8W1ndUQPtBgP_Yq1d0Fe83ypMF0ukorunAXhqX494wufrxqHjmmf82NpkPoGr4PGm6VwRUHMD46_-sisuxkleYkKYa7KSACjx6YhZRzeWh3iC6j40aMiKETKqVTjPhYskV59PjYjoAykpVegj7HYTx-wBclA0NHyyOVceeSNQ6yMdZAHrJO3axZzD_fQPBNmoIkeem2FSYlV1qZ0t5nIhZqdnSWewkj_tB3AbVHkJyZLPHCfmc3Cye8TQX49tgOwV-slI4xbRGhOXC5dj1vPEmuYYaClzFdsna0wN0spVsCj2v1NS4hGfIC9v8mDBAfBV6k3XGtgwnCU9GtGLWrBWHm5INbbKAid7RNbMECj-nmuUQG9jm59ukVgW_OaX8C0wF8M0-itlW71o0kQASw1CEDK64j0QeFLCGbDiHm3wo5rS-DVVINyNvARpdfZ9u4HorV2eod8cs6b_RN-tYVcR_KdPNYHJjVoleHYO6yQlC0yshP7v55TowL5AwKL0iWafafHq082Ad7KQtwd4A

0 commit comments

Comments
 (0)