xref: /aosp_15_r20/external/tink/cc/jwt/internal/jwt_public_key_sign_verify_impl_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2021 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/strings/str_cat.h"
25 #include "absl/strings/str_split.h"
26 #include "tink/internal/ec_util.h"
27 #include "tink/jwt/internal/json_util.h"
28 #include "tink/jwt/internal/jwt_format.h"
29 #include "tink/jwt/internal/jwt_public_key_sign_impl.h"
30 #include "tink/jwt/internal/jwt_public_key_verify_impl.h"
31 #include "tink/jwt/jwt_public_key_sign.h"
32 #include "tink/jwt/jwt_public_key_verify.h"
33 #include "tink/jwt/jwt_validator.h"
34 #include "tink/jwt/raw_jwt.h"
35 #include "tink/jwt/verified_jwt.h"
36 #include "tink/subtle/ecdsa_sign_boringssl.h"
37 #include "tink/subtle/ecdsa_verify_boringssl.h"
38 #include "tink/util/test_matchers.h"
39 
40 using ::crypto::tink::test::IsOk;
41 using ::crypto::tink::test::IsOkAndHolds;
42 using ::testing::Eq;
43 using ::testing::Not;
44 
45 namespace crypto {
46 namespace tink {
47 namespace jwt_internal {
48 
49 namespace {
50 
51 class JwtSignatureImplTest : public ::testing::Test {
52  protected:
SetUp()53   void SetUp() override {
54     util::StatusOr<internal::EcKey> ec_key =
55         internal::NewEcKey(subtle::EllipticCurveType::NIST_P256);
56     ASSERT_THAT(ec_key, IsOk());
57 
58     util::StatusOr<std::unique_ptr<subtle::EcdsaSignBoringSsl>> sign =
59         subtle::EcdsaSignBoringSsl::New(
60             *ec_key, subtle::HashType::SHA256,
61             subtle::EcdsaSignatureEncoding::IEEE_P1363);
62     ASSERT_THAT(sign, IsOk());
63 
64     util::StatusOr<std::unique_ptr<subtle::EcdsaVerifyBoringSsl>> verify =
65         subtle::EcdsaVerifyBoringSsl::New(
66             *ec_key, subtle::HashType::SHA256,
67             subtle::EcdsaSignatureEncoding::IEEE_P1363);
68     ASSERT_THAT(verify, IsOk());
69 
70     jwt_sign_ = absl::make_unique<JwtPublicKeySignImpl>(
71         *std::move(sign), "ES256", /*custom_kid=*/absl::nullopt);
72     jwt_verify_ = absl::make_unique<JwtPublicKeyVerifyImpl>(
73         *std::move(verify), "ES256", /*custom_kid=*/absl::nullopt);
74   }
75   std::unique_ptr<JwtPublicKeySignImpl> jwt_sign_;
76   std::unique_ptr<JwtPublicKeyVerifyImpl> jwt_verify_;
77 };
78 
TEST_F(JwtSignatureImplTest,CreateAndValidateToken)79 TEST_F(JwtSignatureImplTest, CreateAndValidateToken) {
80   absl::Time now = absl::Now();
81   util::StatusOr<RawJwt> raw_jwt_or =
82       RawJwtBuilder()
83           .SetTypeHeader("typeHeader")
84           .SetJwtId("id123")
85           .SetNotBefore(now - absl::Seconds(300))
86           .SetIssuedAt(now)
87           .SetExpiration(now + absl::Seconds(300))
88           .Build();
89   ASSERT_THAT(raw_jwt_or, IsOk());
90   RawJwt raw_jwt = raw_jwt_or.value();
91 
92   util::StatusOr<std::string> compact =
93       jwt_sign_->SignAndEncodeWithKid(raw_jwt, /*kid=*/absl::nullopt);
94   ASSERT_THAT(compact, IsOk());
95 
96   util::StatusOr<JwtValidator> validator =
97       JwtValidatorBuilder().ExpectTypeHeader("typeHeader").Build();
98   ASSERT_THAT(validator, IsOk());
99 
100   // Success
101   util::StatusOr<VerifiedJwt> verified_jwt =
102       jwt_verify_->VerifyAndDecodeWithKid(*compact, *validator,
103                                           /*kid=*/absl::nullopt);
104   ASSERT_THAT(verified_jwt, IsOk());
105   EXPECT_THAT(verified_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader"));
106   EXPECT_THAT(verified_jwt->GetJwtId(), IsOkAndHolds("id123"));
107 
108   // Fails because kid header is not present
109   EXPECT_THAT(
110       jwt_verify_->VerifyAndDecodeWithKid(*compact, *validator, "kid-123")
111           .status(),
112       Not(IsOk()));
113 
114   // Fails with wrong issuer
115   util::StatusOr<JwtValidator> validator2 =
116       JwtValidatorBuilder().ExpectIssuer("unknown").Build();
117   ASSERT_THAT(validator2, IsOk());
118   EXPECT_FALSE(
119       jwt_verify_
120           ->VerifyAndDecodeWithKid(*compact, *validator2, /*kid=*/absl::nullopt)
121           .ok());
122 
123   // Fails because token is not yet valid
124   util::StatusOr<JwtValidator> validator_1970 =
125       JwtValidatorBuilder().SetFixedNow(absl::FromUnixSeconds(12345)).Build();
126   ASSERT_THAT(validator_1970, IsOk());
127   EXPECT_FALSE(jwt_verify_
128                    ->VerifyAndDecodeWithKid(*compact, *validator_1970,
129                                             /*kid=*/absl::nullopt)
130                    .ok());
131 }
132 
TEST_F(JwtSignatureImplTest,CreateAndValidateTokenWithKid)133 TEST_F(JwtSignatureImplTest, CreateAndValidateTokenWithKid) {
134   absl::Time now = absl::Now();
135   util::StatusOr<RawJwt> raw_jwt = RawJwtBuilder()
136                                        .SetTypeHeader("typeHeader")
137                                        .SetJwtId("id123")
138                                        .SetNotBefore(now - absl::Seconds(300))
139                                        .SetIssuedAt(now)
140                                        .SetExpiration(now + absl::Seconds(300))
141                                        .Build();
142   ASSERT_THAT(raw_jwt, IsOk());
143 
144   util::StatusOr<std::string> compact =
145       jwt_sign_->SignAndEncodeWithKid(*raw_jwt, "kid-123");
146   ASSERT_THAT(compact, IsOk());
147 
148   util::StatusOr<JwtValidator> validator =
149       JwtValidatorBuilder().ExpectTypeHeader("typeHeader").Build();
150 
151   util::StatusOr<VerifiedJwt> verified_jwt =
152       jwt_verify_->VerifyAndDecodeWithKid(*compact, *validator, "kid-123");
153   ASSERT_THAT(verified_jwt, IsOk());
154   EXPECT_THAT(verified_jwt->GetTypeHeader(), IsOkAndHolds("typeHeader"));
155   EXPECT_THAT(verified_jwt->GetJwtId(), IsOkAndHolds("id123"));
156 
157   // Kid header in the token is ignored.
158   EXPECT_THAT(
159       jwt_verify_
160           ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt)
161           .status(),
162       IsOk());
163 
164   // parse header to make sure the kid value is set correctly.
165   std::vector<absl::string_view> parts = absl::StrSplit(*compact, '.');
166   ASSERT_THAT(parts.size(), Eq(3));
167   std::string json_header;
168   ASSERT_TRUE(DecodeHeader(parts[0], &json_header));
169   util::StatusOr<google::protobuf::Struct> header =
170       JsonStringToProtoStruct(json_header);
171   ASSERT_THAT(header, IsOk());
172   EXPECT_THAT(header->fields().find("kid")->second.string_value(),
173               Eq("kid-123"));
174 }
175 
TEST_F(JwtSignatureImplTest,FailsWithModifiedCompact)176 TEST_F(JwtSignatureImplTest, FailsWithModifiedCompact) {
177   util::StatusOr<RawJwt> raw_jwt =
178       RawJwtBuilder().SetJwtId("id123").WithoutExpiration().Build();
179   ASSERT_THAT(raw_jwt, IsOk());
180 
181   util::StatusOr<std::string> compact =
182       jwt_sign_->SignAndEncodeWithKid(*raw_jwt, /*kid=*/absl::nullopt);
183   ASSERT_THAT(compact, IsOk());
184   util::StatusOr<JwtValidator> validator =
185       JwtValidatorBuilder().AllowMissingExpiration().Build();
186   ASSERT_THAT(validator, IsOk());
187 
188   EXPECT_THAT(
189       jwt_verify_
190           ->VerifyAndDecodeWithKid(*compact, *validator, /*kid=*/absl::nullopt)
191           .status(),
192       IsOk());
193   EXPECT_FALSE(jwt_verify_
194                    ->VerifyAndDecodeWithKid(absl::StrCat(*compact, "x"),
195                                             *validator,
196                                             /*kid=*/absl::nullopt)
197                    .ok());
198   EXPECT_FALSE(jwt_verify_
199                    ->VerifyAndDecodeWithKid(absl::StrCat(*compact, " "),
200                                             *validator,
201                                             /*kid=*/absl::nullopt)
202                    .ok());
203   EXPECT_FALSE(jwt_verify_
204                    ->VerifyAndDecodeWithKid(absl::StrCat("x", *compact),
205                                             *validator,
206                                             /*kid=*/absl::nullopt)
207                    .ok());
208   EXPECT_FALSE(jwt_verify_
209                    ->VerifyAndDecodeWithKid(absl::StrCat(" ", *compact),
210                                             *validator,
211                                             /*kid=*/absl::nullopt)
212                    .ok());
213 }
214 
TEST_F(JwtSignatureImplTest,FailsWithInvalidTokens)215 TEST_F(JwtSignatureImplTest, FailsWithInvalidTokens) {
216   util::StatusOr<JwtValidator> validator =
217       JwtValidatorBuilder().AllowMissingExpiration().Build();
218   ASSERT_THAT(validator, IsOk());
219   EXPECT_FALSE(jwt_verify_
220                    ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30.YWJj.",
221                                             *validator, /*kid=*/absl::nullopt)
222                    .ok());
223   EXPECT_FALSE(jwt_verify_
224                    ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9?.e30.YWJj",
225                                             *validator, /*kid=*/absl::nullopt)
226                    .ok());
227   EXPECT_FALSE(jwt_verify_
228                    ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30?.YWJj",
229                                             *validator, /*kid=*/absl::nullopt)
230                    .ok());
231   EXPECT_FALSE(jwt_verify_
232                    ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.e30.YWJj?",
233                                             *validator, /*kid=*/absl::nullopt)
234                    .ok());
235   EXPECT_FALSE(jwt_verify_
236                    ->VerifyAndDecodeWithKid("eyJhbGciOiJIUzI1NiJ9.YWJj",
237                                             *validator,
238                                             /*kid=*/absl::nullopt)
239                    .ok());
240   EXPECT_FALSE(
241       jwt_verify_->VerifyAndDecodeWithKid("", *validator, /*kid=*/absl::nullopt)
242           .ok());
243   EXPECT_FALSE(
244       jwt_verify_
245           ->VerifyAndDecodeWithKid("..", *validator, /*kid=*/absl::nullopt)
246 
247           .ok());
248 }
249 
250 }  // namespace
251 }  // namespace jwt_internal
252 }  // namespace tink
253 }  // namespace crypto
254