Home | History | Annotate | Download | only in security
      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 
     19 #include "src/core/lib/security/credentials/jwt/jwt_verifier.h"
     20 
     21 #include <string.h>
     22 
     23 #include <grpc/grpc.h>
     24 
     25 #include <grpc/slice.h>
     26 #include <grpc/support/alloc.h>
     27 #include <grpc/support/log.h>
     28 #include <grpc/support/string_util.h>
     29 
     30 #include "src/core/lib/http/httpcli.h"
     31 #include "src/core/lib/security/credentials/jwt/json_token.h"
     32 #include "src/core/lib/slice/b64.h"
     33 #include "test/core/util/test_config.h"
     34 
     35 /* This JSON key was generated with the GCE console and revoked immediately.
     36    The identifiers have been changed as well.
     37    Maximum size for a string literal is 509 chars in C89, yay!  */
     38 static const char json_key_str_part1[] =
     39     "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
     40     "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJE"
     41     "qg"
     42     "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
     43     "rWBQvS4hle4LfijkP3J5BG+"
     44     "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
     45     "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
     46     "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
     47     "8HpCqFYM9V8f34SBWfD4fRFT+n/"
     48     "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
     49 static const char json_key_str_part2[] =
     50     "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
     51     "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
     52     "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDA"
     53     "G"
     54     "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6Hz"
     55     "A"
     56     "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
     57     "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
     58     "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZ"
     59     "Y"
     60     "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
     61 static const char json_key_str_part3_for_google_email_issuer[] =
     62     "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
     63     "\"client_email\": "
     64     "\"777-abaslkan11hlb6nmim3bpspl31ud (at) developer.gserviceaccount."
     65     "com\", \"client_id\": "
     66     "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
     67     "com\", \"type\": \"service_account\" }";
     68 /* Trick our JWT library into issuing a JWT with iss=accounts.google.com. */
     69 static const char json_key_str_part3_for_url_issuer[] =
     70     "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
     71     "\"client_email\": \"accounts.google.com\", "
     72     "\"client_id\": "
     73     "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
     74     "com\", \"type\": \"service_account\" }";
     75 static const char json_key_str_part3_for_custom_email_issuer[] =
     76     "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
     77     "\"client_email\": "
     78     "\"foo (at) bar.com\", \"client_id\": "
     79     "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
     80     "com\", \"type\": \"service_account\" }";
     81 
     82 static grpc_jwt_verifier_email_domain_key_url_mapping custom_mapping = {
     83     "bar.com", "keys.bar.com/jwk"};
     84 
     85 static const char expected_user_data[] = "user data";
     86 
     87 static const char good_jwk_set[] =
     88     "{"
     89     " \"keys\": ["
     90     "  {"
     91     "   \"kty\": \"RSA\","
     92     "   \"alg\": \"RS256\","
     93     "   \"use\": \"sig\","
     94     "   \"kid\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\","
     95     "   \"n\": "
     96     "\"4S8myegefIeRdynuYkSqBYaOLDvU19cHKC56RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ6mxP"
     97     "QutZC1nKNJ6D-tYFC9LiGV7gt-KOQ_cnkEb4hcMw_xF_OI1FCx6cBcM0-"
     98     "RjiQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFU=\","
     99     "   \"e\": \"AQAB\""
    100     "  }"
    101     " ]"
    102     "}";
    103 
    104 static gpr_timespec expected_lifetime = {3600, 0, GPR_TIMESPAN};
    105 
    106 static const char good_google_email_keys_part1[] =
    107     "{\"e6b5137873db8d2ef81e06a47289e6434ec8a165\": \"-----BEGIN "
    108     "CERTIFICATE-----"
    109     "\\nMIICATCCAWoCCQDEywLhxvHjnDANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB\\nVTET"
    110     "MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0\\ncyBQdHkgTHR"
    111     "kMB4XDTE1MDYyOTA4Mzk1MFoXDTI1MDYyNjA4Mzk1MFowRTELMAkG\\nA1UEBhMCQVUxEzARBg"
    112     "NVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0\\nIFdpZGdpdHMgUHR5IEx0ZDCBn"
    113     "zANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4S8m\\nyegefIeRdynuYkSqBYaOLDvU19cHKC56"
    114     "RIqGjrkXFoZuydIz1IxACpWTtDasb4jQ\\n6mxPQutZC1nKNJ6D+tYFC9LiGV7gt+KOQ/";
    115 
    116 static const char good_google_email_keys_part2[] =
    117     "cnkEb4hcMw/xF/OI1FCx6cBcM0+"
    118     "Rji\\nQkK8q7HbF0M6dUXo3t0vedNhmD65Cs2wxPP1TFUCAwEAATANBgkqhkiG9w0BAQsF\\nA"
    119     "AOBgQBfu69FkPmBknbKNFgurPz78kbs3VNN+k/"
    120     "PUgO5DHKskJmgK2TbtvX2VMpx\\nkftmHGzgzMzUlOtigCaGMgHWjfqjpP9uuDbahXrZBJzB8c"
    121     "Oq7MrQF8r17qVvo3Ue\\nPjTKQMAsU8uxTEMmeuz9L6yExs0rfd6bPOrQkAoVfFfiYB3/"
    122     "pA==\\n-----END CERTIFICATE-----\\n\"}";
    123 
    124 static const char expected_audience[] = "https://foo.com";
    125 
    126 static const char good_openid_config[] =
    127     "{"
    128     " \"issuer\": \"https://accounts.google.com\","
    129     " \"authorization_endpoint\": "
    130     "\"https://accounts.google.com/o/oauth2/v2/auth\","
    131     " \"token_endpoint\": \"https://www.googleapis.com/oauth2/v4/token\","
    132     " \"userinfo_endpoint\": \"https://www.googleapis.com/oauth2/v3/userinfo\","
    133     " \"revocation_endpoint\": \"https://accounts.google.com/o/oauth2/revoke\","
    134     " \"jwks_uri\": \"https://www.googleapis.com/oauth2/v3/certs\""
    135     "}";
    136 
    137 static const char expired_claims[] =
    138     "{ \"aud\": \"https://foo.com\","
    139     "  \"iss\": \"blah.foo.com\","
    140     "  \"sub\": \"juju (at) blah.foo.com\","
    141     "  \"jti\": \"jwtuniqueid\","
    142     "  \"iat\": 100," /* Way back in the past... */
    143     "  \"exp\": 120,"
    144     "  \"nbf\": 60,"
    145     "  \"foo\": \"bar\"}";
    146 
    147 static const char claims_without_time_constraint[] =
    148     "{ \"aud\": \"https://foo.com\","
    149     "  \"iss\": \"blah.foo.com\","
    150     "  \"sub\": \"juju (at) blah.foo.com\","
    151     "  \"jti\": \"jwtuniqueid\","
    152     "  \"foo\": \"bar\"}";
    153 
    154 static const char claims_with_bad_subject[] =
    155     "{ \"aud\": \"https://foo.com\","
    156     "  \"iss\": \"evil (at) blah.foo.com\","
    157     "  \"sub\": \"juju (at) blah.foo.com\","
    158     "  \"jti\": \"jwtuniqueid\","
    159     "  \"foo\": \"bar\"}";
    160 
    161 static const char invalid_claims[] =
    162     "{ \"aud\": \"https://foo.com\","
    163     "  \"iss\": 46," /* Issuer cannot be a number. */
    164     "  \"sub\": \"juju (at) blah.foo.com\","
    165     "  \"jti\": \"jwtuniqueid\","
    166     "  \"foo\": \"bar\"}";
    167 
    168 typedef struct {
    169   grpc_jwt_verifier_status expected_status;
    170   const char* expected_issuer;
    171   const char* expected_subject;
    172 } verifier_test_config;
    173 
    174 static void test_jwt_issuer_email_domain(void) {
    175   const char* d = grpc_jwt_issuer_email_domain("https://foo.com");
    176   GPR_ASSERT(d == nullptr);
    177   d = grpc_jwt_issuer_email_domain("foo.com");
    178   GPR_ASSERT(d == nullptr);
    179   d = grpc_jwt_issuer_email_domain("");
    180   GPR_ASSERT(d == nullptr);
    181   d = grpc_jwt_issuer_email_domain("@");
    182   GPR_ASSERT(d == nullptr);
    183   d = grpc_jwt_issuer_email_domain("bar@foo");
    184   GPR_ASSERT(strcmp(d, "foo") == 0);
    185   d = grpc_jwt_issuer_email_domain("bar (at) foo.com");
    186   GPR_ASSERT(strcmp(d, "foo.com") == 0);
    187   d = grpc_jwt_issuer_email_domain("bar (at) blah.foo.com");
    188   GPR_ASSERT(strcmp(d, "foo.com") == 0);
    189   d = grpc_jwt_issuer_email_domain("bar.blah (at) blah.foo.com");
    190   GPR_ASSERT(strcmp(d, "foo.com") == 0);
    191   d = grpc_jwt_issuer_email_domain("bar.blah (at) baz.blah.foo.com");
    192   GPR_ASSERT(strcmp(d, "foo.com") == 0);
    193 
    194   /* This is not a very good parser but make sure we do not crash on these weird
    195      inputs. */
    196   d = grpc_jwt_issuer_email_domain("@foo");
    197   GPR_ASSERT(strcmp(d, "foo") == 0);
    198   d = grpc_jwt_issuer_email_domain("bar@.");
    199   GPR_ASSERT(d != nullptr);
    200   d = grpc_jwt_issuer_email_domain("bar@..");
    201   GPR_ASSERT(d != nullptr);
    202   d = grpc_jwt_issuer_email_domain("bar (at) ...");
    203   GPR_ASSERT(d != nullptr);
    204 }
    205 
    206 static void test_claims_success(void) {
    207   grpc_jwt_claims* claims;
    208   grpc_slice s = grpc_slice_from_copied_string(claims_without_time_constraint);
    209   grpc_json* json = grpc_json_parse_string_with_len(
    210       reinterpret_cast<char*> GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s));
    211   GPR_ASSERT(json != nullptr);
    212   grpc_core::ExecCtx exec_ctx;
    213   claims = grpc_jwt_claims_from_json(json, s);
    214   GPR_ASSERT(claims != nullptr);
    215   GPR_ASSERT(grpc_jwt_claims_json(claims) == json);
    216   GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0);
    217   GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0);
    218   GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju (at) blah.foo.com") == 0);
    219   GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0);
    220   GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") ==
    221              GRPC_JWT_VERIFIER_OK);
    222   grpc_jwt_claims_destroy(claims);
    223 }
    224 
    225 static void test_expired_claims_failure(void) {
    226   grpc_jwt_claims* claims;
    227   grpc_slice s = grpc_slice_from_copied_string(expired_claims);
    228   grpc_json* json = grpc_json_parse_string_with_len(
    229       reinterpret_cast<char*> GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s));
    230   gpr_timespec exp_iat = {100, 0, GPR_CLOCK_REALTIME};
    231   gpr_timespec exp_exp = {120, 0, GPR_CLOCK_REALTIME};
    232   gpr_timespec exp_nbf = {60, 0, GPR_CLOCK_REALTIME};
    233   GPR_ASSERT(json != nullptr);
    234   grpc_core::ExecCtx exec_ctx;
    235   claims = grpc_jwt_claims_from_json(json, s);
    236   GPR_ASSERT(claims != nullptr);
    237   GPR_ASSERT(grpc_jwt_claims_json(claims) == json);
    238   GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), "https://foo.com") == 0);
    239   GPR_ASSERT(strcmp(grpc_jwt_claims_issuer(claims), "blah.foo.com") == 0);
    240   GPR_ASSERT(strcmp(grpc_jwt_claims_subject(claims), "juju (at) blah.foo.com") == 0);
    241   GPR_ASSERT(strcmp(grpc_jwt_claims_id(claims), "jwtuniqueid") == 0);
    242   GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_issued_at(claims), exp_iat) == 0);
    243   GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_expires_at(claims), exp_exp) == 0);
    244   GPR_ASSERT(gpr_time_cmp(grpc_jwt_claims_not_before(claims), exp_nbf) == 0);
    245 
    246   GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") ==
    247              GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE);
    248   grpc_jwt_claims_destroy(claims);
    249 }
    250 
    251 static void test_invalid_claims_failure(void) {
    252   grpc_slice s = grpc_slice_from_copied_string(invalid_claims);
    253   grpc_json* json = grpc_json_parse_string_with_len(
    254       reinterpret_cast<char*> GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s));
    255   grpc_core::ExecCtx exec_ctx;
    256   GPR_ASSERT(grpc_jwt_claims_from_json(json, s) == nullptr);
    257 }
    258 
    259 static void test_bad_audience_claims_failure(void) {
    260   grpc_jwt_claims* claims;
    261   grpc_slice s = grpc_slice_from_copied_string(claims_without_time_constraint);
    262   grpc_json* json = grpc_json_parse_string_with_len(
    263       reinterpret_cast<char*> GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s));
    264   GPR_ASSERT(json != nullptr);
    265   grpc_core::ExecCtx exec_ctx;
    266   claims = grpc_jwt_claims_from_json(json, s);
    267   GPR_ASSERT(claims != nullptr);
    268   GPR_ASSERT(grpc_jwt_claims_check(claims, "https://bar.com") ==
    269              GRPC_JWT_VERIFIER_BAD_AUDIENCE);
    270   grpc_jwt_claims_destroy(claims);
    271 }
    272 
    273 static void test_bad_subject_claims_failure(void) {
    274   grpc_jwt_claims* claims;
    275   grpc_slice s = grpc_slice_from_copied_string(claims_with_bad_subject);
    276   grpc_json* json = grpc_json_parse_string_with_len(
    277       reinterpret_cast<char*> GRPC_SLICE_START_PTR(s), GRPC_SLICE_LENGTH(s));
    278   GPR_ASSERT(json != nullptr);
    279   grpc_core::ExecCtx exec_ctx;
    280   claims = grpc_jwt_claims_from_json(json, s);
    281   GPR_ASSERT(claims != nullptr);
    282   GPR_ASSERT(grpc_jwt_claims_check(claims, "https://foo.com") ==
    283              GRPC_JWT_VERIFIER_BAD_SUBJECT);
    284   grpc_jwt_claims_destroy(claims);
    285 }
    286 
    287 static char* json_key_str(const char* last_part) {
    288   size_t result_len = strlen(json_key_str_part1) + strlen(json_key_str_part2) +
    289                       strlen(last_part);
    290   char* result = static_cast<char*>(gpr_malloc(result_len + 1));
    291   char* current = result;
    292   strcpy(result, json_key_str_part1);
    293   current += strlen(json_key_str_part1);
    294   strcpy(current, json_key_str_part2);
    295   current += strlen(json_key_str_part2);
    296   strcpy(current, last_part);
    297   return result;
    298 }
    299 
    300 static char* good_google_email_keys(void) {
    301   size_t result_len = strlen(good_google_email_keys_part1) +
    302                       strlen(good_google_email_keys_part2);
    303   char* result = static_cast<char*>(gpr_malloc(result_len + 1));
    304   char* current = result;
    305   strcpy(result, good_google_email_keys_part1);
    306   current += strlen(good_google_email_keys_part1);
    307   strcpy(current, good_google_email_keys_part2);
    308   return result;
    309 }
    310 
    311 static grpc_httpcli_response http_response(int status, char* body) {
    312   grpc_httpcli_response response;
    313   memset(&response, 0, sizeof(grpc_httpcli_response));
    314   response.status = status;
    315   response.body = body;
    316   response.body_length = strlen(body);
    317   return response;
    318 }
    319 
    320 static int httpcli_post_should_not_be_called(
    321     const grpc_httpcli_request* request, const char* body_bytes,
    322     size_t body_size, grpc_millis deadline, grpc_closure* on_done,
    323     grpc_httpcli_response* response) {
    324   GPR_ASSERT("HTTP POST should not be called" == nullptr);
    325   return 1;
    326 }
    327 
    328 static int httpcli_get_google_keys_for_email(
    329     const grpc_httpcli_request* request, grpc_millis deadline,
    330     grpc_closure* on_done, grpc_httpcli_response* response) {
    331   *response = http_response(200, good_google_email_keys());
    332   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
    333   GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
    334   GPR_ASSERT(strcmp(request->http.path,
    335                     "/robot/v1/metadata/x509/"
    336                     "777-abaslkan11hlb6nmim3bpspl31ud@developer."
    337                     "gserviceaccount.com") == 0);
    338   GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
    339   return 1;
    340 }
    341 
    342 static void on_verification_success(void* user_data,
    343                                     grpc_jwt_verifier_status status,
    344                                     grpc_jwt_claims* claims) {
    345   GPR_ASSERT(status == GRPC_JWT_VERIFIER_OK);
    346   GPR_ASSERT(claims != nullptr);
    347   GPR_ASSERT(user_data == (void*)expected_user_data);
    348   GPR_ASSERT(strcmp(grpc_jwt_claims_audience(claims), expected_audience) == 0);
    349   grpc_jwt_claims_destroy(claims);
    350 }
    351 
    352 static void test_jwt_verifier_google_email_issuer_success(void) {
    353   grpc_core::ExecCtx exec_ctx;
    354   grpc_jwt_verifier* verifier = grpc_jwt_verifier_create(nullptr, 0);
    355   char* jwt = nullptr;
    356   char* key_str = json_key_str(json_key_str_part3_for_google_email_issuer);
    357   grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
    358   gpr_free(key_str);
    359   GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
    360   grpc_httpcli_set_override(httpcli_get_google_keys_for_email,
    361                             httpcli_post_should_not_be_called);
    362   jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime,
    363                                  nullptr);
    364   grpc_auth_json_key_destruct(&key);
    365   GPR_ASSERT(jwt != nullptr);
    366   grpc_jwt_verifier_verify(verifier, nullptr, jwt, expected_audience,
    367                            on_verification_success, (void*)expected_user_data);
    368   grpc_jwt_verifier_destroy(verifier);
    369   grpc_core::ExecCtx::Get()->Flush();
    370   gpr_free(jwt);
    371   grpc_httpcli_set_override(nullptr, nullptr);
    372 }
    373 
    374 static int httpcli_get_custom_keys_for_email(
    375     const grpc_httpcli_request* request, grpc_millis deadline,
    376     grpc_closure* on_done, grpc_httpcli_response* response) {
    377   *response = http_response(200, gpr_strdup(good_jwk_set));
    378   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
    379   GPR_ASSERT(strcmp(request->host, "keys.bar.com") == 0);
    380   GPR_ASSERT(strcmp(request->http.path, "/jwk/foo@bar.com") == 0);
    381   GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
    382   return 1;
    383 }
    384 
    385 static void test_jwt_verifier_custom_email_issuer_success(void) {
    386   grpc_core::ExecCtx exec_ctx;
    387   grpc_jwt_verifier* verifier = grpc_jwt_verifier_create(&custom_mapping, 1);
    388   char* jwt = nullptr;
    389   char* key_str = json_key_str(json_key_str_part3_for_custom_email_issuer);
    390   grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
    391   gpr_free(key_str);
    392   GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
    393   grpc_httpcli_set_override(httpcli_get_custom_keys_for_email,
    394                             httpcli_post_should_not_be_called);
    395   jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime,
    396                                  nullptr);
    397   grpc_auth_json_key_destruct(&key);
    398   GPR_ASSERT(jwt != nullptr);
    399   grpc_jwt_verifier_verify(verifier, nullptr, jwt, expected_audience,
    400                            on_verification_success, (void*)expected_user_data);
    401   grpc_jwt_verifier_destroy(verifier);
    402   grpc_core::ExecCtx::Get()->Flush();
    403   gpr_free(jwt);
    404   grpc_httpcli_set_override(nullptr, nullptr);
    405 }
    406 
    407 static int httpcli_get_jwk_set(const grpc_httpcli_request* request,
    408                                grpc_millis deadline, grpc_closure* on_done,
    409                                grpc_httpcli_response* response) {
    410   *response = http_response(200, gpr_strdup(good_jwk_set));
    411   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
    412   GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
    413   GPR_ASSERT(strcmp(request->http.path, "/oauth2/v3/certs") == 0);
    414   GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
    415   return 1;
    416 }
    417 
    418 static int httpcli_get_openid_config(const grpc_httpcli_request* request,
    419                                      grpc_millis deadline,
    420                                      grpc_closure* on_done,
    421                                      grpc_httpcli_response* response) {
    422   *response = http_response(200, gpr_strdup(good_openid_config));
    423   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
    424   GPR_ASSERT(strcmp(request->host, "accounts.google.com") == 0);
    425   GPR_ASSERT(strcmp(request->http.path, GRPC_OPENID_CONFIG_URL_SUFFIX) == 0);
    426   grpc_httpcli_set_override(httpcli_get_jwk_set,
    427                             httpcli_post_should_not_be_called);
    428   GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
    429   return 1;
    430 }
    431 
    432 static void test_jwt_verifier_url_issuer_success(void) {
    433   grpc_core::ExecCtx exec_ctx;
    434   grpc_jwt_verifier* verifier = grpc_jwt_verifier_create(nullptr, 0);
    435   char* jwt = nullptr;
    436   char* key_str = json_key_str(json_key_str_part3_for_url_issuer);
    437   grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
    438   gpr_free(key_str);
    439   GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
    440   grpc_httpcli_set_override(httpcli_get_openid_config,
    441                             httpcli_post_should_not_be_called);
    442   jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime,
    443                                  nullptr);
    444   grpc_auth_json_key_destruct(&key);
    445   GPR_ASSERT(jwt != nullptr);
    446   grpc_jwt_verifier_verify(verifier, nullptr, jwt, expected_audience,
    447                            on_verification_success, (void*)expected_user_data);
    448   grpc_jwt_verifier_destroy(verifier);
    449   grpc_core::ExecCtx::Get()->Flush();
    450   gpr_free(jwt);
    451   grpc_httpcli_set_override(nullptr, nullptr);
    452 }
    453 
    454 static void on_verification_key_retrieval_error(void* user_data,
    455                                                 grpc_jwt_verifier_status status,
    456                                                 grpc_jwt_claims* claims) {
    457   GPR_ASSERT(status == GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR);
    458   GPR_ASSERT(claims == nullptr);
    459   GPR_ASSERT(user_data == (void*)expected_user_data);
    460 }
    461 
    462 static int httpcli_get_bad_json(const grpc_httpcli_request* request,
    463                                 grpc_millis deadline, grpc_closure* on_done,
    464                                 grpc_httpcli_response* response) {
    465   *response = http_response(200, gpr_strdup("{\"bad\": \"stuff\"}"));
    466   GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl);
    467   GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
    468   return 1;
    469 }
    470 
    471 static void test_jwt_verifier_url_issuer_bad_config(void) {
    472   grpc_core::ExecCtx exec_ctx;
    473   grpc_jwt_verifier* verifier = grpc_jwt_verifier_create(nullptr, 0);
    474   char* jwt = nullptr;
    475   char* key_str = json_key_str(json_key_str_part3_for_url_issuer);
    476   grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
    477   gpr_free(key_str);
    478   GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
    479   grpc_httpcli_set_override(httpcli_get_bad_json,
    480                             httpcli_post_should_not_be_called);
    481   jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime,
    482                                  nullptr);
    483   grpc_auth_json_key_destruct(&key);
    484   GPR_ASSERT(jwt != nullptr);
    485   grpc_jwt_verifier_verify(verifier, nullptr, jwt, expected_audience,
    486                            on_verification_key_retrieval_error,
    487                            (void*)expected_user_data);
    488   grpc_jwt_verifier_destroy(verifier);
    489   grpc_core::ExecCtx::Get()->Flush();
    490   gpr_free(jwt);
    491   grpc_httpcli_set_override(nullptr, nullptr);
    492 }
    493 
    494 static void test_jwt_verifier_bad_json_key(void) {
    495   grpc_core::ExecCtx exec_ctx;
    496   grpc_jwt_verifier* verifier = grpc_jwt_verifier_create(nullptr, 0);
    497   char* jwt = nullptr;
    498   char* key_str = json_key_str(json_key_str_part3_for_google_email_issuer);
    499   grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
    500   gpr_free(key_str);
    501   GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
    502   grpc_httpcli_set_override(httpcli_get_bad_json,
    503                             httpcli_post_should_not_be_called);
    504   jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime,
    505                                  nullptr);
    506   grpc_auth_json_key_destruct(&key);
    507   GPR_ASSERT(jwt != nullptr);
    508   grpc_jwt_verifier_verify(verifier, nullptr, jwt, expected_audience,
    509                            on_verification_key_retrieval_error,
    510                            (void*)expected_user_data);
    511   grpc_jwt_verifier_destroy(verifier);
    512   grpc_core::ExecCtx::Get()->Flush();
    513   gpr_free(jwt);
    514   grpc_httpcli_set_override(nullptr, nullptr);
    515 }
    516 
    517 static void corrupt_jwt_sig(char* jwt) {
    518   grpc_slice sig;
    519   char* bad_b64_sig;
    520   uint8_t* sig_bytes;
    521   char* last_dot = strrchr(jwt, '.');
    522   GPR_ASSERT(last_dot != nullptr);
    523   {
    524     grpc_core::ExecCtx exec_ctx;
    525     sig = grpc_base64_decode(last_dot + 1, 1);
    526   }
    527   GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(sig));
    528   sig_bytes = GRPC_SLICE_START_PTR(sig);
    529   (*sig_bytes)++; /* Corrupt first byte. */
    530   bad_b64_sig = grpc_base64_encode(GRPC_SLICE_START_PTR(sig),
    531                                    GRPC_SLICE_LENGTH(sig), 1, 0);
    532   memcpy(last_dot + 1, bad_b64_sig, strlen(bad_b64_sig));
    533   gpr_free(bad_b64_sig);
    534   grpc_slice_unref(sig);
    535 }
    536 
    537 static void on_verification_bad_signature(void* user_data,
    538                                           grpc_jwt_verifier_status status,
    539                                           grpc_jwt_claims* claims) {
    540   GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_SIGNATURE);
    541   GPR_ASSERT(claims == nullptr);
    542   GPR_ASSERT(user_data == (void*)expected_user_data);
    543 }
    544 
    545 static void test_jwt_verifier_bad_signature(void) {
    546   grpc_core::ExecCtx exec_ctx;
    547   grpc_jwt_verifier* verifier = grpc_jwt_verifier_create(nullptr, 0);
    548   char* jwt = nullptr;
    549   char* key_str = json_key_str(json_key_str_part3_for_url_issuer);
    550   grpc_auth_json_key key = grpc_auth_json_key_create_from_string(key_str);
    551   gpr_free(key_str);
    552   GPR_ASSERT(grpc_auth_json_key_is_valid(&key));
    553   grpc_httpcli_set_override(httpcli_get_openid_config,
    554                             httpcli_post_should_not_be_called);
    555   jwt = grpc_jwt_encode_and_sign(&key, expected_audience, expected_lifetime,
    556                                  nullptr);
    557   grpc_auth_json_key_destruct(&key);
    558   corrupt_jwt_sig(jwt);
    559   GPR_ASSERT(jwt != nullptr);
    560   grpc_jwt_verifier_verify(verifier, nullptr, jwt, expected_audience,
    561                            on_verification_bad_signature,
    562                            (void*)expected_user_data);
    563   gpr_free(jwt);
    564   grpc_jwt_verifier_destroy(verifier);
    565   grpc_core::ExecCtx::Get()->Flush();
    566   grpc_httpcli_set_override(nullptr, nullptr);
    567 }
    568 
    569 static int httpcli_get_should_not_be_called(const grpc_httpcli_request* request,
    570                                             grpc_millis deadline,
    571                                             grpc_closure* on_done,
    572                                             grpc_httpcli_response* response) {
    573   GPR_ASSERT(0);
    574   return 1;
    575 }
    576 
    577 static void on_verification_bad_format(void* user_data,
    578                                        grpc_jwt_verifier_status status,
    579                                        grpc_jwt_claims* claims) {
    580   GPR_ASSERT(status == GRPC_JWT_VERIFIER_BAD_FORMAT);
    581   GPR_ASSERT(claims == nullptr);
    582   GPR_ASSERT(user_data == (void*)expected_user_data);
    583 }
    584 
    585 static void test_jwt_verifier_bad_format(void) {
    586   grpc_core::ExecCtx exec_ctx;
    587   grpc_jwt_verifier* verifier = grpc_jwt_verifier_create(nullptr, 0);
    588   grpc_httpcli_set_override(httpcli_get_should_not_be_called,
    589                             httpcli_post_should_not_be_called);
    590   grpc_jwt_verifier_verify(verifier, nullptr, "bad jwt", expected_audience,
    591                            on_verification_bad_format,
    592                            (void*)expected_user_data);
    593   grpc_jwt_verifier_destroy(verifier);
    594   grpc_core::ExecCtx::Get()->Flush();
    595   grpc_httpcli_set_override(nullptr, nullptr);
    596 }
    597 
    598 /* find verification key: bad jks, cannot find key in jks */
    599 /* bad signature custom provided email*/
    600 /* bad key */
    601 
    602 int main(int argc, char** argv) {
    603   grpc_test_init(argc, argv);
    604   grpc_init();
    605   test_jwt_issuer_email_domain();
    606   test_claims_success();
    607   test_expired_claims_failure();
    608   test_invalid_claims_failure();
    609   test_bad_audience_claims_failure();
    610   test_bad_subject_claims_failure();
    611   test_jwt_verifier_google_email_issuer_success();
    612   test_jwt_verifier_custom_email_issuer_success();
    613   test_jwt_verifier_url_issuer_success();
    614   test_jwt_verifier_url_issuer_bad_config();
    615   test_jwt_verifier_bad_json_key();
    616   test_jwt_verifier_bad_signature();
    617   test_jwt_verifier_bad_format();
    618   grpc_shutdown();
    619   return 0;
    620 }
    621