1*e7b1675dSTing-Kang Chang // Copyright 2021 Google LLC
2*e7b1675dSTing-Kang Chang //
3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang //
7*e7b1675dSTing-Kang Chang // http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang //
9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang // limitations under the License.
14*e7b1675dSTing-Kang Chang //
15*e7b1675dSTing-Kang Chang ///////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Chang // Implementation of a JWT Service.
18*e7b1675dSTing-Kang Chang #include "jwt_impl.h"
19*e7b1675dSTing-Kang Chang
20*e7b1675dSTing-Kang Chang #include <memory>
21*e7b1675dSTing-Kang Chang #include <ostream>
22*e7b1675dSTing-Kang Chang #include <sstream>
23*e7b1675dSTing-Kang Chang #include <string>
24*e7b1675dSTing-Kang Chang #include <utility>
25*e7b1675dSTing-Kang Chang #include <vector>
26*e7b1675dSTing-Kang Chang
27*e7b1675dSTing-Kang Chang #include "absl/time/time.h"
28*e7b1675dSTing-Kang Chang #include "tink/binary_keyset_reader.h"
29*e7b1675dSTing-Kang Chang #include "tink/binary_keyset_writer.h"
30*e7b1675dSTing-Kang Chang #include "tink/cleartext_keyset_handle.h"
31*e7b1675dSTing-Kang Chang #include "tink/jwt/jwk_set_converter.h"
32*e7b1675dSTing-Kang Chang #include "tink/jwt/jwt_mac.h"
33*e7b1675dSTing-Kang Chang #include "tink/jwt/jwt_public_key_sign.h"
34*e7b1675dSTing-Kang Chang #include "tink/jwt/jwt_public_key_verify.h"
35*e7b1675dSTing-Kang Chang #include "tink/jwt/raw_jwt.h"
36*e7b1675dSTing-Kang Chang #include "tink/util/status.h"
37*e7b1675dSTing-Kang Chang #include "create.h"
38*e7b1675dSTing-Kang Chang
39*e7b1675dSTing-Kang Chang namespace tink_testing_api {
40*e7b1675dSTing-Kang Chang
41*e7b1675dSTing-Kang Chang using ::crypto::tink::BinaryKeysetReader;
42*e7b1675dSTing-Kang Chang using ::crypto::tink::BinaryKeysetWriter;
43*e7b1675dSTing-Kang Chang using ::crypto::tink::CleartextKeysetHandle;
44*e7b1675dSTing-Kang Chang using ::crypto::tink::JwtMac;
45*e7b1675dSTing-Kang Chang using ::crypto::tink::JwtPublicKeySign;
46*e7b1675dSTing-Kang Chang using ::crypto::tink::JwtPublicKeyVerify;
47*e7b1675dSTing-Kang Chang using ::crypto::tink::KeysetReader;
48*e7b1675dSTing-Kang Chang using ::crypto::tink::RawJwt;
49*e7b1675dSTing-Kang Chang using ::crypto::tink::VerifiedJwt;
50*e7b1675dSTing-Kang Chang using ::crypto::tink::util::StatusOr;
51*e7b1675dSTing-Kang Chang
52*e7b1675dSTing-Kang Chang using ::crypto::tink::JwkSetToPublicKeysetHandle;
53*e7b1675dSTing-Kang Chang
TimestampToTime(google::protobuf::Timestamp t)54*e7b1675dSTing-Kang Chang absl::Time TimestampToTime(google::protobuf::Timestamp t) {
55*e7b1675dSTing-Kang Chang return absl::FromUnixMillis(t.seconds() * 1000 + t.nanos() / 1000000);
56*e7b1675dSTing-Kang Chang }
57*e7b1675dSTing-Kang Chang
TimeToTimestamp(absl::Time time)58*e7b1675dSTing-Kang Chang google::protobuf::Timestamp TimeToTimestamp(absl::Time time) {
59*e7b1675dSTing-Kang Chang int64_t millis = absl::ToUnixMillis(time);
60*e7b1675dSTing-Kang Chang int64_t seconds = millis / 1000;
61*e7b1675dSTing-Kang Chang int32_t nanos = (millis - seconds * 1000) * 1000000;
62*e7b1675dSTing-Kang Chang google::protobuf::Timestamp timestamp;
63*e7b1675dSTing-Kang Chang timestamp.set_seconds(seconds);
64*e7b1675dSTing-Kang Chang timestamp.set_nanos(nanos);
65*e7b1675dSTing-Kang Chang return timestamp;
66*e7b1675dSTing-Kang Chang }
67*e7b1675dSTing-Kang Chang
RawJwtFromProto(const JwtToken & raw_jwt_proto)68*e7b1675dSTing-Kang Chang crypto::tink::util::StatusOr<crypto::tink::RawJwt> RawJwtFromProto(
69*e7b1675dSTing-Kang Chang const JwtToken& raw_jwt_proto) {
70*e7b1675dSTing-Kang Chang auto builder = crypto::tink::RawJwtBuilder();
71*e7b1675dSTing-Kang Chang if (raw_jwt_proto.has_type_header()) {
72*e7b1675dSTing-Kang Chang builder.SetTypeHeader(raw_jwt_proto.type_header().value());
73*e7b1675dSTing-Kang Chang }
74*e7b1675dSTing-Kang Chang if (raw_jwt_proto.has_issuer()) {
75*e7b1675dSTing-Kang Chang builder.SetIssuer(raw_jwt_proto.issuer().value());
76*e7b1675dSTing-Kang Chang }
77*e7b1675dSTing-Kang Chang if (raw_jwt_proto.has_subject()) {
78*e7b1675dSTing-Kang Chang builder.SetSubject(raw_jwt_proto.subject().value());
79*e7b1675dSTing-Kang Chang }
80*e7b1675dSTing-Kang Chang for (const std::string& audience : raw_jwt_proto.audiences()) {
81*e7b1675dSTing-Kang Chang builder.AddAudience(audience);
82*e7b1675dSTing-Kang Chang }
83*e7b1675dSTing-Kang Chang if (raw_jwt_proto.has_jwt_id()) {
84*e7b1675dSTing-Kang Chang builder.SetJwtId(raw_jwt_proto.jwt_id().value());
85*e7b1675dSTing-Kang Chang }
86*e7b1675dSTing-Kang Chang if (raw_jwt_proto.has_expiration()) {
87*e7b1675dSTing-Kang Chang builder.SetExpiration(TimestampToTime(raw_jwt_proto.expiration()));
88*e7b1675dSTing-Kang Chang } else {
89*e7b1675dSTing-Kang Chang builder.WithoutExpiration();
90*e7b1675dSTing-Kang Chang }
91*e7b1675dSTing-Kang Chang if (raw_jwt_proto.has_issued_at()) {
92*e7b1675dSTing-Kang Chang builder.SetIssuedAt(TimestampToTime(raw_jwt_proto.issued_at()));
93*e7b1675dSTing-Kang Chang }
94*e7b1675dSTing-Kang Chang if (raw_jwt_proto.has_not_before()) {
95*e7b1675dSTing-Kang Chang builder.SetNotBefore(TimestampToTime(raw_jwt_proto.not_before()));
96*e7b1675dSTing-Kang Chang }
97*e7b1675dSTing-Kang Chang auto claims = raw_jwt_proto.custom_claims();
98*e7b1675dSTing-Kang Chang for (auto it = claims.begin(); it != claims.end(); it++) {
99*e7b1675dSTing-Kang Chang const auto& name = it->first;
100*e7b1675dSTing-Kang Chang const auto& value = it->second;
101*e7b1675dSTing-Kang Chang if (value.kind_case() == JwtClaimValue::kNullValue) {
102*e7b1675dSTing-Kang Chang builder.AddNullClaim(name);
103*e7b1675dSTing-Kang Chang } else if (value.kind_case() == JwtClaimValue::kBoolValue) {
104*e7b1675dSTing-Kang Chang builder.AddBooleanClaim(name, value.bool_value());
105*e7b1675dSTing-Kang Chang } else if (value.kind_case() == JwtClaimValue::kNumberValue) {
106*e7b1675dSTing-Kang Chang builder.AddNumberClaim(name, value.number_value());
107*e7b1675dSTing-Kang Chang } else if (value.kind_case() == JwtClaimValue::kStringValue) {
108*e7b1675dSTing-Kang Chang builder.AddStringClaim(name, value.string_value());
109*e7b1675dSTing-Kang Chang } else if (value.kind_case() == JwtClaimValue::kJsonObjectValue) {
110*e7b1675dSTing-Kang Chang builder.AddJsonObjectClaim(name, value.json_object_value());
111*e7b1675dSTing-Kang Chang } else if (value.kind_case() == JwtClaimValue::kJsonArrayValue) {
112*e7b1675dSTing-Kang Chang builder.AddJsonArrayClaim(name, value.json_array_value());
113*e7b1675dSTing-Kang Chang }
114*e7b1675dSTing-Kang Chang }
115*e7b1675dSTing-Kang Chang return builder.Build();
116*e7b1675dSTing-Kang Chang }
117*e7b1675dSTing-Kang Chang
VerifiedJwtToProto(const crypto::tink::VerifiedJwt & verified_jwt)118*e7b1675dSTing-Kang Chang JwtToken VerifiedJwtToProto(const crypto::tink::VerifiedJwt& verified_jwt) {
119*e7b1675dSTing-Kang Chang JwtToken token;
120*e7b1675dSTing-Kang Chang if (verified_jwt.HasTypeHeader()) {
121*e7b1675dSTing-Kang Chang token.mutable_type_header()->set_value(
122*e7b1675dSTing-Kang Chang verified_jwt.GetTypeHeader().value());
123*e7b1675dSTing-Kang Chang }
124*e7b1675dSTing-Kang Chang if (verified_jwt.HasIssuer()) {
125*e7b1675dSTing-Kang Chang token.mutable_issuer()->set_value(verified_jwt.GetIssuer().value());
126*e7b1675dSTing-Kang Chang }
127*e7b1675dSTing-Kang Chang if (verified_jwt.HasSubject()) {
128*e7b1675dSTing-Kang Chang token.mutable_subject()->set_value(verified_jwt.GetSubject().value());
129*e7b1675dSTing-Kang Chang }
130*e7b1675dSTing-Kang Chang if (verified_jwt.HasAudiences()) {
131*e7b1675dSTing-Kang Chang std::vector<std::string> audiences = verified_jwt.GetAudiences().value();
132*e7b1675dSTing-Kang Chang for (const std::string& audience : audiences) {
133*e7b1675dSTing-Kang Chang token.add_audiences(audience);
134*e7b1675dSTing-Kang Chang }
135*e7b1675dSTing-Kang Chang }
136*e7b1675dSTing-Kang Chang if (verified_jwt.HasJwtId()) {
137*e7b1675dSTing-Kang Chang token.mutable_jwt_id()->set_value(verified_jwt.GetJwtId().value());
138*e7b1675dSTing-Kang Chang }
139*e7b1675dSTing-Kang Chang if (verified_jwt.HasExpiration()) {
140*e7b1675dSTing-Kang Chang *token.mutable_expiration() =
141*e7b1675dSTing-Kang Chang TimeToTimestamp(verified_jwt.GetExpiration().value());
142*e7b1675dSTing-Kang Chang }
143*e7b1675dSTing-Kang Chang if (verified_jwt.HasIssuedAt()) {
144*e7b1675dSTing-Kang Chang *token.mutable_issued_at() =
145*e7b1675dSTing-Kang Chang TimeToTimestamp(verified_jwt.GetIssuedAt().value());
146*e7b1675dSTing-Kang Chang }
147*e7b1675dSTing-Kang Chang if (verified_jwt.HasNotBefore()) {
148*e7b1675dSTing-Kang Chang *token.mutable_not_before() =
149*e7b1675dSTing-Kang Chang TimeToTimestamp(verified_jwt.GetNotBefore().value());
150*e7b1675dSTing-Kang Chang }
151*e7b1675dSTing-Kang Chang std::vector<std::string> names = verified_jwt.CustomClaimNames();
152*e7b1675dSTing-Kang Chang for (const std::string& name : names) {
153*e7b1675dSTing-Kang Chang if (verified_jwt.IsNullClaim(name)) {
154*e7b1675dSTing-Kang Chang (*token.mutable_custom_claims())[name].set_null_value(
155*e7b1675dSTing-Kang Chang NullValue::NULL_VALUE);
156*e7b1675dSTing-Kang Chang } else if (verified_jwt.HasBooleanClaim(name)) {
157*e7b1675dSTing-Kang Chang (*token.mutable_custom_claims())[name].set_bool_value(
158*e7b1675dSTing-Kang Chang verified_jwt.GetBooleanClaim(name).value());
159*e7b1675dSTing-Kang Chang } else if (verified_jwt.HasNumberClaim(name)) {
160*e7b1675dSTing-Kang Chang (*token.mutable_custom_claims())[name].set_number_value(
161*e7b1675dSTing-Kang Chang verified_jwt.GetNumberClaim(name).value());
162*e7b1675dSTing-Kang Chang } else if (verified_jwt.HasStringClaim(name)) {
163*e7b1675dSTing-Kang Chang (*token.mutable_custom_claims())[name].set_string_value(
164*e7b1675dSTing-Kang Chang verified_jwt.GetStringClaim(name).value());
165*e7b1675dSTing-Kang Chang } else if (verified_jwt.HasJsonObjectClaim(name)) {
166*e7b1675dSTing-Kang Chang (*token.mutable_custom_claims())[name].set_json_object_value(
167*e7b1675dSTing-Kang Chang verified_jwt.GetJsonObjectClaim(name).value());
168*e7b1675dSTing-Kang Chang } else if (verified_jwt.HasJsonArrayClaim(name)) {
169*e7b1675dSTing-Kang Chang (*token.mutable_custom_claims())[name].set_json_array_value(
170*e7b1675dSTing-Kang Chang verified_jwt.GetJsonArrayClaim(name).value());
171*e7b1675dSTing-Kang Chang }
172*e7b1675dSTing-Kang Chang }
173*e7b1675dSTing-Kang Chang return token;
174*e7b1675dSTing-Kang Chang }
175*e7b1675dSTing-Kang Chang
JwtValidatorFromProto(const JwtValidator & validator_proto)176*e7b1675dSTing-Kang Chang crypto::tink::util::StatusOr<crypto::tink::JwtValidator> JwtValidatorFromProto(
177*e7b1675dSTing-Kang Chang const JwtValidator& validator_proto) {
178*e7b1675dSTing-Kang Chang auto builder = crypto::tink::JwtValidatorBuilder();
179*e7b1675dSTing-Kang Chang if (validator_proto.has_expected_type_header()) {
180*e7b1675dSTing-Kang Chang builder.ExpectTypeHeader(validator_proto.expected_type_header().value());
181*e7b1675dSTing-Kang Chang }
182*e7b1675dSTing-Kang Chang if (validator_proto.has_expected_issuer()) {
183*e7b1675dSTing-Kang Chang builder.ExpectIssuer(validator_proto.expected_issuer().value());
184*e7b1675dSTing-Kang Chang }
185*e7b1675dSTing-Kang Chang if (validator_proto.has_expected_audience()) {
186*e7b1675dSTing-Kang Chang builder.ExpectAudience(validator_proto.expected_audience().value());
187*e7b1675dSTing-Kang Chang }
188*e7b1675dSTing-Kang Chang if (validator_proto.ignore_type_header()) {
189*e7b1675dSTing-Kang Chang builder.IgnoreTypeHeader();
190*e7b1675dSTing-Kang Chang }
191*e7b1675dSTing-Kang Chang if (validator_proto.ignore_issuer()) {
192*e7b1675dSTing-Kang Chang builder.IgnoreIssuer();
193*e7b1675dSTing-Kang Chang }
194*e7b1675dSTing-Kang Chang if (validator_proto.ignore_audience()) {
195*e7b1675dSTing-Kang Chang builder.IgnoreAudiences();
196*e7b1675dSTing-Kang Chang }
197*e7b1675dSTing-Kang Chang if (validator_proto.allow_missing_expiration()) {
198*e7b1675dSTing-Kang Chang builder.AllowMissingExpiration();
199*e7b1675dSTing-Kang Chang }
200*e7b1675dSTing-Kang Chang if (validator_proto.expect_issued_in_the_past()) {
201*e7b1675dSTing-Kang Chang builder.ExpectIssuedInThePast();
202*e7b1675dSTing-Kang Chang }
203*e7b1675dSTing-Kang Chang if (validator_proto.has_now()) {
204*e7b1675dSTing-Kang Chang builder.SetFixedNow(TimestampToTime(validator_proto.now()));
205*e7b1675dSTing-Kang Chang }
206*e7b1675dSTing-Kang Chang if (validator_proto.has_clock_skew()) {
207*e7b1675dSTing-Kang Chang builder.SetClockSkew(
208*e7b1675dSTing-Kang Chang absl::Seconds(validator_proto.clock_skew().seconds()));
209*e7b1675dSTing-Kang Chang }
210*e7b1675dSTing-Kang Chang return builder.Build();
211*e7b1675dSTing-Kang Chang }
212*e7b1675dSTing-Kang Chang
CreateJwtMac(grpc::ServerContext * context,const CreationRequest * request,CreationResponse * response)213*e7b1675dSTing-Kang Chang ::grpc::Status JwtImpl::CreateJwtMac(grpc::ServerContext* context,
214*e7b1675dSTing-Kang Chang const CreationRequest* request,
215*e7b1675dSTing-Kang Chang CreationResponse* response) {
216*e7b1675dSTing-Kang Chang return CreatePrimitiveForRpc<JwtMac>(request, response);
217*e7b1675dSTing-Kang Chang }
218*e7b1675dSTing-Kang Chang
CreateJwtPublicKeySign(grpc::ServerContext * context,const CreationRequest * request,CreationResponse * response)219*e7b1675dSTing-Kang Chang ::grpc::Status JwtImpl::CreateJwtPublicKeySign(grpc::ServerContext* context,
220*e7b1675dSTing-Kang Chang const CreationRequest* request,
221*e7b1675dSTing-Kang Chang CreationResponse* response) {
222*e7b1675dSTing-Kang Chang return CreatePrimitiveForRpc<JwtPublicKeySign>(request, response);
223*e7b1675dSTing-Kang Chang }
224*e7b1675dSTing-Kang Chang
CreateJwtPublicKeyVerify(grpc::ServerContext * context,const CreationRequest * request,CreationResponse * response)225*e7b1675dSTing-Kang Chang ::grpc::Status JwtImpl::CreateJwtPublicKeyVerify(grpc::ServerContext* context,
226*e7b1675dSTing-Kang Chang const CreationRequest* request,
227*e7b1675dSTing-Kang Chang CreationResponse* response) {
228*e7b1675dSTing-Kang Chang return CreatePrimitiveForRpc<JwtPublicKeyVerify>(request, response);
229*e7b1675dSTing-Kang Chang }
230*e7b1675dSTing-Kang Chang
231*e7b1675dSTing-Kang Chang // Computes a MAC and generates a signed compact JWT
ComputeMacAndEncode(grpc::ServerContext * context,const JwtSignRequest * request,JwtSignResponse * response)232*e7b1675dSTing-Kang Chang grpc::Status JwtImpl::ComputeMacAndEncode(grpc::ServerContext* context,
233*e7b1675dSTing-Kang Chang const JwtSignRequest* request,
234*e7b1675dSTing-Kang Chang JwtSignResponse* response) {
235*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<JwtMac>> jwt_mac =
236*e7b1675dSTing-Kang Chang PrimitiveFromSerializedBinaryProtoKeyset<JwtMac>(
237*e7b1675dSTing-Kang Chang request->annotated_keyset());
238*e7b1675dSTing-Kang Chang if (!jwt_mac.ok()) {
239*e7b1675dSTing-Kang Chang response->set_err(std::string(jwt_mac.status().message()));
240*e7b1675dSTing-Kang Chang return grpc::Status::OK;
241*e7b1675dSTing-Kang Chang }
242*e7b1675dSTing-Kang Chang StatusOr<RawJwt> raw_jwt = RawJwtFromProto(request->raw_jwt());
243*e7b1675dSTing-Kang Chang if (!raw_jwt.ok()) {
244*e7b1675dSTing-Kang Chang response->set_err(std::string(raw_jwt.status().message()));
245*e7b1675dSTing-Kang Chang return grpc::Status::OK;
246*e7b1675dSTing-Kang Chang }
247*e7b1675dSTing-Kang Chang StatusOr<std::string> compact =
248*e7b1675dSTing-Kang Chang (*jwt_mac)->ComputeMacAndEncode(*raw_jwt);
249*e7b1675dSTing-Kang Chang if (!compact.ok()) {
250*e7b1675dSTing-Kang Chang response->set_err(std::string(compact.status().message()));
251*e7b1675dSTing-Kang Chang return grpc::Status::OK;
252*e7b1675dSTing-Kang Chang }
253*e7b1675dSTing-Kang Chang response->set_signed_compact_jwt(*compact);
254*e7b1675dSTing-Kang Chang return grpc::Status::OK;
255*e7b1675dSTing-Kang Chang }
256*e7b1675dSTing-Kang Chang
257*e7b1675dSTing-Kang Chang // Verifies a signed compact JWT
VerifyMacAndDecode(grpc::ServerContext * context,const JwtVerifyRequest * request,JwtVerifyResponse * response)258*e7b1675dSTing-Kang Chang grpc::Status JwtImpl::VerifyMacAndDecode(grpc::ServerContext* context,
259*e7b1675dSTing-Kang Chang const JwtVerifyRequest* request,
260*e7b1675dSTing-Kang Chang JwtVerifyResponse* response) {
261*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<JwtMac>> jwt_mac =
262*e7b1675dSTing-Kang Chang PrimitiveFromSerializedBinaryProtoKeyset<JwtMac>(
263*e7b1675dSTing-Kang Chang request->annotated_keyset());
264*e7b1675dSTing-Kang Chang if (!jwt_mac.ok()) {
265*e7b1675dSTing-Kang Chang response->set_err(std::string(jwt_mac.status().message()));
266*e7b1675dSTing-Kang Chang return grpc::Status::OK;
267*e7b1675dSTing-Kang Chang }
268*e7b1675dSTing-Kang Chang StatusOr<crypto::tink::JwtValidator> validator =
269*e7b1675dSTing-Kang Chang JwtValidatorFromProto(request->validator());
270*e7b1675dSTing-Kang Chang StatusOr<VerifiedJwt> verified_jwt =
271*e7b1675dSTing-Kang Chang (*jwt_mac)->VerifyMacAndDecode(request->signed_compact_jwt(), *validator);
272*e7b1675dSTing-Kang Chang if (!verified_jwt.ok()) {
273*e7b1675dSTing-Kang Chang response->set_err(std::string(verified_jwt.status().message()));
274*e7b1675dSTing-Kang Chang return grpc::Status::OK;
275*e7b1675dSTing-Kang Chang }
276*e7b1675dSTing-Kang Chang *response->mutable_verified_jwt() = VerifiedJwtToProto(*verified_jwt);
277*e7b1675dSTing-Kang Chang return grpc::Status::OK;
278*e7b1675dSTing-Kang Chang }
279*e7b1675dSTing-Kang Chang
PublicKeySignAndEncode(grpc::ServerContext * context,const JwtSignRequest * request,JwtSignResponse * response)280*e7b1675dSTing-Kang Chang grpc::Status JwtImpl::PublicKeySignAndEncode(grpc::ServerContext* context,
281*e7b1675dSTing-Kang Chang const JwtSignRequest* request,
282*e7b1675dSTing-Kang Chang JwtSignResponse* response) {
283*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_sign =
284*e7b1675dSTing-Kang Chang PrimitiveFromSerializedBinaryProtoKeyset<JwtPublicKeySign>(
285*e7b1675dSTing-Kang Chang request->annotated_keyset());
286*e7b1675dSTing-Kang Chang if (!jwt_sign.ok()) {
287*e7b1675dSTing-Kang Chang response->set_err(std::string(jwt_sign.status().message()));
288*e7b1675dSTing-Kang Chang return grpc::Status::OK;
289*e7b1675dSTing-Kang Chang }
290*e7b1675dSTing-Kang Chang StatusOr<RawJwt> raw_jwt = RawJwtFromProto(request->raw_jwt());
291*e7b1675dSTing-Kang Chang if (!raw_jwt.ok()) {
292*e7b1675dSTing-Kang Chang response->set_err(std::string(raw_jwt.status().message()));
293*e7b1675dSTing-Kang Chang return grpc::Status::OK;
294*e7b1675dSTing-Kang Chang }
295*e7b1675dSTing-Kang Chang StatusOr<std::string> compact = (*jwt_sign)->SignAndEncode(*raw_jwt);
296*e7b1675dSTing-Kang Chang if (!compact.ok()) {
297*e7b1675dSTing-Kang Chang response->set_err(std::string(compact.status().message()));
298*e7b1675dSTing-Kang Chang return grpc::Status::OK;
299*e7b1675dSTing-Kang Chang }
300*e7b1675dSTing-Kang Chang response->set_signed_compact_jwt(*compact);
301*e7b1675dSTing-Kang Chang return grpc::Status::OK;
302*e7b1675dSTing-Kang Chang }
303*e7b1675dSTing-Kang Chang
PublicKeyVerifyAndDecode(grpc::ServerContext * context,const JwtVerifyRequest * request,JwtVerifyResponse * response)304*e7b1675dSTing-Kang Chang grpc::Status JwtImpl::PublicKeyVerifyAndDecode(grpc::ServerContext* context,
305*e7b1675dSTing-Kang Chang const JwtVerifyRequest* request,
306*e7b1675dSTing-Kang Chang JwtVerifyResponse* response) {
307*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verify =
308*e7b1675dSTing-Kang Chang PrimitiveFromSerializedBinaryProtoKeyset<JwtPublicKeyVerify>(
309*e7b1675dSTing-Kang Chang request->annotated_keyset());
310*e7b1675dSTing-Kang Chang if (!jwt_verify.ok()) {
311*e7b1675dSTing-Kang Chang response->set_err(std::string(jwt_verify.status().message()));
312*e7b1675dSTing-Kang Chang return grpc::Status::OK;
313*e7b1675dSTing-Kang Chang }
314*e7b1675dSTing-Kang Chang StatusOr<crypto::tink::JwtValidator> validator =
315*e7b1675dSTing-Kang Chang JwtValidatorFromProto(request->validator());
316*e7b1675dSTing-Kang Chang StatusOr<VerifiedJwt> verified_jwt =
317*e7b1675dSTing-Kang Chang (*jwt_verify)->VerifyAndDecode(request->signed_compact_jwt(), *validator);
318*e7b1675dSTing-Kang Chang if (!verified_jwt.ok()) {
319*e7b1675dSTing-Kang Chang response->set_err(std::string(verified_jwt.status().message()));
320*e7b1675dSTing-Kang Chang return grpc::Status::OK;
321*e7b1675dSTing-Kang Chang }
322*e7b1675dSTing-Kang Chang *response->mutable_verified_jwt() = VerifiedJwtToProto(*verified_jwt);
323*e7b1675dSTing-Kang Chang return grpc::Status::OK;
324*e7b1675dSTing-Kang Chang }
325*e7b1675dSTing-Kang Chang
ToJwkSet(grpc::ServerContext * context,const JwtToJwkSetRequest * request,JwtToJwkSetResponse * response)326*e7b1675dSTing-Kang Chang ::grpc::Status JwtImpl::ToJwkSet(grpc::ServerContext* context,
327*e7b1675dSTing-Kang Chang const JwtToJwkSetRequest* request,
328*e7b1675dSTing-Kang Chang JwtToJwkSetResponse* response) {
329*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<KeysetReader>> reader =
330*e7b1675dSTing-Kang Chang BinaryKeysetReader::New(request->keyset());
331*e7b1675dSTing-Kang Chang if (!reader.ok()) {
332*e7b1675dSTing-Kang Chang response->set_err(std::string(reader.status().message()));
333*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
334*e7b1675dSTing-Kang Chang }
335*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<::crypto::tink::KeysetHandle>> handle =
336*e7b1675dSTing-Kang Chang CleartextKeysetHandle::Read(*std::move(reader));
337*e7b1675dSTing-Kang Chang if (!handle.ok()) {
338*e7b1675dSTing-Kang Chang response->set_err(std::string(handle.status().message()));
339*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
340*e7b1675dSTing-Kang Chang }
341*e7b1675dSTing-Kang Chang StatusOr<std::string> jwk_set = JwkSetFromPublicKeysetHandle(**handle);
342*e7b1675dSTing-Kang Chang if (!jwk_set.ok()) {
343*e7b1675dSTing-Kang Chang response->set_err(std::string(jwk_set.status().message()));
344*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
345*e7b1675dSTing-Kang Chang }
346*e7b1675dSTing-Kang Chang response->set_jwk_set(*jwk_set);
347*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
348*e7b1675dSTing-Kang Chang }
349*e7b1675dSTing-Kang Chang
FromJwkSet(grpc::ServerContext * context,const JwtFromJwkSetRequest * request,JwtFromJwkSetResponse * response)350*e7b1675dSTing-Kang Chang ::grpc::Status JwtImpl::FromJwkSet(grpc::ServerContext* context,
351*e7b1675dSTing-Kang Chang const JwtFromJwkSetRequest* request,
352*e7b1675dSTing-Kang Chang JwtFromJwkSetResponse* response) {
353*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<::crypto::tink::KeysetHandle>> keyset_handle =
354*e7b1675dSTing-Kang Chang JwkSetToPublicKeysetHandle(request->jwk_set());
355*e7b1675dSTing-Kang Chang if (!keyset_handle.ok()) {
356*e7b1675dSTing-Kang Chang response->set_err(std::string(keyset_handle.status().message()));
357*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
358*e7b1675dSTing-Kang Chang }
359*e7b1675dSTing-Kang Chang std::stringbuf keyset;
360*e7b1675dSTing-Kang Chang StatusOr<std::unique_ptr<crypto::tink::BinaryKeysetWriter>> writer =
361*e7b1675dSTing-Kang Chang BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
362*e7b1675dSTing-Kang Chang if (!writer.ok()) {
363*e7b1675dSTing-Kang Chang response->set_err(std::string(writer.status().message()));
364*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
365*e7b1675dSTing-Kang Chang }
366*e7b1675dSTing-Kang Chang crypto::tink::util::Status status =
367*e7b1675dSTing-Kang Chang CleartextKeysetHandle::Write(writer->get(), **keyset_handle);
368*e7b1675dSTing-Kang Chang if (!status.ok()) {
369*e7b1675dSTing-Kang Chang response->set_err(std::string(status.message()));
370*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
371*e7b1675dSTing-Kang Chang }
372*e7b1675dSTing-Kang Chang response->set_keyset(keyset.str());
373*e7b1675dSTing-Kang Chang return ::grpc::Status::OK;
374*e7b1675dSTing-Kang Chang }
375*e7b1675dSTing-Kang Chang
376*e7b1675dSTing-Kang Chang } // namespace tink_testing_api
377