static char *_jwk_parse(apr_pool_t *pool, const char *s, apr_jwk_t **jwk, apr_jwt_error_t *err) { json_t *j_jwk = json_loads(s, 0, NULL); TST_ASSERT("json_loads", ((j_jwk != NULL) && (json_is_object(j_jwk)))); TST_ASSERT_ERR("apr_jwk_parse_json", apr_jwk_parse_json(pool, j_jwk, jwk, err), pool, (*err)); json_decref(j_jwk); return 0; }
/* * get the key from the JWKs that corresponds with the key specified in the header */ static apr_byte_t oidc_proto_get_key_from_jwks(request_rec *r, apr_jwt_header_t *jwt_hdr, json_t *j_jwks, const char *type, apr_jwk_t **result) { char *x5t = NULL; apr_jwt_get_string(r->pool, &jwt_hdr->value, "x5t", &x5t); oidc_debug(r, "search for kid \"%s\" or thumbprint x5t \"%s\"", jwt_hdr->kid, x5t); /* get the "keys" JSON array from the JWKs object */ json_t *keys = json_object_get(j_jwks, "keys"); if ((keys == NULL) || !(json_is_array(keys))) { oidc_error(r, "\"keys\" array element is not a JSON array"); return FALSE; } int i; for (i = 0; i < json_array_size(keys); i++) { /* get the next element in the array */ json_t *elem = json_array_get(keys, i); /* check that it is a JSON object */ if (!json_is_object(elem)) { oidc_warn(r, "\"keys\" array element is not a JSON object, skipping"); continue; } /* get the key type and see if it is the RSA type that we are looking for */ json_t *kty = json_object_get(elem, "kty"); if ((!json_is_string(kty)) || (strcmp(json_string_value(kty), type) != 0)) continue; /* see if we were looking for a specific kid, if not we'll return the first one found */ if ((jwt_hdr->kid == NULL) && (x5t == NULL)) { oidc_debug(r, "no kid/x5t to match, return first key found"); apr_jwk_parse_json(r->pool, elem, NULL, result); break; } /* we are looking for a specific kid, get the kid from the current element */ json_t *ekid = json_object_get(elem, "kid"); if ((ekid != NULL) && json_is_string(ekid) && (jwt_hdr->kid != NULL)) { /* compare the requested kid against the current element */ if (apr_strnatcmp(jwt_hdr->kid, json_string_value(ekid)) == 0) { oidc_debug(r, "found matching kid: \"%s\"", jwt_hdr->kid); apr_jwk_parse_json(r->pool, elem, NULL, result); break; } } /* we are looking for a specific x5t, get the x5t from the current element */ json_t *ex5t = json_object_get(elem, "kid"); if ((ex5t != NULL) && json_is_string(ex5t) && (x5t != NULL)) { /* compare the requested kid against the current element */ if (apr_strnatcmp(x5t, json_string_value(ex5t)) == 0) { oidc_debug(r, "found matching x5t: \"%s\"", x5t); apr_jwk_parse_json(r->pool, elem, NULL, result); break; } } } return TRUE; }