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