blob: 2227a0f6d0c97cc323f2dadae8c07badb588ff17 [file]
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
#include "jwt_impl.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "tink/binary_keyset_writer.h"
#include "tink/cleartext_keyset_handle.h"
#include "tink/jwt/jwt_mac_config.h"
#include "tink/jwt/jwt_signature_config.h"
#include "tink/jwt/jwt_key_templates.h"
#include "proto/testing/testing_api.grpc.pb.h"
#include "tink/util/test_matchers.h"
namespace crypto {
namespace tink {
namespace {
using ::crypto::tink::BinaryKeysetWriter;
using ::crypto::tink::CleartextKeysetHandle;
using ::crypto::tink::KeysetHandle;
using ::google::crypto::tink::KeyTemplate;
using ::testing::Eq;
using ::testing::IsEmpty;
using ::crypto::tink::test::IsOk;
using ::tink_testing_api::JwtSignRequest;
using ::tink_testing_api::JwtSignResponse;
using ::tink_testing_api::JwtVerifyRequest;
using ::tink_testing_api::JwtVerifyResponse;
std::string ValidKeyset() {
const KeyTemplate& key_template = ::crypto::tink::JwtHs256Template();
auto handle_or = KeysetHandle::GenerateNew(key_template);
EXPECT_THAT(handle_or.status(), IsOk());
std::stringbuf keyset;
auto writer_or =
BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
EXPECT_THAT(writer_or.status(), IsOk());
auto status = CleartextKeysetHandle::Write(writer_or.ValueOrDie().get(),
*handle_or.ValueOrDie());
EXPECT_THAT(status, IsOk());
return keyset.str();
}
class JwtImplMacTest : public ::testing::Test {
protected:
static void SetUpTestSuite() { ASSERT_THAT(JwtMacRegister(), IsOk()); }
};
TEST_F(JwtImplMacTest, MacComputeVerifySuccess) {
tink_testing_api::JwtImpl jwt;
std::string keyset = ValidKeyset();
JwtSignRequest comp_request;
comp_request.set_keyset(keyset);
auto raw_jwt = comp_request.mutable_raw_jwt();
raw_jwt->mutable_issuer()->set_value("issuer");
raw_jwt->mutable_subject()->set_value("subject");
raw_jwt->mutable_audiences()->Add("audience1");
raw_jwt->mutable_audiences()->Add("audience2");
raw_jwt->mutable_jwt_id()->set_value("jwt_id");
raw_jwt->mutable_not_before()->set_seconds(12345);
raw_jwt->mutable_not_before()->set_nanos(123000000);
raw_jwt->mutable_issued_at()->set_seconds(23456);
raw_jwt->mutable_expiration()->set_seconds(34567);
auto custom_claims = raw_jwt->mutable_custom_claims();
(*custom_claims)["null_claim"].set_null_value(
tink_testing_api::NullValue::NULL_VALUE);
(*custom_claims)["bool_claim"].set_bool_value(true);
(*custom_claims)["number_claim"].set_number_value(123.456);
(*custom_claims)["string_claim"].set_string_value("string_value");
JwtSignResponse comp_response;
EXPECT_TRUE(
jwt.ComputeMacAndEncode(nullptr, &comp_request, &comp_response).ok());
EXPECT_THAT(comp_response.err(), IsEmpty());
JwtVerifyRequest verify_request;
verify_request.set_keyset(keyset);
verify_request.set_signed_compact_jwt(comp_response.signed_compact_jwt());
auto validator = verify_request.mutable_validator();
validator->mutable_issuer()->set_value("issuer");
validator->mutable_audience()->set_value("audience2");
validator->mutable_now()->set_seconds(23456);
JwtVerifyResponse verify_response;
EXPECT_TRUE(
jwt.VerifyMacAndDecode(nullptr, &verify_request, &verify_response).ok());
EXPECT_THAT(verify_response.err(), IsEmpty());
auto verified_jwt = verify_response.verified_jwt();
EXPECT_THAT(verified_jwt.issuer().value(), Eq("issuer"));
EXPECT_THAT(verified_jwt.subject().value(), Eq("subject"));
EXPECT_THAT(verified_jwt.audiences_size(), Eq(2));
EXPECT_THAT(verified_jwt.audiences(0), Eq("audience1"));
EXPECT_THAT(verified_jwt.audiences(1), Eq("audience2"));
EXPECT_THAT(verified_jwt.jwt_id().value(), Eq("jwt_id"));
EXPECT_THAT(verified_jwt.not_before().seconds(), Eq(12345));
EXPECT_THAT(verified_jwt.not_before().nanos(), Eq(123000000));
EXPECT_THAT(verified_jwt.issued_at().seconds(), Eq(23456));
EXPECT_THAT(verified_jwt.issued_at().nanos(), Eq(0));
EXPECT_THAT(verified_jwt.expiration().seconds(), Eq(34567));
EXPECT_THAT(verified_jwt.expiration().nanos(), Eq(0));
auto verified_custom_claims = verified_jwt.custom_claims();
EXPECT_THAT(verified_custom_claims["null_claim"].null_value(),
Eq(tink_testing_api::NullValue::NULL_VALUE));
EXPECT_THAT(verified_custom_claims["bool_claim"].bool_value(), Eq(true));
EXPECT_THAT(verified_custom_claims["number_claim"].number_value(),
Eq(123.456));
EXPECT_THAT(verified_custom_claims["string_claim"].string_value(),
Eq("string_value"));
}
TEST_F(JwtImplMacTest, ComputeBadKeysetFail) {
tink_testing_api::JwtImpl jwt;
JwtSignRequest comp_request;
comp_request.set_keyset("bad keyset");
comp_request.mutable_raw_jwt()->mutable_issuer()->set_value("issuer");
JwtSignResponse comp_response;
EXPECT_TRUE(
jwt.ComputeMacAndEncode(nullptr, &comp_request, &comp_response).ok());
EXPECT_THAT(comp_response.err(), Not(IsEmpty()));
}
TEST_F(JwtImplMacTest, VerifyWithWrongIssuerFails) {
tink_testing_api::JwtImpl jwt;
std::string keyset = ValidKeyset();
JwtSignRequest comp_request;
comp_request.set_keyset(keyset);
comp_request.mutable_raw_jwt()->mutable_issuer()->set_value("unknown");
JwtSignResponse comp_response;
EXPECT_TRUE(
jwt.ComputeMacAndEncode(nullptr, &comp_request, &comp_response).ok());
EXPECT_THAT(comp_response.err(), IsEmpty());
JwtVerifyRequest verify_request;
verify_request.set_keyset(keyset);
verify_request.set_signed_compact_jwt(comp_response.signed_compact_jwt());
verify_request.mutable_validator()->mutable_issuer()->set_value("issuer");
JwtVerifyResponse verify_response;
EXPECT_TRUE(
jwt.VerifyMacAndDecode(nullptr, &verify_request, &verify_response).ok());
EXPECT_THAT(verify_response.err(), Not(IsEmpty()));
}
class JwtImplSignatureTest : public ::testing::Test {
protected:
static void SetUpTestSuite() { ASSERT_THAT(JwtSignatureRegister(), IsOk()); }
void SetUp() override {
const KeyTemplate& key_template = ::crypto::tink::JwtEs256Template();
auto handle_or = KeysetHandle::GenerateNew(key_template);
EXPECT_THAT(handle_or.status(), IsOk());
std::stringbuf keyset;
auto writer_or =
BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
EXPECT_THAT(writer_or.status(), IsOk());
auto status = CleartextKeysetHandle::Write(writer_or.ValueOrDie().get(),
*handle_or.ValueOrDie());
EXPECT_THAT(status, IsOk());
private_keyset_ = keyset.str();
auto pub_handle_or = handle_or.ValueOrDie()->GetPublicKeysetHandle();
EXPECT_THAT(pub_handle_or.status(), IsOk());
std::stringbuf pub_keyset;
auto pub_writer_or = BinaryKeysetWriter::New(
absl::make_unique<std::ostream>(&pub_keyset));
EXPECT_THAT(writer_or.status(), IsOk());
auto pub_status = CleartextKeysetHandle::Write(
pub_writer_or.ValueOrDie().get(), *pub_handle_or.ValueOrDie());
EXPECT_THAT(pub_status, IsOk());
public_keyset_ = pub_keyset.str();
}
std::string private_keyset_;
std::string public_keyset_;
};
TEST_F(JwtImplSignatureTest, SignVerifySuccess) {
tink_testing_api::JwtImpl jwt;
JwtSignRequest comp_request;
comp_request.set_keyset(private_keyset_);
auto raw_jwt = comp_request.mutable_raw_jwt();
raw_jwt->mutable_issuer()->set_value("issuer");
raw_jwt->mutable_subject()->set_value("subject");
raw_jwt->mutable_audiences()->Add("audience1");
raw_jwt->mutable_audiences()->Add("audience2");
raw_jwt->mutable_jwt_id()->set_value("jwt_id");
raw_jwt->mutable_not_before()->set_seconds(12345);
raw_jwt->mutable_issued_at()->set_seconds(23456);
raw_jwt->mutable_expiration()->set_seconds(34567);
auto custom_claims = raw_jwt->mutable_custom_claims();
(*custom_claims)["null_claim"].set_null_value(
tink_testing_api::NullValue::NULL_VALUE);
(*custom_claims)["bool_claim"].set_bool_value(true);
(*custom_claims)["number_claim"].set_number_value(123.456);
(*custom_claims)["string_claim"].set_string_value("string_value");
JwtSignResponse comp_response;
EXPECT_TRUE(
jwt.PublicKeySignAndEncode(nullptr, &comp_request, &comp_response).ok());
EXPECT_THAT(comp_response.err(), IsEmpty());
JwtVerifyRequest verify_request;
verify_request.set_keyset(public_keyset_);
verify_request.set_signed_compact_jwt(comp_response.signed_compact_jwt());
auto validator = verify_request.mutable_validator();
validator->mutable_issuer()->set_value("issuer");
validator->mutable_audience()->set_value("audience2");
validator->mutable_now()->set_seconds(23456);
JwtVerifyResponse verify_response;
EXPECT_TRUE(
jwt.PublicKeyVerifyAndDecode(nullptr, &verify_request, &verify_response)
.ok());
EXPECT_THAT(verify_response.err(), IsEmpty());
auto verified_jwt = verify_response.verified_jwt();
EXPECT_THAT(verified_jwt.issuer().value(), Eq("issuer"));
EXPECT_THAT(verified_jwt.subject().value(), Eq("subject"));
EXPECT_THAT(verified_jwt.audiences_size(), Eq(2));
EXPECT_THAT(verified_jwt.audiences(0), Eq("audience1"));
EXPECT_THAT(verified_jwt.audiences(1), Eq("audience2"));
EXPECT_THAT(verified_jwt.jwt_id().value(), Eq("jwt_id"));
EXPECT_THAT(verified_jwt.not_before().seconds(), Eq(12345));
EXPECT_THAT(verified_jwt.issued_at().seconds(), Eq(23456));
EXPECT_THAT(verified_jwt.expiration().seconds(), Eq(34567));
auto verified_custom_claims = verified_jwt.custom_claims();
EXPECT_THAT(verified_custom_claims["null_claim"].null_value(),
Eq(tink_testing_api::NullValue::NULL_VALUE));
EXPECT_THAT(verified_custom_claims["bool_claim"].bool_value(), Eq(true));
EXPECT_THAT(verified_custom_claims["number_claim"].number_value(),
Eq(123.456));
EXPECT_THAT(verified_custom_claims["string_claim"].string_value(),
Eq("string_value"));
}
TEST_F(JwtImplSignatureTest, SignWithBadKeysetFails) {
tink_testing_api::JwtImpl jwt;
JwtSignRequest comp_request;
comp_request.set_keyset("bad keyset");
comp_request.mutable_raw_jwt()->mutable_issuer()->set_value("issuer");
JwtSignResponse comp_response;
EXPECT_TRUE(
jwt.PublicKeySignAndEncode(nullptr, &comp_request, &comp_response).ok());
EXPECT_THAT(comp_response.err(), Not(IsEmpty()));
}
TEST_F(JwtImplSignatureTest, VerifyWithWrongIssuerFails) {
tink_testing_api::JwtImpl jwt;
JwtSignRequest comp_request;
comp_request.set_keyset(private_keyset_);
comp_request.mutable_raw_jwt()->mutable_issuer()->set_value("unknown");
JwtSignResponse comp_response;
EXPECT_TRUE(
jwt.PublicKeySignAndEncode(nullptr, &comp_request, &comp_response).ok());
EXPECT_THAT(comp_response.err(), IsEmpty());
JwtVerifyRequest verify_request;
verify_request.set_keyset(public_keyset_);
verify_request.set_signed_compact_jwt(comp_response.signed_compact_jwt());
verify_request.mutable_validator()->mutable_issuer()->set_value("issuer");
JwtVerifyResponse verify_response;
EXPECT_TRUE(
jwt.PublicKeyVerifyAndDecode(nullptr, &verify_request, &verify_response)
.ok());
EXPECT_THAT(verify_response.err(), Not(IsEmpty()));
}
} // namespace
} // namespace tink
} // namespace crypto