in cpp/jwt.cc [32:73]
absl::StatusOr<std::string> GetValueFromTokenPayloadWithKeys(
const std::string& token, absl::Span<const std::string> keys) {
try {
if (keys.empty() || token.empty()) {
return absl::InvalidArgumentError("Keys/token cannot be empty.");
}
absl::StatusOr<decoded_jwt_t> decoded = DecodeJwt(token);
if (!decoded.ok()) {
return decoded.status();
}
jwt::traits::nlohmann_json::json json_obj = decoded->get_payload_json();
for (const std::string& key : keys) {
if (!json_obj.is_object()) {
return absl::InternalError(
absl::StrCat("Token has an invalid format: ", json_obj.dump()));
}
if (!json_obj.contains(key)) {
return absl::InternalError(absl::StrFormat(
"Token: %s does not contain key: %s.", json_obj.dump(), key));
}
json_obj = json_obj[key];
}
if (json_obj.is_number()) {
return json_obj.dump();
}
if (json_obj.is_string()) {
return json_obj.get<std::string>();
}
return absl::InternalError(absl::StrFormat(
"Token %s does not have a string/number value for key (%s): ",
json_obj.dump(), absl::StrJoin(keys, ",")));
} catch (const std::exception& e) {
// The try-catch is to catch the exception thrown by the jwt-cpp
// library. This is probably redundant since we already have the try-catch
// in DecodeJwt, which is the only place where I suspect the exception can
// throw. We add this outer try-catch to make the code more robust
// and prevent exception leak into google3.
return absl::InternalError(absl::StrFormat(
"Failed to get value of key (%s) from token %s: due to exception: %s",
absl::StrJoin(keys, ","), token, e.what()));
}
}