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