From e0251c93fb5036c056397c64a7d07af1b29f44e7 Mon Sep 17 00:00:00 2001 From: Oliver Freyermuth Date: Mon, 5 Jun 2023 22:25:53 +0200 Subject: [PATCH] scitokens_internal: catch matching exception type after jwt-cpp update (#125) After updating the vendored jwt-cpp version in: a8c597775f44ad2fa0f7bde8d186aca9466757ab the exception type if a claim is not found has changed, breaking the "no kid claim" use case. The vendored jwt-cpp version offers a convenience function to check whether the header claim is present, use that instead of accessing it and catching the exception. Co-authored-by: Derek Weitzel Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/scitokens_internal.h | 9 ++--- test/main.cpp | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 5 deletions(-) diff --git a/src/scitokens_internal.h b/src/scitokens_internal.h index 13ba58b..3705104 100644 --- a/src/scitokens_internal.h +++ b/src/scitokens_internal.h @@ -152,8 +152,9 @@ class SciTokenKey { m_private(private_contents) {} std::string serialize(jwt::builder &builder) { - std::error_code ec; - builder.set_key_id(m_kid); + if (m_kid != "none") { + builder.set_key_id(m_kid); + } return builder.sign(*this); } @@ -496,10 +497,8 @@ class Validator { std::string algorithm; // Key id is optional in the RFC, set to blank if it doesn't exist std::string key_id; - try { + if (jwt.has_key_id()) { key_id = jwt.get_key_id(); - } catch (const std::runtime_error &) { - // Don't do anything, key_id is empty, as it should be. } auto status = get_public_key_pem(jwt.get_issuer(), key_id, public_pem, algorithm); diff --git a/test/main.cpp b/test/main.cpp index d37a142..7296c90 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -697,6 +697,86 @@ TEST_F(SerializeTest, ExplicitTime) { enforcer_destroy(enforcer); } +class SerializeNoKidTest : public ::testing::Test { + protected: + void SetUp() override { + char *err_msg; + m_key = KeyPtr(scitoken_key_create("none", "ES256", ec_public, + ec_private, &err_msg), + scitoken_key_destroy); + ASSERT_TRUE(m_key.get() != nullptr); + + m_token = TokenPtr(scitoken_create(m_key.get()), scitoken_destroy); + ASSERT_TRUE(m_token.get() != nullptr); + + auto rv = scitoken_set_claim_string( + m_token.get(), "iss", "https://demo.scitokens.org/gtest", &err_msg); + ASSERT_TRUE(rv == 0); + + rv = scitoken_store_public_ec_key("https://demo.scitokens.org/gtest", + "1", ec_public, &err_msg); + ASSERT_TRUE(rv == 0); + + scitoken_set_lifetime(m_token.get(), 60); + + m_audiences_array.push_back("https://demo.scitokens.org/"); + m_audiences_array.push_back(nullptr); + + const char *groups[3] = {nullptr, nullptr, nullptr}; + const char group0[] = "group0"; + const char group1[] = "group1"; + groups[0] = group0; + groups[1] = group1; + rv = scitoken_set_claim_string_list(m_token.get(), "groups", groups, + &err_msg); + ASSERT_TRUE(rv == 0); + + m_read_token.reset(scitoken_create(nullptr)); + ASSERT_TRUE(m_read_token.get() != nullptr); + } + + using KeyPtr = std::unique_ptr; + KeyPtr m_key{nullptr, scitoken_key_destroy}; + + using TokenPtr = std::unique_ptr; + TokenPtr m_token{nullptr, scitoken_destroy}; + + std::vector m_audiences_array; + + TokenPtr m_read_token{nullptr, scitoken_destroy}; +}; + +TEST_F(SerializeNoKidTest, VerifyATJWTTest) { + + char *err_msg = nullptr; + + // Serialize as at+jwt token. + char *token_value = nullptr; + scitoken_set_serialize_profile(m_token.get(), SciTokenProfile::AT_JWT); + auto rv = scitoken_serialize(m_token.get(), &token_value, &err_msg); + ASSERT_TRUE(rv == 0); + std::unique_ptr token_value_ptr(token_value, free); + + // Accepts any profile. + rv = scitoken_deserialize_v2(token_value, m_read_token.get(), nullptr, + &err_msg); + ASSERT_TRUE(rv == 0); + + // Accepts only an at+jwt token, should work with at+jwt token + scitoken_set_deserialize_profile(m_read_token.get(), + SciTokenProfile::AT_JWT); + rv = scitoken_deserialize_v2(token_value, m_read_token.get(), nullptr, + &err_msg); + ASSERT_TRUE(rv == 0); + + // Accepts only SciToken 2.0; should fail + scitoken_set_deserialize_profile(m_read_token.get(), + SciTokenProfile::SCITOKENS_2_0); + rv = scitoken_deserialize_v2(token_value, m_read_token.get(), nullptr, + &err_msg); + ASSERT_FALSE(rv == 0); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();