absl::StatusOr GetValueFromTokenPayloadWithKeys()

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()));
  }
}