From 59ee751a68f26d5218adf2a12df0ccee9f1fa404 Mon Sep 17 00:00:00 2001 From: lei-tang <32078630+lei-tang@users.noreply.github.com> Date: Wed, 31 Jan 2018 16:00:05 -0800 Subject: [PATCH] Extract the subject field of a JWT (#967) Automatic merge from submit-queue. Extract the subject field of a JWT Extract the subject field (i.e., sub) of a JWT, which is used during the authentication. To run the tests: bazel test //src/envoy/auth:jwt_test **What this PR does / why we need it**: Extract the subject field (i.e., sub) of a JWT, which is used during the authentication. **Which issue this PR fixes** *(optional, in `fixes #(, fixes #, ...)` format, will close that issue when PR gets merged)*: fixes #966 **Special notes for your reviewer**: **Release note**: ```release-note ``` --- src/envoy/auth/jwt.cc | 2 ++ src/envoy/auth/jwt.h | 11 ++++++++--- src/envoy/auth/jwt_test.cc | 14 +++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/envoy/auth/jwt.cc b/src/envoy/auth/jwt.cc index 8059bcce901b..5e77b4424e78 100644 --- a/src/envoy/auth/jwt.cc +++ b/src/envoy/auth/jwt.cc @@ -270,6 +270,7 @@ Jwt::Jwt(const std::string &jwt) { iss_ = payload_->getString("iss", ""); aud_ = payload_->getString("aud", ""); + sub_ = payload_->getString("sub", ""); exp_ = payload_->getInteger("exp", 0); // Set up signature @@ -361,6 +362,7 @@ const std::string &Jwt::PayloadStr() { return payload_str_; } const std::string &Jwt::PayloadStrBase64Url() { return payload_str_base64url_; } const std::string &Jwt::Iss() { return iss_; } const std::string &Jwt::Aud() { return aud_; } +const std::string &Jwt::Sub() { return sub_; } int64_t Jwt::Exp() { return exp_; } void Pubkeys::CreateFromPemCore(const std::string &pkey_pem) { diff --git a/src/envoy/auth/jwt.h b/src/envoy/auth/jwt.h index 608e1039b236..36850fe93031 100644 --- a/src/envoy/auth/jwt.h +++ b/src/envoy/auth/jwt.h @@ -193,6 +193,10 @@ class Jwt : public WithStatus { // "aud" claim does not exist. const std::string& Aud(); + // It returns the "sub" claim value of the given JWT, or an empty string if + // "sub" claim does not exist. + const std::string& Sub(); + // It returns the "exp" claim value of the given JWT, or 0 if "exp" claim does // not exist. int64_t Exp(); @@ -211,6 +215,7 @@ class Jwt : public WithStatus { std::string kid_; std::string iss_; std::string aud_; + std::string sub_; int64_t exp_; /* @@ -254,8 +259,8 @@ class Pubkeys : public WithStatus { friend bool Verifier::Verify(const Jwt& jwt, const Pubkeys& pubkeys); }; -} // Auth -} // Http -} // Envoy +} // namespace Auth +} // namespace Http +} // namespace Envoy #endif // PROXY_JWT_H diff --git a/src/envoy/auth/jwt_test.cc b/src/envoy/auth/jwt_test.cc index 7862c38e1ce7..2f63ca7714a6 100644 --- a/src/envoy/auth/jwt_test.cc +++ b/src/envoy/auth/jwt_test.cc @@ -41,6 +41,7 @@ class DatasetPem { "N09hdvlCtAF87Fu1qqfwEQ93A-J7m08bZJoyIPcNmTcYGHwfMR4-lcI5cC_93C_" "5BGE1FHPLOHpNghLuM6-rhOtgwZc9ywupn_bBK3QzuAoDnYwpqQhgQL_CdUD_bSHcmWFkw"; + const std::string kJwtSub = "test@example.com"; const std::string kJwtHeaderEncoded = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9"; const std::string kJwtPayloadEncoded = "eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoidGVzdEBleGFtcGxlLmNvbSIs" @@ -340,7 +341,7 @@ namespace { bool EqJson(Json::ObjectSharedPtr p1, Json::ObjectSharedPtr p2) { return p1->asJsonString() == p2->asJsonString(); } -} +} // namespace class JwtTest : public testing::Test { protected: @@ -459,6 +460,17 @@ TEST_F(JwtTestPem, InvalidAlg) { Status::ALG_NOT_IMPLEMENTED, nullptr); } +TEST(JwtSubExtractionTest, NonEmptyJwtSubShouldEqual) { + DatasetPem ds; + Jwt jwt(ds.kJwt); + EXPECT_EQ(jwt.Sub(), ds.kJwtSub); +} + +TEST(JwtSubExtractionTest, EmptyJwtSubShouldEqual) { + Jwt jwt(""); + EXPECT_EQ(jwt.Sub(), ""); +} + // Test cases w/ JWKs-formatted public key class JwtTestJwks : public JwtTest {