xref: /aosp_15_r20/external/tink/testing/go/jwt_service.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2022 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 Changpackage services
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Changimport (
20*e7b1675dSTing-Kang Chang	"bytes"
21*e7b1675dSTing-Kang Chang	"context"
22*e7b1675dSTing-Kang Chang	"fmt"
23*e7b1675dSTing-Kang Chang	"time"
24*e7b1675dSTing-Kang Chang
25*e7b1675dSTing-Kang Chang	spb "google.golang.org/protobuf/types/known/structpb"
26*e7b1675dSTing-Kang Chang	tpb "google.golang.org/protobuf/types/known/timestamppb"
27*e7b1675dSTing-Kang Chang	wpb "google.golang.org/protobuf/types/known/wrapperspb"
28*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/insecurecleartextkeyset"
29*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/jwt"
30*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/keyset"
31*e7b1675dSTing-Kang Chang	pb "github.com/google/tink/testing/go/protos/testing_api_go_grpc"
32*e7b1675dSTing-Kang Chang)
33*e7b1675dSTing-Kang Chang
34*e7b1675dSTing-Kang Chang// JWTService implements the JWT testing service.
35*e7b1675dSTing-Kang Changtype JWTService struct {
36*e7b1675dSTing-Kang Chang	pb.JwtServer
37*e7b1675dSTing-Kang Chang}
38*e7b1675dSTing-Kang Chang
39*e7b1675dSTing-Kang Changfunc (s *JWTService) CreateJwtMac(ctx context.Context, req *pb.CreationRequest) (*pb.CreationResponse, error) {
40*e7b1675dSTing-Kang Chang	handle, err := toKeysetHandle(req.GetAnnotatedKeyset())
41*e7b1675dSTing-Kang Chang	if err != nil {
42*e7b1675dSTing-Kang Chang		return &pb.CreationResponse{Err: err.Error()}, nil
43*e7b1675dSTing-Kang Chang	}
44*e7b1675dSTing-Kang Chang	_, err = jwt.NewMAC(handle)
45*e7b1675dSTing-Kang Chang	if err != nil {
46*e7b1675dSTing-Kang Chang		return &pb.CreationResponse{Err: err.Error()}, nil
47*e7b1675dSTing-Kang Chang	}
48*e7b1675dSTing-Kang Chang	return &pb.CreationResponse{}, nil
49*e7b1675dSTing-Kang Chang}
50*e7b1675dSTing-Kang Chang
51*e7b1675dSTing-Kang Changfunc (s *JWTService) CreateJwtPublicKeySign(ctx context.Context, req *pb.CreationRequest) (*pb.CreationResponse, error) {
52*e7b1675dSTing-Kang Chang	handle, err := toKeysetHandle(req.GetAnnotatedKeyset())
53*e7b1675dSTing-Kang Chang	if err != nil {
54*e7b1675dSTing-Kang Chang		return &pb.CreationResponse{Err: err.Error()}, nil
55*e7b1675dSTing-Kang Chang	}
56*e7b1675dSTing-Kang Chang	_, err = jwt.NewSigner(handle)
57*e7b1675dSTing-Kang Chang	if err != nil {
58*e7b1675dSTing-Kang Chang		return &pb.CreationResponse{Err: err.Error()}, nil
59*e7b1675dSTing-Kang Chang	}
60*e7b1675dSTing-Kang Chang	return &pb.CreationResponse{}, nil
61*e7b1675dSTing-Kang Chang}
62*e7b1675dSTing-Kang Chang
63*e7b1675dSTing-Kang Changfunc (s *JWTService) CreateJwtPublicKeyVerify(ctx context.Context, req *pb.CreationRequest) (*pb.CreationResponse, error) {
64*e7b1675dSTing-Kang Chang	handle, err := toKeysetHandle(req.GetAnnotatedKeyset())
65*e7b1675dSTing-Kang Chang	if err != nil {
66*e7b1675dSTing-Kang Chang		return &pb.CreationResponse{Err: err.Error()}, nil
67*e7b1675dSTing-Kang Chang	}
68*e7b1675dSTing-Kang Chang	_, err = jwt.NewVerifier(handle)
69*e7b1675dSTing-Kang Chang	if err != nil {
70*e7b1675dSTing-Kang Chang		return &pb.CreationResponse{Err: err.Error()}, nil
71*e7b1675dSTing-Kang Chang	}
72*e7b1675dSTing-Kang Chang	return &pb.CreationResponse{}, nil
73*e7b1675dSTing-Kang Chang}
74*e7b1675dSTing-Kang Chang
75*e7b1675dSTing-Kang Changfunc refString(s *wpb.StringValue) *string {
76*e7b1675dSTing-Kang Chang	if s == nil {
77*e7b1675dSTing-Kang Chang		return nil
78*e7b1675dSTing-Kang Chang	}
79*e7b1675dSTing-Kang Chang	v := s.GetValue()
80*e7b1675dSTing-Kang Chang	return &v
81*e7b1675dSTing-Kang Chang}
82*e7b1675dSTing-Kang Chang
83*e7b1675dSTing-Kang Changfunc refTime(t *tpb.Timestamp) *time.Time {
84*e7b1675dSTing-Kang Chang	if t == nil {
85*e7b1675dSTing-Kang Chang		return nil
86*e7b1675dSTing-Kang Chang	}
87*e7b1675dSTing-Kang Chang	v := time.Unix(t.GetSeconds(), 0)
88*e7b1675dSTing-Kang Chang	return &v
89*e7b1675dSTing-Kang Chang}
90*e7b1675dSTing-Kang Chang
91*e7b1675dSTing-Kang Changfunc arrayClaimToJSONString(array []interface{}) (string, error) {
92*e7b1675dSTing-Kang Chang	lv, err := spb.NewList(array)
93*e7b1675dSTing-Kang Chang	if err != nil {
94*e7b1675dSTing-Kang Chang		return "", err
95*e7b1675dSTing-Kang Chang	}
96*e7b1675dSTing-Kang Chang	b, err := lv.MarshalJSON()
97*e7b1675dSTing-Kang Chang	if err != nil {
98*e7b1675dSTing-Kang Chang		return "", err
99*e7b1675dSTing-Kang Chang	}
100*e7b1675dSTing-Kang Chang	return string(b), nil
101*e7b1675dSTing-Kang Chang}
102*e7b1675dSTing-Kang Chang
103*e7b1675dSTing-Kang Changfunc jsonStringToArrayClaim(stringArray string) ([]interface{}, error) {
104*e7b1675dSTing-Kang Chang	s := spb.NewListValue(&spb.ListValue{})
105*e7b1675dSTing-Kang Chang	if err := s.UnmarshalJSON([]byte(stringArray)); err != nil {
106*e7b1675dSTing-Kang Chang		return nil, err
107*e7b1675dSTing-Kang Chang	}
108*e7b1675dSTing-Kang Chang	if s.GetListValue() == nil {
109*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("invalid list")
110*e7b1675dSTing-Kang Chang	}
111*e7b1675dSTing-Kang Chang	return s.GetListValue().AsSlice(), nil
112*e7b1675dSTing-Kang Chang}
113*e7b1675dSTing-Kang Chang
114*e7b1675dSTing-Kang Changfunc objectClaimToJSONString(o map[string]interface{}) (string, error) {
115*e7b1675dSTing-Kang Chang	s, err := spb.NewStruct(o)
116*e7b1675dSTing-Kang Chang	if err != nil {
117*e7b1675dSTing-Kang Chang		return "", err
118*e7b1675dSTing-Kang Chang	}
119*e7b1675dSTing-Kang Chang	b, err := s.MarshalJSON()
120*e7b1675dSTing-Kang Chang	if err != nil {
121*e7b1675dSTing-Kang Chang		return "", err
122*e7b1675dSTing-Kang Chang	}
123*e7b1675dSTing-Kang Chang	return string(b), nil
124*e7b1675dSTing-Kang Chang}
125*e7b1675dSTing-Kang Chang
126*e7b1675dSTing-Kang Changfunc jsonStringToObjectClaim(obj string) (map[string]interface{}, error) {
127*e7b1675dSTing-Kang Chang	s := &spb.Struct{}
128*e7b1675dSTing-Kang Chang	if err := s.UnmarshalJSON([]byte(obj)); err != nil {
129*e7b1675dSTing-Kang Chang		return nil, err
130*e7b1675dSTing-Kang Chang	}
131*e7b1675dSTing-Kang Chang	return s.AsMap(), nil
132*e7b1675dSTing-Kang Chang}
133*e7b1675dSTing-Kang Chang
134*e7b1675dSTing-Kang Changfunc customClaimsFromProto(cc map[string]*pb.JwtClaimValue) (map[string]interface{}, error) {
135*e7b1675dSTing-Kang Chang	r := map[string]interface{}{}
136*e7b1675dSTing-Kang Chang	for key, val := range cc {
137*e7b1675dSTing-Kang Chang		switch val.Kind.(type) {
138*e7b1675dSTing-Kang Chang		case *pb.JwtClaimValue_NullValue:
139*e7b1675dSTing-Kang Chang			r[key] = nil
140*e7b1675dSTing-Kang Chang		case *pb.JwtClaimValue_StringValue:
141*e7b1675dSTing-Kang Chang			r[key] = val.GetStringValue()
142*e7b1675dSTing-Kang Chang		case *pb.JwtClaimValue_NumberValue:
143*e7b1675dSTing-Kang Chang			r[key] = val.GetNumberValue()
144*e7b1675dSTing-Kang Chang		case *pb.JwtClaimValue_BoolValue:
145*e7b1675dSTing-Kang Chang			r[key] = val.GetBoolValue()
146*e7b1675dSTing-Kang Chang		case *pb.JwtClaimValue_JsonArrayValue:
147*e7b1675dSTing-Kang Chang			a, err := jsonStringToArrayClaim(val.GetJsonArrayValue())
148*e7b1675dSTing-Kang Chang			if err != nil {
149*e7b1675dSTing-Kang Chang				return nil, err
150*e7b1675dSTing-Kang Chang			}
151*e7b1675dSTing-Kang Chang			r[key] = a
152*e7b1675dSTing-Kang Chang		case *pb.JwtClaimValue_JsonObjectValue:
153*e7b1675dSTing-Kang Chang			o, err := jsonStringToObjectClaim(val.GetJsonObjectValue())
154*e7b1675dSTing-Kang Chang			if err != nil {
155*e7b1675dSTing-Kang Chang				return nil, err
156*e7b1675dSTing-Kang Chang			}
157*e7b1675dSTing-Kang Chang			r[key] = o
158*e7b1675dSTing-Kang Chang		default:
159*e7b1675dSTing-Kang Chang			return nil, fmt.Errorf("unsupported type")
160*e7b1675dSTing-Kang Chang		}
161*e7b1675dSTing-Kang Chang	}
162*e7b1675dSTing-Kang Chang	return r, nil
163*e7b1675dSTing-Kang Chang}
164*e7b1675dSTing-Kang Chang
165*e7b1675dSTing-Kang Changfunc tokenFromProto(t *pb.JwtToken) (*jwt.RawJWT, error) {
166*e7b1675dSTing-Kang Chang	if t == nil {
167*e7b1675dSTing-Kang Chang		return nil, nil
168*e7b1675dSTing-Kang Chang	}
169*e7b1675dSTing-Kang Chang	ccs, err := customClaimsFromProto(t.GetCustomClaims())
170*e7b1675dSTing-Kang Chang	if err != nil {
171*e7b1675dSTing-Kang Chang		return nil, err
172*e7b1675dSTing-Kang Chang	}
173*e7b1675dSTing-Kang Chang	opts := &jwt.RawJWTOptions{
174*e7b1675dSTing-Kang Chang		TypeHeader:   refString(t.GetTypeHeader()),
175*e7b1675dSTing-Kang Chang		Audiences:    t.GetAudiences(),
176*e7b1675dSTing-Kang Chang		Subject:      refString(t.GetSubject()),
177*e7b1675dSTing-Kang Chang		Issuer:       refString(t.GetIssuer()),
178*e7b1675dSTing-Kang Chang		JWTID:        refString(t.GetJwtId()),
179*e7b1675dSTing-Kang Chang		IssuedAt:     refTime(t.GetIssuedAt()),
180*e7b1675dSTing-Kang Chang		NotBefore:    refTime(t.GetNotBefore()),
181*e7b1675dSTing-Kang Chang		ExpiresAt:    refTime(t.GetExpiration()),
182*e7b1675dSTing-Kang Chang		CustomClaims: ccs,
183*e7b1675dSTing-Kang Chang	}
184*e7b1675dSTing-Kang Chang	if opts.ExpiresAt == nil {
185*e7b1675dSTing-Kang Chang		opts.WithoutExpiration = true
186*e7b1675dSTing-Kang Chang	}
187*e7b1675dSTing-Kang Chang	return jwt.NewRawJWT(opts)
188*e7b1675dSTing-Kang Chang}
189*e7b1675dSTing-Kang Chang
190*e7b1675dSTing-Kang Changfunc toStringValue(present bool, getValue func() (string, error), val **wpb.StringValue) error {
191*e7b1675dSTing-Kang Chang	if !present {
192*e7b1675dSTing-Kang Chang		return nil
193*e7b1675dSTing-Kang Chang	}
194*e7b1675dSTing-Kang Chang	v, err := getValue()
195*e7b1675dSTing-Kang Chang	if err != nil {
196*e7b1675dSTing-Kang Chang		return err
197*e7b1675dSTing-Kang Chang	}
198*e7b1675dSTing-Kang Chang	*val = &wpb.StringValue{Value: v}
199*e7b1675dSTing-Kang Chang	return nil
200*e7b1675dSTing-Kang Chang}
201*e7b1675dSTing-Kang Chang
202*e7b1675dSTing-Kang Changfunc toTimeValue(present bool, getValue func() (time.Time, error), val **tpb.Timestamp) error {
203*e7b1675dSTing-Kang Chang	if !present {
204*e7b1675dSTing-Kang Chang		return nil
205*e7b1675dSTing-Kang Chang	}
206*e7b1675dSTing-Kang Chang	v, err := getValue()
207*e7b1675dSTing-Kang Chang	if err != nil {
208*e7b1675dSTing-Kang Chang		return err
209*e7b1675dSTing-Kang Chang	}
210*e7b1675dSTing-Kang Chang	*val = &tpb.Timestamp{Seconds: v.Unix()}
211*e7b1675dSTing-Kang Chang	return nil
212*e7b1675dSTing-Kang Chang}
213*e7b1675dSTing-Kang Chang
214*e7b1675dSTing-Kang Changfunc tokenToProto(v *jwt.VerifiedJWT) (*pb.JwtToken, error) {
215*e7b1675dSTing-Kang Chang	t := &pb.JwtToken{
216*e7b1675dSTing-Kang Chang		CustomClaims: map[string]*pb.JwtClaimValue{},
217*e7b1675dSTing-Kang Chang	}
218*e7b1675dSTing-Kang Chang	if err := toStringValue(v.HasTypeHeader(), v.TypeHeader, &t.TypeHeader); err != nil {
219*e7b1675dSTing-Kang Chang		return nil, err
220*e7b1675dSTing-Kang Chang	}
221*e7b1675dSTing-Kang Chang	if err := toStringValue(v.HasIssuer(), v.Issuer, &t.Issuer); err != nil {
222*e7b1675dSTing-Kang Chang		return nil, err
223*e7b1675dSTing-Kang Chang	}
224*e7b1675dSTing-Kang Chang	if err := toStringValue(v.HasSubject(), v.Subject, &t.Subject); err != nil {
225*e7b1675dSTing-Kang Chang		return nil, err
226*e7b1675dSTing-Kang Chang	}
227*e7b1675dSTing-Kang Chang	if err := toStringValue(v.HasJWTID(), v.JWTID, &t.JwtId); err != nil {
228*e7b1675dSTing-Kang Chang		return nil, err
229*e7b1675dSTing-Kang Chang	}
230*e7b1675dSTing-Kang Chang	if err := toTimeValue(v.HasExpiration(), v.ExpiresAt, &t.Expiration); err != nil {
231*e7b1675dSTing-Kang Chang		return nil, err
232*e7b1675dSTing-Kang Chang	}
233*e7b1675dSTing-Kang Chang	if err := toTimeValue(v.HasIssuedAt(), v.IssuedAt, &t.IssuedAt); err != nil {
234*e7b1675dSTing-Kang Chang		return nil, err
235*e7b1675dSTing-Kang Chang	}
236*e7b1675dSTing-Kang Chang	if err := toTimeValue(v.HasNotBefore(), v.NotBefore, &t.NotBefore); err != nil {
237*e7b1675dSTing-Kang Chang		return nil, err
238*e7b1675dSTing-Kang Chang	}
239*e7b1675dSTing-Kang Chang	if v.HasAudiences() {
240*e7b1675dSTing-Kang Chang		aud, err := v.Audiences()
241*e7b1675dSTing-Kang Chang		if err != nil {
242*e7b1675dSTing-Kang Chang			return nil, err
243*e7b1675dSTing-Kang Chang		}
244*e7b1675dSTing-Kang Chang		t.Audiences = aud
245*e7b1675dSTing-Kang Chang	}
246*e7b1675dSTing-Kang Chang
247*e7b1675dSTing-Kang Chang	for _, name := range v.CustomClaimNames() {
248*e7b1675dSTing-Kang Chang		if v.HasArrayClaim(name) {
249*e7b1675dSTing-Kang Chang			array, err := v.ArrayClaim(name)
250*e7b1675dSTing-Kang Chang			if err != nil {
251*e7b1675dSTing-Kang Chang				return nil, err
252*e7b1675dSTing-Kang Chang			}
253*e7b1675dSTing-Kang Chang			s, err := arrayClaimToJSONString(array)
254*e7b1675dSTing-Kang Chang			if err != nil {
255*e7b1675dSTing-Kang Chang				return nil, err
256*e7b1675dSTing-Kang Chang			}
257*e7b1675dSTing-Kang Chang			t.CustomClaims[name] = &pb.JwtClaimValue{Kind: &pb.JwtClaimValue_JsonArrayValue{JsonArrayValue: s}}
258*e7b1675dSTing-Kang Chang			continue
259*e7b1675dSTing-Kang Chang		}
260*e7b1675dSTing-Kang Chang		if v.HasObjectClaim(name) {
261*e7b1675dSTing-Kang Chang			m, err := v.ObjectClaim(name)
262*e7b1675dSTing-Kang Chang			if err != nil {
263*e7b1675dSTing-Kang Chang				return nil, err
264*e7b1675dSTing-Kang Chang			}
265*e7b1675dSTing-Kang Chang			o, err := objectClaimToJSONString(m)
266*e7b1675dSTing-Kang Chang			if err != nil {
267*e7b1675dSTing-Kang Chang				return nil, err
268*e7b1675dSTing-Kang Chang			}
269*e7b1675dSTing-Kang Chang			t.CustomClaims[name] = &pb.JwtClaimValue{Kind: &pb.JwtClaimValue_JsonObjectValue{JsonObjectValue: o}}
270*e7b1675dSTing-Kang Chang			continue
271*e7b1675dSTing-Kang Chang		}
272*e7b1675dSTing-Kang Chang		if v.HasNullClaim(name) {
273*e7b1675dSTing-Kang Chang			t.CustomClaims[name] = &pb.JwtClaimValue{Kind: &pb.JwtClaimValue_NullValue{}}
274*e7b1675dSTing-Kang Chang			continue
275*e7b1675dSTing-Kang Chang		}
276*e7b1675dSTing-Kang Chang		if v.HasStringClaim(name) {
277*e7b1675dSTing-Kang Chang			s, err := v.StringClaim(name)
278*e7b1675dSTing-Kang Chang			if err != nil {
279*e7b1675dSTing-Kang Chang				return nil, err
280*e7b1675dSTing-Kang Chang			}
281*e7b1675dSTing-Kang Chang			t.CustomClaims[name] = &pb.JwtClaimValue{Kind: &pb.JwtClaimValue_StringValue{StringValue: s}}
282*e7b1675dSTing-Kang Chang			continue
283*e7b1675dSTing-Kang Chang		}
284*e7b1675dSTing-Kang Chang		if v.HasBooleanClaim(name) {
285*e7b1675dSTing-Kang Chang			b, err := v.BooleanClaim(name)
286*e7b1675dSTing-Kang Chang			if err != nil {
287*e7b1675dSTing-Kang Chang				return nil, err
288*e7b1675dSTing-Kang Chang			}
289*e7b1675dSTing-Kang Chang			t.CustomClaims[name] = &pb.JwtClaimValue{Kind: &pb.JwtClaimValue_BoolValue{BoolValue: b}}
290*e7b1675dSTing-Kang Chang			continue
291*e7b1675dSTing-Kang Chang		}
292*e7b1675dSTing-Kang Chang		if v.HasNumberClaim(name) {
293*e7b1675dSTing-Kang Chang			n, err := v.NumberClaim(name)
294*e7b1675dSTing-Kang Chang			if err != nil {
295*e7b1675dSTing-Kang Chang				return nil, err
296*e7b1675dSTing-Kang Chang			}
297*e7b1675dSTing-Kang Chang			t.CustomClaims[name] = &pb.JwtClaimValue{Kind: &pb.JwtClaimValue_NumberValue{NumberValue: n}}
298*e7b1675dSTing-Kang Chang			continue
299*e7b1675dSTing-Kang Chang		}
300*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("claim %q of unsupported type", name)
301*e7b1675dSTing-Kang Chang	}
302*e7b1675dSTing-Kang Chang
303*e7b1675dSTing-Kang Chang	return t, nil
304*e7b1675dSTing-Kang Chang}
305*e7b1675dSTing-Kang Chang
306*e7b1675dSTing-Kang Changfunc validatorFromProto(v *pb.JwtValidator) (*jwt.Validator, error) {
307*e7b1675dSTing-Kang Chang	fixedNow := time.Now()
308*e7b1675dSTing-Kang Chang	if v.GetNow() != nil {
309*e7b1675dSTing-Kang Chang		fixedNow = *refTime(v.GetNow())
310*e7b1675dSTing-Kang Chang	}
311*e7b1675dSTing-Kang Chang	opts := &jwt.ValidatorOpts{
312*e7b1675dSTing-Kang Chang		ExpectedTypeHeader:     refString(v.GetExpectedTypeHeader()),
313*e7b1675dSTing-Kang Chang		ExpectedAudience:       refString(v.GetExpectedAudience()),
314*e7b1675dSTing-Kang Chang		ExpectedIssuer:         refString(v.GetExpectedIssuer()),
315*e7b1675dSTing-Kang Chang		ExpectIssuedInThePast:  v.GetExpectIssuedInThePast(),
316*e7b1675dSTing-Kang Chang		AllowMissingExpiration: v.GetAllowMissingExpiration(),
317*e7b1675dSTing-Kang Chang		IgnoreTypeHeader:       v.GetIgnoreTypeHeader(),
318*e7b1675dSTing-Kang Chang		IgnoreAudiences:        v.GetIgnoreAudience(),
319*e7b1675dSTing-Kang Chang		IgnoreIssuer:           v.GetIgnoreIssuer(),
320*e7b1675dSTing-Kang Chang		FixedNow:               fixedNow,
321*e7b1675dSTing-Kang Chang		ClockSkew:              time.Duration(v.GetClockSkew().GetSeconds()) * time.Second,
322*e7b1675dSTing-Kang Chang	}
323*e7b1675dSTing-Kang Chang	return jwt.NewValidator(opts)
324*e7b1675dSTing-Kang Chang}
325*e7b1675dSTing-Kang Chang
326*e7b1675dSTing-Kang Changfunc jwtSignResponseError(err error) *pb.JwtSignResponse {
327*e7b1675dSTing-Kang Chang	return &pb.JwtSignResponse{
328*e7b1675dSTing-Kang Chang		Result: &pb.JwtSignResponse_Err{err.Error()}}
329*e7b1675dSTing-Kang Chang}
330*e7b1675dSTing-Kang Chang
331*e7b1675dSTing-Kang Changfunc jwtVerifyResponseError(err error) *pb.JwtVerifyResponse {
332*e7b1675dSTing-Kang Chang	return &pb.JwtVerifyResponse{
333*e7b1675dSTing-Kang Chang		Result: &pb.JwtVerifyResponse_Err{err.Error()}}
334*e7b1675dSTing-Kang Chang}
335*e7b1675dSTing-Kang Chang
336*e7b1675dSTing-Kang Changfunc jwtToJWKSetResponseError(err error) *pb.JwtToJwkSetResponse {
337*e7b1675dSTing-Kang Chang	return &pb.JwtToJwkSetResponse{
338*e7b1675dSTing-Kang Chang		Result: &pb.JwtToJwkSetResponse_Err{err.Error()}}
339*e7b1675dSTing-Kang Chang}
340*e7b1675dSTing-Kang Chang
341*e7b1675dSTing-Kang Changfunc jwtFromJwkSetResponseError(err error) *pb.JwtFromJwkSetResponse {
342*e7b1675dSTing-Kang Chang	return &pb.JwtFromJwkSetResponse{
343*e7b1675dSTing-Kang Chang		Result: &pb.JwtFromJwkSetResponse_Err{err.Error()}}
344*e7b1675dSTing-Kang Chang}
345*e7b1675dSTing-Kang Chang
346*e7b1675dSTing-Kang Changfunc (s *JWTService) ComputeMacAndEncode(ctx context.Context, req *pb.JwtSignRequest) (*pb.JwtSignResponse, error) {
347*e7b1675dSTing-Kang Chang	handle, err := toKeysetHandle(req.GetAnnotatedKeyset())
348*e7b1675dSTing-Kang Chang	if err != nil {
349*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
350*e7b1675dSTing-Kang Chang	}
351*e7b1675dSTing-Kang Chang	primitive, err := jwt.NewMAC(handle)
352*e7b1675dSTing-Kang Chang	if err != nil {
353*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
354*e7b1675dSTing-Kang Chang	}
355*e7b1675dSTing-Kang Chang	rawJWT, err := tokenFromProto(req.GetRawJwt())
356*e7b1675dSTing-Kang Chang	if err != nil {
357*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
358*e7b1675dSTing-Kang Chang	}
359*e7b1675dSTing-Kang Chang	compact, err := primitive.ComputeMACAndEncode(rawJWT)
360*e7b1675dSTing-Kang Chang	if err != nil {
361*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
362*e7b1675dSTing-Kang Chang	}
363*e7b1675dSTing-Kang Chang	return &pb.JwtSignResponse{
364*e7b1675dSTing-Kang Chang		Result: &pb.JwtSignResponse_SignedCompactJwt{compact},
365*e7b1675dSTing-Kang Chang	}, nil
366*e7b1675dSTing-Kang Chang}
367*e7b1675dSTing-Kang Chang
368*e7b1675dSTing-Kang Changfunc (s *JWTService) VerifyMacAndDecode(ctx context.Context, req *pb.JwtVerifyRequest) (*pb.JwtVerifyResponse, error) {
369*e7b1675dSTing-Kang Chang	handle, err := toKeysetHandle(req.GetAnnotatedKeyset())
370*e7b1675dSTing-Kang Chang	if err != nil {
371*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
372*e7b1675dSTing-Kang Chang	}
373*e7b1675dSTing-Kang Chang	primitive, err := jwt.NewMAC(handle)
374*e7b1675dSTing-Kang Chang	if err != nil {
375*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
376*e7b1675dSTing-Kang Chang	}
377*e7b1675dSTing-Kang Chang	validator, err := validatorFromProto(req.GetValidator())
378*e7b1675dSTing-Kang Chang	if err != nil {
379*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
380*e7b1675dSTing-Kang Chang	}
381*e7b1675dSTing-Kang Chang	verified, err := primitive.VerifyMACAndDecode(req.GetSignedCompactJwt(), validator)
382*e7b1675dSTing-Kang Chang	if err != nil {
383*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
384*e7b1675dSTing-Kang Chang	}
385*e7b1675dSTing-Kang Chang	verifiedJWT, err := tokenToProto(verified)
386*e7b1675dSTing-Kang Chang	if err != nil {
387*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
388*e7b1675dSTing-Kang Chang	}
389*e7b1675dSTing-Kang Chang	return &pb.JwtVerifyResponse{
390*e7b1675dSTing-Kang Chang		Result: &pb.JwtVerifyResponse_VerifiedJwt{verifiedJWT},
391*e7b1675dSTing-Kang Chang	}, nil
392*e7b1675dSTing-Kang Chang}
393*e7b1675dSTing-Kang Chang
394*e7b1675dSTing-Kang Changfunc (s *JWTService) PublicKeySignAndEncode(ctx context.Context, req *pb.JwtSignRequest) (*pb.JwtSignResponse, error) {
395*e7b1675dSTing-Kang Chang	handle, err := toKeysetHandle(req.GetAnnotatedKeyset())
396*e7b1675dSTing-Kang Chang	if err != nil {
397*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
398*e7b1675dSTing-Kang Chang	}
399*e7b1675dSTing-Kang Chang	signer, err := jwt.NewSigner(handle)
400*e7b1675dSTing-Kang Chang	if err != nil {
401*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
402*e7b1675dSTing-Kang Chang	}
403*e7b1675dSTing-Kang Chang	rawJWT, err := tokenFromProto(req.GetRawJwt())
404*e7b1675dSTing-Kang Chang	if err != nil {
405*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
406*e7b1675dSTing-Kang Chang	}
407*e7b1675dSTing-Kang Chang	compact, err := signer.SignAndEncode(rawJWT)
408*e7b1675dSTing-Kang Chang	if err != nil {
409*e7b1675dSTing-Kang Chang		return jwtSignResponseError(err), nil
410*e7b1675dSTing-Kang Chang	}
411*e7b1675dSTing-Kang Chang	return &pb.JwtSignResponse{
412*e7b1675dSTing-Kang Chang		Result: &pb.JwtSignResponse_SignedCompactJwt{compact},
413*e7b1675dSTing-Kang Chang	}, nil
414*e7b1675dSTing-Kang Chang}
415*e7b1675dSTing-Kang Chang
416*e7b1675dSTing-Kang Changfunc (s *JWTService) PublicKeyVerifyAndDecode(ctx context.Context, req *pb.JwtVerifyRequest) (*pb.JwtVerifyResponse, error) {
417*e7b1675dSTing-Kang Chang
418*e7b1675dSTing-Kang Chang	handle, err := toKeysetHandle(req.GetAnnotatedKeyset())
419*e7b1675dSTing-Kang Chang	if err != nil {
420*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
421*e7b1675dSTing-Kang Chang	}
422*e7b1675dSTing-Kang Chang	verifier, err := jwt.NewVerifier(handle)
423*e7b1675dSTing-Kang Chang	if err != nil {
424*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
425*e7b1675dSTing-Kang Chang	}
426*e7b1675dSTing-Kang Chang	validator, err := validatorFromProto(req.GetValidator())
427*e7b1675dSTing-Kang Chang	if err != nil {
428*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
429*e7b1675dSTing-Kang Chang	}
430*e7b1675dSTing-Kang Chang	verified, err := verifier.VerifyAndDecode(req.GetSignedCompactJwt(), validator)
431*e7b1675dSTing-Kang Chang	if err != nil {
432*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
433*e7b1675dSTing-Kang Chang	}
434*e7b1675dSTing-Kang Chang	verifiedJWT, err := tokenToProto(verified)
435*e7b1675dSTing-Kang Chang	if err != nil {
436*e7b1675dSTing-Kang Chang		return jwtVerifyResponseError(err), nil
437*e7b1675dSTing-Kang Chang	}
438*e7b1675dSTing-Kang Chang	return &pb.JwtVerifyResponse{
439*e7b1675dSTing-Kang Chang		Result: &pb.JwtVerifyResponse_VerifiedJwt{verifiedJWT},
440*e7b1675dSTing-Kang Chang	}, nil
441*e7b1675dSTing-Kang Chang}
442*e7b1675dSTing-Kang Chang
443*e7b1675dSTing-Kang Changfunc (s *JWTService) ToJwkSet(ctx context.Context, req *pb.JwtToJwkSetRequest) (*pb.JwtToJwkSetResponse, error) {
444*e7b1675dSTing-Kang Chang	ks, err := keyset.NewBinaryReader(bytes.NewReader(req.GetKeyset())).Read()
445*e7b1675dSTing-Kang Chang	if err != nil {
446*e7b1675dSTing-Kang Chang		return jwtToJWKSetResponseError(err), nil
447*e7b1675dSTing-Kang Chang	}
448*e7b1675dSTing-Kang Chang	handle, err := keyset.NewHandleWithNoSecrets(ks)
449*e7b1675dSTing-Kang Chang	if err != nil {
450*e7b1675dSTing-Kang Chang		return jwtToJWKSetResponseError(err), nil
451*e7b1675dSTing-Kang Chang	}
452*e7b1675dSTing-Kang Chang	jwkSet, err := jwt.JWKSetFromPublicKeysetHandle(handle)
453*e7b1675dSTing-Kang Chang	if err != nil {
454*e7b1675dSTing-Kang Chang		return jwtToJWKSetResponseError(err), nil
455*e7b1675dSTing-Kang Chang	}
456*e7b1675dSTing-Kang Chang	return &pb.JwtToJwkSetResponse{
457*e7b1675dSTing-Kang Chang		Result: &pb.JwtToJwkSetResponse_JwkSet{string(jwkSet)},
458*e7b1675dSTing-Kang Chang	}, nil
459*e7b1675dSTing-Kang Chang}
460*e7b1675dSTing-Kang Chang
461*e7b1675dSTing-Kang Changfunc (s *JWTService) FromJwkSet(ctx context.Context, req *pb.JwtFromJwkSetRequest) (*pb.JwtFromJwkSetResponse, error) {
462*e7b1675dSTing-Kang Chang	handle, err := jwt.JWKSetToPublicKeysetHandle([]byte(req.GetJwkSet()))
463*e7b1675dSTing-Kang Chang	if err != nil {
464*e7b1675dSTing-Kang Chang		return jwtFromJwkSetResponseError(err), nil
465*e7b1675dSTing-Kang Chang	}
466*e7b1675dSTing-Kang Chang	b := &bytes.Buffer{}
467*e7b1675dSTing-Kang Chang	if err := insecurecleartextkeyset.Write(handle, keyset.NewBinaryWriter(b)); err != nil {
468*e7b1675dSTing-Kang Chang		return jwtFromJwkSetResponseError(err), nil
469*e7b1675dSTing-Kang Chang	}
470*e7b1675dSTing-Kang Chang	return &pb.JwtFromJwkSetResponse{
471*e7b1675dSTing-Kang Chang		Result: &pb.JwtFromJwkSetResponse_Keyset{b.Bytes()},
472*e7b1675dSTing-Kang Chang	}, nil
473*e7b1675dSTing-Kang Chang}
474