Go to the documentation of this file.
41 #include "absl/status/statusor.h"
42 #include "absl/strings/string_view.h"
79 return "BAD_SIGNATURE";
83 return "BAD_AUDIENCE";
85 return "KEY_RETRIEVAL_ERROR";
87 return "TIME_CONSTRAINT_FAILURE";
89 return "GENERIC_ERROR";
96 if (strcmp(alg,
"RS256") == 0) {
98 }
else if (strcmp(alg,
"RS384") == 0) {
100 }
else if (strcmp(alg,
"RS512") == 0) {
127 if (json.
type() != Json::Type::STRING) {
136 if (json.
type() != Json::Type::NUMBER) {
159 const char* alg_value;
160 Json::Object::const_iterator
it;
162 if (json.
type() != Json::Type::OBJECT) {
176 alg_value =
it->second.string_value().c_str();
177 if (
it->second.type() != Json::Type::STRING ||
178 strncmp(alg_value,
"RS", 2) != 0 ||
188 if (h->typ ==
nullptr)
goto error;
194 if (h->kid ==
nullptr)
goto error;
225 if (claims ==
nullptr)
return nullptr;
230 if (claims ==
nullptr)
return nullptr;
235 if (claims ==
nullptr)
return nullptr;
240 if (claims ==
nullptr)
return nullptr;
245 if (claims ==
nullptr)
return nullptr;
273 if (
p.first ==
"sub") {
275 if (claims->
sub ==
nullptr)
goto error;
276 }
else if (
p.first ==
"iss") {
278 if (claims->
iss ==
nullptr)
goto error;
279 }
else if (
p.first ==
"aud") {
281 if (claims->
aud ==
nullptr)
goto error;
282 }
else if (
p.first ==
"jti") {
284 if (claims->
jti ==
nullptr)
goto error;
285 }
else if (
p.first ==
"iat") {
290 }
else if (
p.first ==
"exp") {
295 }
else if (
p.first ==
"nbf") {
310 const char* audience) {
333 claims->
sub !=
nullptr && strcmp(claims->
iss, claims->
sub) != 0) {
335 "Email issuer (%s) cannot assert another subject (%s) than itself.",
336 claims->
iss, claims->
sub);
340 if (audience ==
nullptr) {
341 audience_ok = claims->
aud ==
nullptr;
343 audience_ok = claims->
aud !=
nullptr && strcmp(audience, claims->
aud) == 0;
347 audience ==
nullptr ?
"NULL" : audience,
348 claims->
aud ==
nullptr ?
"NULL" : claims->
aud);
379 const char* signed_jwt,
size_t signed_jwt_len,
void* user_data,
388 ctx->claims = claims;
389 ctx->signature = signature;
391 ctx->user_data = user_data;
457 X509* x509 =
nullptr;
460 size_t len = strlen(x509_str);
464 if (x509 ==
nullptr) {
483 if (b64 ==
nullptr)
return nullptr;
495 #if OPENSSL_VERSION_NUMBER < 0x10100000L
503 if ((
r->n ==
nullptr &&
n ==
nullptr) || (
r->e ==
nullptr && e ==
nullptr)) {
522 #endif // OPENSSL_VERSION_NUMBER < 0x10100000L
529 Json::Object::const_iterator
it;
533 if (strcmp(kty,
"RSA") != 0) {
538 if (rsa ==
nullptr) {
548 if (tmp_n ==
nullptr)
goto end;
555 if (tmp_e ==
nullptr)
goto end;
574 const char* header_kid) {
578 if (jwt_keys ==
nullptr) {
582 if (
cur ==
nullptr)
return nullptr;
585 if (jwt_keys->
type() != Json::Type::ARRAY) {
587 "Unexpected value type of keys property in jwks key set.");
593 if (jkey.type() != Json::Type::OBJECT)
continue;
594 const char* alg =
nullptr;
595 auto it = jkey.object_value().find(
"alg");
596 if (
it != jkey.object_value().end()) {
599 const char* kid =
nullptr;
600 it = jkey.object_value().find(
"kid");
601 if (
it != jkey.object_value().end()) {
604 const char* kty =
nullptr;
605 it = jkey.object_value().find(
"kty");
606 if (
it != jkey.object_value().end()) {
609 if (alg !=
nullptr && kid !=
nullptr && kty !=
nullptr &&
610 strcmp(kid, header_kid) == 0 && strcmp(alg, header_alg) == 0) {
615 "Could not find matching key in key set for kid=%s and alg=%s",
616 header_kid, header_alg);
628 if (md_ctx ==
nullptr) {
656 EVP_PKEY* verification_key =
nullptr;
660 if (json.
type() == Json::Type::JSON_NULL) {
666 if (verification_key ==
nullptr) {
682 claims =
ctx->claims;
683 ctx->claims =
nullptr;
699 const char* jwks_uri;
706 if (json.
type() == Json::Type::JSON_NULL)
goto error;
708 if (
cur ==
nullptr) {
713 if (jwks_uri ==
nullptr)
goto error;
714 if (strstr(jwks_uri,
"https://") != jwks_uri) {
720 path =
const_cast<char*
>(strchr(jwks_uri,
'/'));
721 if (
path ==
nullptr) {
722 path =
const_cast<char*
>(
"");
724 *(host + (
path - jwks_uri)) =
'\0';
741 ctx->http_request->Start();
751 const char* email_domain) {
753 if (
v->mappings ==
nullptr)
return nullptr;
754 for (
i = 0;
i <
v->num_mappings;
i++) {
755 if (strcmp(email_domain,
v->mappings[
i].email_domain) == 0) {
756 return &
v->mappings[
i];
763 const char* key_url_prefix) {
766 if (mapping !=
nullptr) {
771 v->mappings[
v->num_mappings].email_domain =
gpr_strdup(email_domain);
772 v->mappings[
v->num_mappings].key_url_prefix =
gpr_strdup(key_url_prefix);
780 const char* at_sign = strchr(issuer,
'@');
781 if (at_sign ==
nullptr)
return nullptr;
782 const char* email_domain = at_sign + 1;
783 if (*email_domain ==
'\0')
return nullptr;
784 const char* dot = strrchr(email_domain,
'.');
785 if (dot ==
nullptr || dot == email_domain)
return email_domain;
788 dot =
static_cast<const char*
>(
789 gpr_memrchr(email_domain,
'.',
static_cast<size_t>(dot - email_domain)));
790 if (dot ==
nullptr)
return email_domain;
796 const char* email_domain;
798 char* path_prefix =
nullptr;
808 ctx->claims !=
nullptr);
809 iss =
ctx->claims->iss;
810 if (
ctx->header->kid ==
nullptr) {
814 if (iss ==
nullptr) {
825 if (email_domain !=
nullptr) {
829 if (mapping ==
nullptr) {
834 path_prefix = strchr(host,
'/');
835 if (path_prefix ==
nullptr) {
838 *(path_prefix++) =
'\0';
845 host =
gpr_strdup(strstr(iss,
"https://") == iss ? iss + 8 : iss);
846 path_prefix = strchr(host,
'/');
847 if (path_prefix ==
nullptr) {
850 *(path_prefix++) = 0;
854 grpc_schedule_on_exec_ctx);
870 ctx->http_request->Start();
882 const char* audience,
885 const char* dot =
nullptr;
889 size_t signed_jwt_len;
890 const char*
cur = jwt;
895 dot = strchr(
cur,
'.');
896 if (dot ==
nullptr)
goto error;
898 if (json.
type() == Json::Type::JSON_NULL)
goto error;
903 dot = strchr(
cur,
'.');
904 if (dot ==
nullptr)
goto error;
906 if (json.
type() == Json::Type::JSON_NULL)
goto error;
908 if (claims ==
nullptr)
goto error;
910 signed_jwt_len =
static_cast<size_t>(dot - jwt);
916 signature, jwt, signed_jwt_len, user_data,
cb));
927 size_t num_mappings) {
931 v->allocated_mappings = 1 + num_mappings;
937 if (mappings !=
nullptr) {
939 for (
i = 0;
i < num_mappings;
i++) {
941 mappings[
i].key_url_prefix);
949 if (
v ==
nullptr)
return;
950 if (
v->mappings !=
nullptr) {
951 for (
i = 0;
i <
v->num_mappings;
i++) {
const char * grpc_jwt_claims_issuer(const grpc_jwt_claims *claims)
@ GRPC_JWT_VERIFIER_TIME_CONSTRAINT_FAILURE
void grpc_jwt_verifier_verify(grpc_jwt_verifier *verifier, grpc_pollset *pollset, const char *jwt, const char *audience, grpc_jwt_verification_done_cb cb, void *user_data)
const OPENSSL_EXPORT EVP_MD * EVP_sha512(void)
gpr_timespec grpc_jwt_verifier_clock_skew
#define EVP_DigestVerifyInit
return memset(p, 0, total)
static gpr_timespec validate_time_field(const Json &json, const char *key)
@ GRPC_JWT_VERIFIER_BAD_SIGNATURE
GPRAPI gpr_timespec gpr_time_0(gpr_clock_type type)
const OPENSSL_EXPORT EVP_MD * EVP_sha384(void)
#define TSI_SIZE_AS_SIZE(x)
static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
absl::string_view StringViewFromSlice(const grpc_slice &slice)
GPRAPI void gpr_free(void *ptr)
static EVP_PKEY * pkey_from_jwk(const Json &json, const char *kty)
@ GRPC_JWT_VERIFIER_BAD_SUBJECT
static const Json * find_property_by_name(const Json &json, const char *name)
const Object & object_value() const
GPRAPI void * gpr_malloc(size_t size)
gpr_timespec grpc_jwt_claims_expires_at(const grpc_jwt_claims *claims)
#define EVP_DigestVerifyUpdate
void(* grpc_jwt_verification_done_cb)(void *user_data, grpc_jwt_verifier_status status, grpc_jwt_claims *claims)
GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type)
const char * grpc_jwt_claims_subject(const grpc_jwt_claims *claims)
static struct test_ctx ctx
grpc_polling_entity pollent
#define GRPC_CLOSURE_CREATE(cb, cb_arg, scheduler)
RefCountedPtr< grpc_channel_credentials > CreateHttpRequestSSLCredentials()
grpc_core::ManualConstructor< Json > json
const OPENSSL_EXPORT EVP_MD * EVP_sha256(void)
static void verifier(grpc_server *server, grpc_completion_queue *cq, void *)
const char * grpc_jwt_claims_id(const grpc_jwt_claims *claims)
const char * grpc_jwt_verifier_status_to_string(grpc_jwt_verifier_status status)
void grpc_jwt_claims_destroy(grpc_jwt_claims *claims)
static EVP_PKEY * extract_pkey_from_x509(const char *x509_str)
static email_key_mapping * verifier_get_mapping(grpc_jwt_verifier *v, const char *email_domain)
const char * grpc_jwt_issuer_email_domain(const char *issuer)
static const EVP_MD * evp_md_from_alg(const char *alg)
grpc_slice grpc_base64_decode_with_len(const char *b64, size_t b64_len, int url_safe)
const Array & array_value() const
void verifier_cb_ctx_destroy(verifier_cb_ctx *ctx)
#define PEM_read_bio_X509
grpc_jwt_verification_done_cb user_cb
static void verifier_put_mapping(grpc_jwt_verifier *v, const char *email_domain, const char *key_url_prefix)
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b)
def c_str(s, encoding='ascii')
JSON (JavaScript Object Notation).
@ GRPC_JWT_VERIFIER_GENERIC_ERROR
#define GRPC_SLICE_IS_EMPTY(slice)
GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b)
grpc_slice grpc_base64_decode(const char *b64, int url_safe)
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
grpc_polling_entity grpc_polling_entity_create_from_pollset(grpc_pollset *pollset)
@ GRPC_JWT_VERIFIER_KEY_RETRIEVAL_ERROR
const Json * grpc_jwt_claims_json(const grpc_jwt_claims *claims)
#define GRPC_GOOGLE_SERVICE_ACCOUNTS_KEY_URL_PREFIX
static int verify_jwt_signature(EVP_PKEY *key, const char *alg, const grpc_slice &signature, const grpc_slice &signed_data)
gpr_timespec grpc_jwt_claims_not_before(const grpc_jwt_claims *claims)
email_key_mapping * mappings
grpc_core::OrphanablePtr< grpc_core::HttpRequest > http_request
struct absl::base_internal::@2940::AllocList::Header header
void * gpr_memrchr(const void *s, int c, size_t n)
#define GRPC_SLICE_START_PTR(slice)
const char * grpc_jwt_claims_audience(const grpc_jwt_claims *claims)
GPRAPI int gpr_asprintf(char **strp, const char *format,...) GPR_PRINT_FORMAT_CHECK(2
void grpc_http_response_destroy(grpc_http_response *response)
bool Parse(FlagOpFn op, absl::string_view text, void *dst, std::string *error)
static jose_header * jose_header_from_json(Json json)
GPRAPI gpr_timespec gpr_now(gpr_clock_type clock)
static void jose_header_destroy(jose_header *h)
#define GRPC_OPENID_CONFIG_URL_SUFFIX
@ GRPC_JWT_VERIFIER_BAD_FORMAT
#define GRPC_SLICE_LENGTH(slice)
static Json parse_json_part_from_jwt(const char *str, size_t len)
static EVP_PKEY * find_verification_key(const Json &json, const char *header_alg, const char *header_kid)
static void on_openid_config_retrieved(void *user_data, grpc_error_handle)
GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type)
#define EVP_PKEY_set1_RSA
ABSL_MUST_USE_RESULT bool ok() const
#define EVP_MD_CTX_destroy
GPRAPI grpc_slice grpc_slice_from_copied_buffer(const char *source, size_t len)
static OrphanablePtr< HttpRequest > Get(URI uri, const grpc_channel_args *args, grpc_polling_entity *pollent, const grpc_http_request *request, Timestamp deadline, grpc_closure *on_done, grpc_http_response *response, RefCountedPtr< grpc_channel_credentials > channel_creds) GRPC_MUST_USE_RESULT
GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b)
grpc_jwt_claims * grpc_jwt_claims_from_json(Json json)
grpc_core::ExecCtx exec_ctx
std::string grpc_error_std_string(grpc_error_handle error)
grpc_jwt_verifier * grpc_jwt_verifier_create(const grpc_jwt_verifier_email_domain_key_url_mapping *mappings, size_t num_mappings)
static void retrieve_key_and_verify(verifier_cb_ctx *ctx)
static absl::StatusOr< URI > Create(std::string scheme, std::string authority, std::string path, std::vector< QueryParam > query_parameter_pairs, std::string fragment)
std::unique_ptr< T, Deleter > OrphanablePtr
const std::string & string_value() const
grpc_core::Duration grpc_jwt_verifier_max_delay
#define GRPC_ERROR_UNREF(err)
grpc_jwt_verifier * verifier
static BIGNUM * bignum_from_base64(const char *b64)
grpc_jwt_verifier_status grpc_jwt_claims_check(const grpc_jwt_claims *claims, const char *audience)
GPRAPI char * gpr_strdup(const char *src)
static verifier_cb_ctx * verifier_cb_ctx_create(grpc_jwt_verifier *verifier, grpc_pollset *pollset, jose_header *header, grpc_jwt_claims *claims, const char *audience, const grpc_slice &signature, const char *signed_jwt, size_t signed_jwt_len, void *user_data, grpc_jwt_verification_done_cb cb)
#define GRPC_GOOGLE_SERVICE_ACCOUNTS_EMAIL_DOMAIN
gpr_timespec grpc_jwt_claims_issued_at(const grpc_jwt_claims *claims)
void grpc_jwt_verifier_destroy(grpc_jwt_verifier *v)
static Json json_from_http(const grpc_http_response *response)
#define EVP_DigestVerifyFinal
#define EVP_MD_CTX_create
static const char * validate_string_field(const Json &json, const char *key)
size_t allocated_mappings
@ GRPC_JWT_VERIFIER_BAD_AUDIENCE
OPENSSL_EXPORT pem_password_cb * cb
static void on_keys_retrieved(void *user_data, grpc_error_handle)
void grpc_slice_unref_internal(const grpc_slice &slice)
#define GRPC_ERROR_IS_NONE(err)
static constexpr Duration Minutes(int64_t minutes)
grpc_http_response responses[HTTP_RESPONSE_COUNT]
grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:14