aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasily Gerasimov <UgnineSirdis@ydb.tech>2024-07-08 12:51:17 +0300
committerGitHub <noreply@github.com>2024-07-08 12:51:17 +0300
commit8ccdffdeede630040938ce7d0130f34d2a089dfe (patch)
tree6a56ce29b5caba2b9e0f048f61e299bb1746c56c
parent57741e4c04902b615c634bc39592127bd50de1fe (diff)
downloadydb-8ccdffdeede630040938ce7d0130f34d2a089dfe.tar.gz
Fix HMAC secret key loading for OAuth 2.0 token exchange config (#6290)
-rw-r--r--ydb/docs/en/core/reference/ydb-sdk/_includes/auth.md2
-rw-r--r--ydb/docs/ru/core/reference/ydb-sdk/_includes/auth.md2
-rw-r--r--ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/from_file.cpp35
-rw-r--r--ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/credentials_ut.cpp84
-rw-r--r--ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_check_helper.h6
-rw-r--r--ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_token_source_ut.cpp13
-rw-r--r--ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/ya.make1
-rw-r--r--ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ya.make1
8 files changed, 124 insertions, 20 deletions
diff --git a/ydb/docs/en/core/reference/ydb-sdk/_includes/auth.md b/ydb/docs/en/core/reference/ydb-sdk/_includes/auth.md
index 3808c2b0a35..8f7233f4aff 100644
--- a/ydb/docs/en/core/reference/ydb-sdk/_includes/auth.md
+++ b/ydb/docs/en/core/reference/ydb-sdk/_includes/auth.md
@@ -122,7 +122,7 @@ Fields not described in this table are ignored.
|**Description of fields of `creds_json` (JWT)**|||||
|`type`|string|Token source type. Set `JWT`||
|`alg`|string|Algorithm for JWT signature. Supported algorithms: ES256, ES384, ES512, HS256, HS384, HS512, PS256, PS384, PS512, RS256, RS384, RS512||
-|`private-key`|string|(Private) key in PEM format for JWT signature||
+|`private-key`|string|(Private) key in PEM format (for algorithms `ES*`, `PS*`, `RS*`) or Base64 format (for algorithms `HS*`) for JWT signature||
|`kid`|string|`kid` JWT standard claim (key id)|optional|
|`iss`|string|`iss` JWT standard claim (issuer)|optional|
|`sub`|string|`sub` JWT standard claim (subject)|optional|
diff --git a/ydb/docs/ru/core/reference/ydb-sdk/_includes/auth.md b/ydb/docs/ru/core/reference/ydb-sdk/_includes/auth.md
index d74a680c036..7c16406ac1b 100644
--- a/ydb/docs/ru/core/reference/ydb-sdk/_includes/auth.md
+++ b/ydb/docs/ru/core/reference/ydb-sdk/_includes/auth.md
@@ -121,7 +121,7 @@
|**Описание полей `creds_json` (JWT)**|||||
|`type`|string|Тип источника токена. Нужно задать константу `JWT`||
|`alg`|string|Алгоритм подписи JWT. Поддерживаются следующие алгоритмы: ES256, ES384, ES512, HS256, HS384, HS512, PS256, PS384, PS512, RS256, RS384, RS512||
-|`private-key`|string|(Приватный) ключ в формате PEM для подписи||
+|`private-key`|string|(Приватный) ключ в формате PEM (для алгоритмов `ES*`, `PS*`, `RS*`) или Base64 (для алгоритмов `HS*`) для подписи||
|`kid`|string|Стандартное поле JWT `kid` (key id)|опциональное|
|`iss`|string|Стандартное поле JWT `iss` (issuer)|опциональное|
|`sub`|string|Стандартное поле JWT `sub` (subject)|опциональное|
diff --git a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/from_file.cpp b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/from_file.cpp
index 594ac4a995c..6eb684423bc 100644
--- a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/from_file.cpp
+++ b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/from_file.cpp
@@ -3,6 +3,7 @@
#include "jwt_token_source.h"
#include <library/cpp/json/json_reader.h>
+#include <library/cpp/string_utils/base64/base64.h>
#include <util/generic/map.h>
#include <util/stream/file.h>
@@ -32,10 +33,42 @@ void ApplyAsymmetricAlg(TJwtTokenSourceParams* params, const TString& privateKey
params->SigningAlgorithm<TAlg>(std::string{}, privateKey);
}
+size_t Base64OutputLen(TStringBuf input) {
+ while (input && (input.back() == '=' || input.back() == ',')) { // padding
+ input.remove_suffix(1);
+ }
+ const size_t inputLen = input.size();
+ const size_t tailEncoded = inputLen % 4;
+ if (tailEncoded == 1) {
+ throw std::runtime_error(TStringBuilder() << "invalid Base64 encoded data size: " << input.size());
+ }
+ const size_t mainSize = (inputLen / 4) * 3;
+ size_t tailSize = 0;
+ switch (tailEncoded) {
+ case 2: // 12 bit => 1 byte
+ tailSize = 1;
+ break;
+ case 3: // 18 bits -> 2 bytes
+ tailSize = 2;
+ break;
+ }
+ return mainSize + tailSize;
+}
+
template <class TAlg>
void ApplyHmacAlg(TJwtTokenSourceParams* params, const TString& key) {
+ // HMAC keys are encoded in base64 encoding
+ const size_t base64OutputSize = Base64OutputLen(key); // throws
+ TString binaryKey;
+ binaryKey.ReserveAndResize(Base64DecodeBufSize(key.size()));
+ // allows strings without padding
+ const size_t decodedBytes = Base64DecodeUneven(const_cast<char*>(binaryKey.data()), key);
+ if (decodedBytes != base64OutputSize) {
+ throw std::runtime_error("failed to decode HMAC secret from Base64");
+ }
+ binaryKey.resize(decodedBytes);
// Alg with first param as key
- params->SigningAlgorithm<TAlg>(key);
+ params->SigningAlgorithm<TAlg>(binaryKey);
}
const TMap<TString, void(*)(TJwtTokenSourceParams*, const TString& privateKey), TLessNoCase> JwtAlgorithmsFactory = {
diff --git a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/credentials_ut.cpp b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/credentials_ut.cpp
index 4bb4a6562ba..f502a7e3c34 100644
--- a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/credentials_ut.cpp
+++ b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/credentials_ut.cpp
@@ -7,6 +7,7 @@
#include <library/cpp/http/server/http.h>
#include <library/cpp/http/server/response.h>
#include <library/cpp/json/json_writer.h>
+#include <library/cpp/string_utils/base64/base64.h>
#include <library/cpp/testing/unittest/registar.h>
#include <library/cpp/testing/unittest/tests_data.h>
@@ -16,8 +17,11 @@
using namespace NYdb;
-extern const TString TestPrivateKeyContent;
-extern const TString TestPublicKeyContent;
+extern const TString TestRSAPrivateKeyContent;
+extern const TString TestRSAPublicKeyContent;
+extern const TString TestECPrivateKeyContent;
+extern const TString TestECPublicKeyContent;
+extern const TString TestHMACSecretKeyBase64Content;
class TTestTokenExchangeServer: public THttpServer::ICallBack {
public:
@@ -33,7 +37,7 @@ public:
TMaybe<TJwtCheck> ActorJwtCheck;
void Check() {
- UNIT_ASSERT(InputParams || !ExpectRequest);
+ UNIT_ASSERT_C(InputParams || !ExpectRequest, "Request error: " << Error);
if (InputParams) {
if (SubjectJwtCheck || ActorJwtCheck) {
TCgiParameters inputParamsCopy = *InputParams;
@@ -976,7 +980,7 @@ Y_UNIT_TEST_SUITE(TestTokenExchange) {
.Subject("test_sub")
.Audience("test_aud")
.Id("test_jti")
- .Alg<jwt::algorithm::rs384>(TestPublicKeyContent);
+ .Alg<jwt::algorithm::rs384>(TestRSAPublicKeyContent);
server.Check.ActorJwtCheck.ConstructInPlace()
.AppendAudience("a1")
.AppendAudience("a2");
@@ -993,7 +997,7 @@ Y_UNIT_TEST_SUITE(TestTokenExchange) {
.Field("aud", "test_aud")
.Field("jti", "test_jti")
.Field("alg", "rs384")
- .Field("private-key", TestPrivateKeyContent)
+ .Field("private-key", TestRSAPrivateKeyContent)
.Field("unknown", "unknown value")
.Build()
.SubMap("actor-credentials")
@@ -1003,7 +1007,33 @@ Y_UNIT_TEST_SUITE(TestTokenExchange) {
.Value("a2")
.Build()
.Field("alg", "RS256")
- .Field("private-key", TestPrivateKeyContent)
+ .Field("private-key", TestRSAPrivateKeyContent)
+ .Build()
+ .Build(),
+ "Bearer received_token"
+ );
+
+ // Other signing methods
+ server.Check.SubjectJwtCheck.ConstructInPlace()
+ .Id("jti")
+ .Alg<jwt::algorithm::hs384>(Base64Decode(TestHMACSecretKeyBase64Content));
+ server.Check.ActorJwtCheck.ConstructInPlace()
+ .Alg<jwt::algorithm::es256>(TestECPublicKeyContent)
+ .Issuer("iss");
+ server.RunFromConfig(
+ TTestConfigFile()
+ .Field("token-endpoint", server.GetEndpoint())
+ .SubMap("subject-credentials")
+ .Field("type", "jwt")
+ .Field("jti", "jti")
+ .Field("alg", "HS384")
+ .Field("private-key", TestHMACSecretKeyBase64Content)
+ .Build()
+ .SubMap("actor-credentials")
+ .Field("type", "JWT")
+ .Field("alg", "ES256")
+ .Field("private-key", TestECPrivateKeyContent)
+ .Field("iss", "iss")
.Build()
.Build(),
"Bearer received_token"
@@ -1089,7 +1119,7 @@ Y_UNIT_TEST_SUITE(TestTokenExchange) {
.Field("token-endpoint", server.GetEndpoint())
.SubMap("subject-credentials")
.Field("type", "jwt")
- .Field("private-key", TestPrivateKeyContent)
+ .Field("private-key", TestRSAPrivateKeyContent)
.Build()
.Build()
);
@@ -1112,7 +1142,7 @@ Y_UNIT_TEST_SUITE(TestTokenExchange) {
.SubMap("subject-credentials")
.Field("type", "jwt")
.Field("alg", "rs256")
- .Field("private-key", TestPrivateKeyContent)
+ .Field("private-key", TestRSAPrivateKeyContent)
.Field("ttl", "-1s")
.Build()
.Build()
@@ -1125,7 +1155,7 @@ Y_UNIT_TEST_SUITE(TestTokenExchange) {
.SubMap("subject-credentials")
.Field("type", "jwt")
.Field("alg", "algorithm")
- .Field("private-key", TestPrivateKeyContent)
+ .Field("private-key", TestRSAPrivateKeyContent)
.Build()
.Build()
);
@@ -1142,6 +1172,42 @@ Y_UNIT_TEST_SUITE(TestTokenExchange) {
.Build()
);
+ server.Check.ExpectedErrorPart = "failed to decode HMAC secret from Base64";
+ server.RunFromConfig(
+ TTestConfigFile()
+ .Field("token-endpoint", server.GetEndpoint())
+ .SubMap("subject-credentials")
+ .Field("type", "jwt")
+ .Field("alg", "hs256")
+ .Field("private-key", "\n<not a base64>\n")
+ .Build()
+ .Build()
+ );
+
+ server.Check.ExpectedErrorPart = "failed to load private key";
+ server.RunFromConfig(
+ TTestConfigFile()
+ .Field("token-endpoint", server.GetEndpoint())
+ .SubMap("subject-credentials")
+ .Field("type", "jwt")
+ .Field("alg", "es256")
+ .Field("private-key", TestRSAPrivateKeyContent) // Need EC key
+ .Build()
+ .Build()
+ );
+
+ server.Check.ExpectedErrorPart = "failed to load private key";
+ server.RunFromConfig(
+ TTestConfigFile()
+ .Field("token-endpoint", server.GetEndpoint())
+ .SubMap("subject-credentials")
+ .Field("type", "jwt")
+ .Field("alg", "ps512")
+ .Field("private-key", TestHMACSecretKeyBase64Content) // Need RSA key
+ .Build()
+ .Build()
+ );
+
server.Check.ExpectedErrorPart = "Not a map";
server.RunFromConfig(
TTestConfigFile()
diff --git a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_check_helper.h b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_check_helper.h
index 4466dc8dbb1..551822575f8 100644
--- a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_check_helper.h
+++ b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_check_helper.h
@@ -5,8 +5,8 @@
#include <contrib/libs/jwt-cpp/include/jwt-cpp/jwt.h>
-extern const TString TestPrivateKeyContent;
-extern const TString TestPublicKeyContent;
+extern const TString TestRSAPrivateKeyContent;
+extern const TString TestRSAPublicKeyContent;
struct TJwtCheck {
using TSelf = TJwtCheck;
@@ -37,7 +37,7 @@ struct TJwtCheck {
Alg_.Reset(new TAlgCheck<TAlg>(publicKey));
return *this;
}
- THolder<IAlgCheck> Alg_ = MakeHolder<TAlgCheck<jwt::algorithm::rs256>>(TestPublicKeyContent);
+ THolder<IAlgCheck> Alg_ = MakeHolder<TAlgCheck<jwt::algorithm::rs256>>(TestRSAPublicKeyContent);
FLUENT_SETTING_OPTIONAL(TString, KeyId);
diff --git a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_token_source_ut.cpp b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_token_source_ut.cpp
index 5da56b5021c..d66403d835b 100644
--- a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_token_source_ut.cpp
+++ b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/jwt_token_source_ut.cpp
@@ -7,15 +7,18 @@
using namespace NYdb;
-extern const TString TestPrivateKeyContent = "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC75/JS3rMcLJxv\nFgpOzF5+2gH+Yig3RE2MTl9uwC0BZKAv6foYr7xywQyWIK+W1cBhz8R4LfFmZo2j\nM0aCvdRmNBdW0EDSTnHLxCsFhoQWLVq+bI5f5jzkcoiioUtaEpADPqwgVULVtN/n\nnPJiZ6/dU30C3jmR6+LUgEntUtWt3eq3xQIn5lG3zC1klBY/HxtfH5Hu8xBvwRQT\nJnh3UpPLj8XwSmriDgdrhR7o6umWyVuGrMKlLHmeivlfzjYtfzO1MOIMG8t2/zxG\nR+xb4Vwks73sH1KruH/0/JMXU97npwpe+Um+uXhpldPygGErEia7abyZB2gMpXqr\nWYKMo02NAgMBAAECggEAO0BpC5OYw/4XN/optu4/r91bupTGHKNHlsIR2rDzoBhU\nYLd1evpTQJY6O07EP5pYZx9mUwUdtU4KRJeDGO/1/WJYp7HUdtxwirHpZP0lQn77\nuccuX/QQaHLrPekBgz4ONk+5ZBqukAfQgM7fKYOLk41jgpeDbM2Ggb6QUSsJISEp\nzrwpI/nNT/wn+Hvx4DxrzWU6wF+P8kl77UwPYlTA7GsT+T7eKGVH8xsxmK8pt6lg\nsvlBA5XosWBWUCGLgcBkAY5e4ZWbkdd183o+oMo78id6C+PQPE66PLDtHWfpRRmN\nm6XC03x6NVhnfvfozoWnmS4+e4qj4F/emCHvn0GMywKBgQDLXlj7YPFVXxZpUvg/\nrheVcCTGbNmQJ+4cZXx87huqwqKgkmtOyeWsRc7zYInYgraDrtCuDBCfP//ZzOh0\nLxepYLTPk5eNn/GT+VVrqsy35Ccr60g7Lp/bzb1WxyhcLbo0KX7/6jl0lP+VKtdv\nmto+4mbSBXSM1Y5BVVoVgJ3T/wKBgQDsiSvPRzVi5TTj13x67PFymTMx3HCe2WzH\nJUyepCmVhTm482zW95pv6raDr5CTO6OYpHtc5sTTRhVYEZoEYFTM9Vw8faBtluWG\nBjkRh4cIpoIARMn74YZKj0C/0vdX7SHdyBOU3bgRPHg08Hwu3xReqT1kEPSI/B2V\n4pe5fVrucwKBgQCNFgUxUA3dJjyMES18MDDYUZaRug4tfiYouRdmLGIxUxozv6CG\nZnbZzwxFt+GpvPUV4f+P33rgoCvFU+yoPctyjE6j+0aW0DFucPmb2kBwCu5J/856\nkFwCx3blbwFHAco+SdN7g2kcwgmV2MTg/lMOcU7XwUUcN0Obe7UlWbckzQKBgQDQ\nnXaXHL24GGFaZe4y2JFmujmNy1dEsoye44W9ERpf9h1fwsoGmmCKPp90az5+rIXw\nFXl8CUgk8lXW08db/r4r+ma8Lyx0GzcZyplAnaB5/6j+pazjSxfO4KOBy4Y89Tb+\nTP0AOcCi6ws13bgY+sUTa/5qKA4UVw+c5zlb7nRpgwKBgGXAXhenFw1666482iiN\ncHSgwc4ZHa1oL6aNJR1XWH+aboBSwR+feKHUPeT4jHgzRGo/aCNHD2FE5I8eBv33\nof1kWYjAO0YdzeKrW0rTwfvt9gGg+CS397aWu4cy+mTI+MNfBgeDAIVBeJOJXLlX\nhL8bFAuNNVrCOp79TNnNIsh7\n-----END PRIVATE KEY-----\n";
-extern const TString TestPublicKeyContent = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu+fyUt6zHCycbxYKTsxe\nftoB/mIoN0RNjE5fbsAtAWSgL+n6GK+8csEMliCvltXAYc/EeC3xZmaNozNGgr3U\nZjQXVtBA0k5xy8QrBYaEFi1avmyOX+Y85HKIoqFLWhKQAz6sIFVC1bTf55zyYmev\n3VN9At45kevi1IBJ7VLVrd3qt8UCJ+ZRt8wtZJQWPx8bXx+R7vMQb8EUEyZ4d1KT\ny4/F8Epq4g4Ha4Ue6OrplslbhqzCpSx5nor5X842LX8ztTDiDBvLdv88RkfsW+Fc\nJLO97B9Sq7h/9PyTF1Pe56cKXvlJvrl4aZXT8oBhKxImu2m8mQdoDKV6q1mCjKNN\njQIDAQAB\n-----END PUBLIC KEY-----\n";
+extern const TString TestRSAPrivateKeyContent = "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC75/JS3rMcLJxv\nFgpOzF5+2gH+Yig3RE2MTl9uwC0BZKAv6foYr7xywQyWIK+W1cBhz8R4LfFmZo2j\nM0aCvdRmNBdW0EDSTnHLxCsFhoQWLVq+bI5f5jzkcoiioUtaEpADPqwgVULVtN/n\nnPJiZ6/dU30C3jmR6+LUgEntUtWt3eq3xQIn5lG3zC1klBY/HxtfH5Hu8xBvwRQT\nJnh3UpPLj8XwSmriDgdrhR7o6umWyVuGrMKlLHmeivlfzjYtfzO1MOIMG8t2/zxG\nR+xb4Vwks73sH1KruH/0/JMXU97npwpe+Um+uXhpldPygGErEia7abyZB2gMpXqr\nWYKMo02NAgMBAAECggEAO0BpC5OYw/4XN/optu4/r91bupTGHKNHlsIR2rDzoBhU\nYLd1evpTQJY6O07EP5pYZx9mUwUdtU4KRJeDGO/1/WJYp7HUdtxwirHpZP0lQn77\nuccuX/QQaHLrPekBgz4ONk+5ZBqukAfQgM7fKYOLk41jgpeDbM2Ggb6QUSsJISEp\nzrwpI/nNT/wn+Hvx4DxrzWU6wF+P8kl77UwPYlTA7GsT+T7eKGVH8xsxmK8pt6lg\nsvlBA5XosWBWUCGLgcBkAY5e4ZWbkdd183o+oMo78id6C+PQPE66PLDtHWfpRRmN\nm6XC03x6NVhnfvfozoWnmS4+e4qj4F/emCHvn0GMywKBgQDLXlj7YPFVXxZpUvg/\nrheVcCTGbNmQJ+4cZXx87huqwqKgkmtOyeWsRc7zYInYgraDrtCuDBCfP//ZzOh0\nLxepYLTPk5eNn/GT+VVrqsy35Ccr60g7Lp/bzb1WxyhcLbo0KX7/6jl0lP+VKtdv\nmto+4mbSBXSM1Y5BVVoVgJ3T/wKBgQDsiSvPRzVi5TTj13x67PFymTMx3HCe2WzH\nJUyepCmVhTm482zW95pv6raDr5CTO6OYpHtc5sTTRhVYEZoEYFTM9Vw8faBtluWG\nBjkRh4cIpoIARMn74YZKj0C/0vdX7SHdyBOU3bgRPHg08Hwu3xReqT1kEPSI/B2V\n4pe5fVrucwKBgQCNFgUxUA3dJjyMES18MDDYUZaRug4tfiYouRdmLGIxUxozv6CG\nZnbZzwxFt+GpvPUV4f+P33rgoCvFU+yoPctyjE6j+0aW0DFucPmb2kBwCu5J/856\nkFwCx3blbwFHAco+SdN7g2kcwgmV2MTg/lMOcU7XwUUcN0Obe7UlWbckzQKBgQDQ\nnXaXHL24GGFaZe4y2JFmujmNy1dEsoye44W9ERpf9h1fwsoGmmCKPp90az5+rIXw\nFXl8CUgk8lXW08db/r4r+ma8Lyx0GzcZyplAnaB5/6j+pazjSxfO4KOBy4Y89Tb+\nTP0AOcCi6ws13bgY+sUTa/5qKA4UVw+c5zlb7nRpgwKBgGXAXhenFw1666482iiN\ncHSgwc4ZHa1oL6aNJR1XWH+aboBSwR+feKHUPeT4jHgzRGo/aCNHD2FE5I8eBv33\nof1kWYjAO0YdzeKrW0rTwfvt9gGg+CS397aWu4cy+mTI+MNfBgeDAIVBeJOJXLlX\nhL8bFAuNNVrCOp79TNnNIsh7\n-----END PRIVATE KEY-----\n";
+extern const TString TestRSAPublicKeyContent = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu+fyUt6zHCycbxYKTsxe\nftoB/mIoN0RNjE5fbsAtAWSgL+n6GK+8csEMliCvltXAYc/EeC3xZmaNozNGgr3U\nZjQXVtBA0k5xy8QrBYaEFi1avmyOX+Y85HKIoqFLWhKQAz6sIFVC1bTf55zyYmev\n3VN9At45kevi1IBJ7VLVrd3qt8UCJ+ZRt8wtZJQWPx8bXx+R7vMQb8EUEyZ4d1KT\ny4/F8Epq4g4Ha4Ue6OrplslbhqzCpSx5nor5X842LX8ztTDiDBvLdv88RkfsW+Fc\nJLO97B9Sq7h/9PyTF1Pe56cKXvlJvrl4aZXT8oBhKxImu2m8mQdoDKV6q1mCjKNN\njQIDAQAB\n-----END PUBLIC KEY-----\n";
+extern const TString TestECPrivateKeyContent = "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIB6fv25gf7P/7fkjW/2kcKICUhHeOygkFeUJ/ylyU3hloAoGCCqGSM49\nAwEHoUQDQgAEvkKy92hpLiT0GEpzFkYBEWWnkAGTTA6141H0oInA9X30eS0RObAa\nmVY8yD39NI7Nj03hBxEa4Z0tOhrq9cW8eg==\n-----END EC PRIVATE KEY-----\n";
+extern const TString TestECPublicKeyContent = "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvkKy92hpLiT0GEpzFkYBEWWnkAGT\nTA6141H0oInA9X30eS0RObAamVY8yD39NI7Nj03hBxEa4Z0tOhrq9cW8eg==\n-----END PUBLIC KEY-----\n";
+extern const TString TestHMACSecretKeyBase64Content = "VGhlIHdvcmxkIGhhcyBjaGFuZ2VkLgpJIHNlZSBpdCBpbiB0aGUgd2F0ZXIuCkkgZmVlbCBpdCBpbiB0aGUgRWFydGguCkkgc21lbGwgaXQgaW4gdGhlIGFpci4KTXVjaCB0aGF0IG9uY2Ugd2FzIGlzIGxvc3QsCkZvciBub25lIG5vdyBsaXZlIHdobyByZW1lbWJlciBpdC4K";
Y_UNIT_TEST_SUITE(JwtTokenSourceTest) {
Y_UNIT_TEST(Encodes) {
auto source = CreateJwtTokenSource(
TJwtTokenSourceParams()
.KeyId("test_key_id")
- .SigningAlgorithm<jwt::algorithm::rs256>("", TestPrivateKeyContent)
+ .SigningAlgorithm<jwt::algorithm::rs256>("", TestRSAPrivateKeyContent)
.Issuer("test_issuer")
.Subject("test_subject")
.Audience("test_audience")
@@ -45,13 +48,13 @@ Y_UNIT_TEST_SUITE(JwtTokenSourceTest) {
UNIT_ASSERT_EXCEPTION_CONTAINS(CreateJwtTokenSource(
TJwtTokenSourceParams()
.KeyId("test_key_id")
- .SigningAlgorithm<jwt::algorithm::rs256>("", TestPrivateKeyContent)
+ .SigningAlgorithm<jwt::algorithm::rs256>("", TestRSAPrivateKeyContent)
.TokenTtl(TDuration::Zero())
), std::invalid_argument, "token TTL must be positive");
UNIT_ASSERT_EXCEPTION_CONTAINS(CreateJwtTokenSource(
TJwtTokenSourceParams()
- .SigningAlgorithm<jwt::algorithm::rs256>("", TestPrivateKeyContent)
+ .SigningAlgorithm<jwt::algorithm::rs256>("", TestRSAPrivateKeyContent)
.AppendAudience("aud")
.AppendAudience("aud2")
.AppendAudience("")
diff --git a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/ya.make b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/ya.make
index f0b83c9bf7b..9261e5126b5 100644
--- a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/ya.make
+++ b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ut/ya.make
@@ -9,6 +9,7 @@ PEERDIR(
contrib/libs/jwt-cpp
library/cpp/http/server
library/cpp/json
+ library/cpp/string_utils/base64
)
END()
diff --git a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ya.make b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ya.make
index 7782a8c4fed..e7d74863076 100644
--- a/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ya.make
+++ b/ydb/public/sdk/cpp/client/ydb_types/credentials/oauth2_token_exchange/ya.make
@@ -13,6 +13,7 @@ PEERDIR(
library/cpp/http/simple
library/cpp/json
library/cpp/retry
+ library/cpp/string_utils/base64
library/cpp/uri
ydb/public/sdk/cpp/client/ydb_types
ydb/public/sdk/cpp/client/ydb_types/credentials