json_token_test.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include "src/core/lib/security/credentials/jwt/json_token.h"
  19. #include <string.h>
  20. #include <openssl/evp.h>
  21. #include <grpc/grpc_security.h>
  22. #include <grpc/slice.h>
  23. #include <grpc/support/alloc.h>
  24. #include <grpc/support/log.h>
  25. #include "src/core/lib/json/json.h"
  26. #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
  27. #include "src/core/lib/slice/b64.h"
  28. #include "src/core/lib/slice/slice_internal.h"
  29. #include "test/core/util/test_config.h"
  30. using grpc_core::Json;
  31. /* This JSON key was generated with the GCE console and revoked immediately.
  32. The identifiers have been changed as well.
  33. Maximum size for a string literal is 509 chars in C89, yay! */
  34. static const char test_json_key_str_part1[] =
  35. "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
  36. "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE"
  37. "qg"
  38. "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
  39. "rWBQvS4hle4LfijkP3J5BG+"
  40. "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
  41. "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
  42. "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
  43. "8HpCqFYM9V8f34SBWfD4fRFT+n/"
  44. "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
  45. static const char test_json_key_str_part2[] =
  46. "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
  47. "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
  48. "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA"
  49. "G"
  50. "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz"
  51. "A"
  52. "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
  53. "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
  54. "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ"
  55. "Y"
  56. "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
  57. static const char test_json_key_str_part3[] =
  58. "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
  59. "\"client_email\": "
  60. "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
  61. "com\", \"client_id\": "
  62. "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
  63. "com\", \"type\": \"service_account\" }";
  64. /* Test refresh token. */
  65. static const char test_refresh_token_str[] =
  66. "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
  67. " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
  68. " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
  69. " \"type\": \"authorized_user\"}";
  70. static const char test_scope[] = "myperm1 myperm2";
  71. static const char test_service_url[] = "https://foo.com/foo.v1";
  72. static char* test_json_key_str(const char* bad_part3) {
  73. const char* part3 =
  74. bad_part3 != nullptr ? bad_part3 : test_json_key_str_part3;
  75. size_t result_len = strlen(test_json_key_str_part1) +
  76. strlen(test_json_key_str_part2) + strlen(part3);
  77. char* result = static_cast<char*>(gpr_malloc(result_len + 1));
  78. char* current = result;
  79. strcpy(result, test_json_key_str_part1);
  80. current += strlen(test_json_key_str_part1);
  81. strcpy(current, test_json_key_str_part2);
  82. current += strlen(test_json_key_str_part2);
  83. strcpy(current, part3);
  84. return result;
  85. }
  86. static void test_parse_json_key_success(void) {
  87. char* json_string = test_json_key_str(nullptr);
  88. grpc_auth_json_key json_key =
  89. grpc_auth_json_key_create_from_string(json_string);
  90. GPR_ASSERT(grpc_auth_json_key_is_valid(&json_key));
  91. GPR_ASSERT(json_key.type != nullptr &&
  92. strcmp(json_key.type, "service_account") == 0);
  93. GPR_ASSERT(json_key.private_key_id != nullptr &&
  94. strcmp(json_key.private_key_id,
  95. "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0);
  96. GPR_ASSERT(json_key.client_id != nullptr &&
  97. strcmp(json_key.client_id,
  98. "777-abaslkan11hlb6nmim3bpspl31ud.apps."
  99. "googleusercontent.com") == 0);
  100. GPR_ASSERT(json_key.client_email != nullptr &&
  101. strcmp(json_key.client_email,
  102. "777-abaslkan11hlb6nmim3bpspl31ud@developer."
  103. "gserviceaccount.com") == 0);
  104. GPR_ASSERT(json_key.private_key != nullptr);
  105. gpr_free(json_string);
  106. grpc_auth_json_key_destruct(&json_key);
  107. }
  108. static void test_parse_json_key_failure_bad_json(void) {
  109. const char non_closing_part3[] =
  110. "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
  111. "\"client_email\": "
  112. "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
  113. "com\", \"client_id\": "
  114. "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
  115. "com\", \"type\": \"service_account\" ";
  116. char* json_string = test_json_key_str(non_closing_part3);
  117. grpc_auth_json_key json_key =
  118. grpc_auth_json_key_create_from_string(json_string);
  119. GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key));
  120. gpr_free(json_string);
  121. grpc_auth_json_key_destruct(&json_key);
  122. }
  123. static void test_parse_json_key_failure_no_type(void) {
  124. const char no_type_part3[] =
  125. "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
  126. "\"client_email\": "
  127. "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
  128. "com\", \"client_id\": "
  129. "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
  130. "com\" }";
  131. char* json_string = test_json_key_str(no_type_part3);
  132. grpc_auth_json_key json_key =
  133. grpc_auth_json_key_create_from_string(json_string);
  134. GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key));
  135. gpr_free(json_string);
  136. grpc_auth_json_key_destruct(&json_key);
  137. }
  138. static void test_parse_json_key_failure_no_client_id(void) {
  139. const char no_client_id_part3[] =
  140. "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
  141. "\"client_email\": "
  142. "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
  143. "com\", "
  144. "\"type\": \"service_account\" }";
  145. char* json_string = test_json_key_str(no_client_id_part3);
  146. grpc_auth_json_key json_key =
  147. grpc_auth_json_key_create_from_string(json_string);
  148. GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key));
  149. gpr_free(json_string);
  150. grpc_auth_json_key_destruct(&json_key);
  151. }
  152. static void test_parse_json_key_failure_no_client_email(void) {
  153. const char no_client_email_part3[] =
  154. "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
  155. "\"client_id\": "
  156. "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
  157. "com\", \"type\": \"service_account\" }";
  158. char* json_string = test_json_key_str(no_client_email_part3);
  159. grpc_auth_json_key json_key =
  160. grpc_auth_json_key_create_from_string(json_string);
  161. GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key));
  162. gpr_free(json_string);
  163. grpc_auth_json_key_destruct(&json_key);
  164. }
  165. static void test_parse_json_key_failure_no_private_key_id(void) {
  166. const char no_private_key_id_part3[] =
  167. "\"client_email\": "
  168. "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
  169. "com\", \"client_id\": "
  170. "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
  171. "com\", \"type\": \"service_account\" }";
  172. char* json_string = test_json_key_str(no_private_key_id_part3);
  173. grpc_auth_json_key json_key =
  174. grpc_auth_json_key_create_from_string(json_string);
  175. GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key));
  176. gpr_free(json_string);
  177. grpc_auth_json_key_destruct(&json_key);
  178. }
  179. static void test_parse_json_key_failure_no_private_key(void) {
  180. const char no_private_key_json_string[] =
  181. "{ \"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
  182. "\"client_email\": "
  183. "\"777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount."
  184. "com\", \"client_id\": "
  185. "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
  186. "com\", \"type\": \"service_account\" }";
  187. grpc_auth_json_key json_key =
  188. grpc_auth_json_key_create_from_string(no_private_key_json_string);
  189. GPR_ASSERT(!grpc_auth_json_key_is_valid(&json_key));
  190. grpc_auth_json_key_destruct(&json_key);
  191. }
  192. static Json parse_json_part_from_jwt(const char* str, size_t len) {
  193. grpc_core::ExecCtx exec_ctx;
  194. char* b64 = static_cast<char*>(gpr_malloc(len + 1));
  195. strncpy(b64, str, len);
  196. b64[len] = '\0';
  197. grpc_slice slice = grpc_base64_decode(b64, 1);
  198. gpr_free(b64);
  199. GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(slice));
  200. grpc_error_handle error = GRPC_ERROR_NONE;
  201. absl::string_view string = grpc_core::StringViewFromSlice(slice);
  202. Json json = Json::Parse(string, &error);
  203. if (error != GRPC_ERROR_NONE) {
  204. gpr_log(GPR_ERROR, "JSON parse error: %s",
  205. grpc_error_std_string(error).c_str());
  206. GRPC_ERROR_UNREF(error);
  207. }
  208. grpc_slice_unref(slice);
  209. return json;
  210. }
  211. static void check_jwt_header(const Json& header) {
  212. Json::Object object = header.object_value();
  213. Json value = object["alg"];
  214. GPR_ASSERT(value.type() == Json::Type::STRING);
  215. GPR_ASSERT(strcmp(value.string_value().c_str(), "RS256") == 0);
  216. value = object["typ"];
  217. GPR_ASSERT(value.type() == Json::Type::STRING);
  218. GPR_ASSERT(strcmp(value.string_value().c_str(), "JWT") == 0);
  219. value = object["kid"];
  220. GPR_ASSERT(value.type() == Json::Type::STRING);
  221. GPR_ASSERT(strcmp(value.string_value().c_str(),
  222. "e6b5137873db8d2ef81e06a47289e6434ec8a165") == 0);
  223. }
  224. static void check_jwt_claim(const Json& claim, const char* expected_audience,
  225. const char* expected_scope) {
  226. Json::Object object = claim.object_value();
  227. Json value = object["iss"];
  228. GPR_ASSERT(value.type() == Json::Type::STRING);
  229. GPR_ASSERT(value.string_value() ==
  230. "777-abaslkan11hlb6nmim3bpspl31ud@developer.gserviceaccount.com");
  231. if (expected_scope != nullptr) {
  232. GPR_ASSERT(object.find("sub") == object.end());
  233. value = object["scope"];
  234. GPR_ASSERT(value.type() == Json::Type::STRING);
  235. GPR_ASSERT(value.string_value() == expected_scope);
  236. } else {
  237. /* Claims without scope must have a sub. */
  238. GPR_ASSERT(object.find("scope") == object.end());
  239. value = object["sub"];
  240. GPR_ASSERT(value.type() == Json::Type::STRING);
  241. GPR_ASSERT(value.string_value() == object["iss"].string_value());
  242. }
  243. value = object["aud"];
  244. GPR_ASSERT(value.type() == Json::Type::STRING);
  245. GPR_ASSERT(value.string_value() == expected_audience);
  246. gpr_timespec expiration = gpr_time_0(GPR_CLOCK_REALTIME);
  247. value = object["exp"];
  248. GPR_ASSERT(value.type() == Json::Type::NUMBER);
  249. expiration.tv_sec = strtol(value.string_value().c_str(), nullptr, 10);
  250. gpr_timespec issue_time = gpr_time_0(GPR_CLOCK_REALTIME);
  251. value = object["iat"];
  252. GPR_ASSERT(value.type() == Json::Type::NUMBER);
  253. issue_time.tv_sec = strtol(value.string_value().c_str(), nullptr, 10);
  254. gpr_timespec parsed_lifetime = gpr_time_sub(expiration, issue_time);
  255. GPR_ASSERT(parsed_lifetime.tv_sec == grpc_max_auth_token_lifetime().tv_sec);
  256. }
  257. static void check_jwt_signature(const char* b64_signature, RSA* rsa_key,
  258. const char* signed_data,
  259. size_t signed_data_size) {
  260. grpc_core::ExecCtx exec_ctx;
  261. EVP_MD_CTX* md_ctx = EVP_MD_CTX_create();
  262. EVP_PKEY* key = EVP_PKEY_new();
  263. grpc_slice sig = grpc_base64_decode(b64_signature, 1);
  264. GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(sig));
  265. GPR_ASSERT(GRPC_SLICE_LENGTH(sig) == 128);
  266. GPR_ASSERT(md_ctx != nullptr);
  267. GPR_ASSERT(key != nullptr);
  268. EVP_PKEY_set1_RSA(key, rsa_key);
  269. GPR_ASSERT(
  270. EVP_DigestVerifyInit(md_ctx, nullptr, EVP_sha256(), nullptr, key) == 1);
  271. GPR_ASSERT(EVP_DigestVerifyUpdate(md_ctx, signed_data, signed_data_size) ==
  272. 1);
  273. GPR_ASSERT(EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(sig),
  274. GRPC_SLICE_LENGTH(sig)) == 1);
  275. grpc_slice_unref_internal(sig);
  276. if (key != nullptr) EVP_PKEY_free(key);
  277. if (md_ctx != nullptr) EVP_MD_CTX_destroy(md_ctx);
  278. }
  279. static char* service_account_creds_jwt_encode_and_sign(
  280. const grpc_auth_json_key* key) {
  281. return grpc_jwt_encode_and_sign(key, GRPC_JWT_OAUTH2_AUDIENCE,
  282. grpc_max_auth_token_lifetime(), test_scope);
  283. }
  284. static char* jwt_creds_jwt_encode_and_sign(const grpc_auth_json_key* key) {
  285. return grpc_jwt_encode_and_sign(key, test_service_url,
  286. grpc_max_auth_token_lifetime(), nullptr);
  287. }
  288. static void service_account_creds_check_jwt_claim(const Json& claim) {
  289. check_jwt_claim(claim, GRPC_JWT_OAUTH2_AUDIENCE, test_scope);
  290. }
  291. static void jwt_creds_check_jwt_claim(const Json& claim) {
  292. check_jwt_claim(claim, test_service_url, nullptr);
  293. }
  294. static void test_jwt_encode_and_sign(
  295. char* (*jwt_encode_and_sign_func)(const grpc_auth_json_key*),
  296. void (*check_jwt_claim_func)(const Json&)) {
  297. char* json_string = test_json_key_str(nullptr);
  298. grpc_auth_json_key json_key =
  299. grpc_auth_json_key_create_from_string(json_string);
  300. const char* b64_signature;
  301. size_t offset = 0;
  302. char* jwt = jwt_encode_and_sign_func(&json_key);
  303. const char* dot = strchr(jwt, '.');
  304. GPR_ASSERT(dot != nullptr);
  305. Json parsed_header =
  306. parse_json_part_from_jwt(jwt, static_cast<size_t>(dot - jwt));
  307. GPR_ASSERT(parsed_header.type() == Json::Type::OBJECT);
  308. check_jwt_header(parsed_header);
  309. offset = static_cast<size_t>(dot - jwt) + 1;
  310. dot = strchr(jwt + offset, '.');
  311. GPR_ASSERT(dot != nullptr);
  312. Json parsed_claim = parse_json_part_from_jwt(
  313. jwt + offset, static_cast<size_t>(dot - (jwt + offset)));
  314. GPR_ASSERT(parsed_claim.type() == Json::Type::OBJECT);
  315. check_jwt_claim_func(parsed_claim);
  316. offset = static_cast<size_t>(dot - jwt) + 1;
  317. dot = strchr(jwt + offset, '.');
  318. GPR_ASSERT(dot == nullptr); /* no more part. */
  319. b64_signature = jwt + offset;
  320. check_jwt_signature(b64_signature, json_key.private_key, jwt, offset - 1);
  321. gpr_free(json_string);
  322. grpc_auth_json_key_destruct(&json_key);
  323. gpr_free(jwt);
  324. }
  325. static void test_service_account_creds_jwt_encode_and_sign(void) {
  326. test_jwt_encode_and_sign(service_account_creds_jwt_encode_and_sign,
  327. service_account_creds_check_jwt_claim);
  328. }
  329. static void test_jwt_creds_jwt_encode_and_sign(void) {
  330. test_jwt_encode_and_sign(jwt_creds_jwt_encode_and_sign,
  331. jwt_creds_check_jwt_claim);
  332. }
  333. static void test_parse_refresh_token_success(void) {
  334. grpc_auth_refresh_token refresh_token =
  335. grpc_auth_refresh_token_create_from_string(test_refresh_token_str);
  336. GPR_ASSERT(grpc_auth_refresh_token_is_valid(&refresh_token));
  337. GPR_ASSERT(refresh_token.type != nullptr &&
  338. (strcmp(refresh_token.type, "authorized_user") == 0));
  339. GPR_ASSERT(refresh_token.client_id != nullptr &&
  340. (strcmp(refresh_token.client_id,
  341. "32555999999.apps.googleusercontent.com") == 0));
  342. GPR_ASSERT(
  343. refresh_token.client_secret != nullptr &&
  344. (strcmp(refresh_token.client_secret, "EmssLNjJy1332hD4KFsecret") == 0));
  345. GPR_ASSERT(refresh_token.refresh_token != nullptr &&
  346. (strcmp(refresh_token.refresh_token,
  347. "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42") == 0));
  348. grpc_auth_refresh_token_destruct(&refresh_token);
  349. }
  350. static void test_parse_refresh_token_failure_no_type(void) {
  351. const char refresh_token_str[] =
  352. "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
  353. " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
  354. " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"}";
  355. grpc_auth_refresh_token refresh_token =
  356. grpc_auth_refresh_token_create_from_string(refresh_token_str);
  357. GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
  358. }
  359. static void test_parse_refresh_token_failure_no_client_id(void) {
  360. const char refresh_token_str[] =
  361. "{ \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
  362. " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
  363. " \"type\": \"authorized_user\"}";
  364. grpc_auth_refresh_token refresh_token =
  365. grpc_auth_refresh_token_create_from_string(refresh_token_str);
  366. GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
  367. }
  368. static void test_parse_refresh_token_failure_no_client_secret(void) {
  369. const char refresh_token_str[] =
  370. "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
  371. " \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
  372. " \"type\": \"authorized_user\"}";
  373. grpc_auth_refresh_token refresh_token =
  374. grpc_auth_refresh_token_create_from_string(refresh_token_str);
  375. GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
  376. }
  377. static void test_parse_refresh_token_failure_no_refresh_token(void) {
  378. const char refresh_token_str[] =
  379. "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
  380. " \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
  381. " \"type\": \"authorized_user\"}";
  382. grpc_auth_refresh_token refresh_token =
  383. grpc_auth_refresh_token_create_from_string(refresh_token_str);
  384. GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
  385. }
  386. int main(int argc, char** argv) {
  387. grpc::testing::TestEnvironment env(argc, argv);
  388. grpc_init();
  389. test_parse_json_key_success();
  390. test_parse_json_key_failure_bad_json();
  391. test_parse_json_key_failure_no_type();
  392. test_parse_json_key_failure_no_client_id();
  393. test_parse_json_key_failure_no_client_email();
  394. test_parse_json_key_failure_no_private_key_id();
  395. test_parse_json_key_failure_no_private_key();
  396. test_service_account_creds_jwt_encode_and_sign();
  397. test_jwt_creds_jwt_encode_and_sign();
  398. test_parse_refresh_token_success();
  399. test_parse_refresh_token_failure_no_type();
  400. test_parse_refresh_token_failure_no_client_id();
  401. test_parse_refresh_token_failure_no_client_secret();
  402. test_parse_refresh_token_failure_no_refresh_token();
  403. grpc_shutdown();
  404. return 0;
  405. }