1// Copyright 2022 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 17package jwt 18 19import ( 20 "fmt" 21 22 "github.com/google/tink/go/tink" 23) 24 25// macWithKID implements the JWTMAC internal interface. 26type macWithKID struct { 27 tm tink.MAC 28 algorithm string 29 customKID *string 30} 31 32// newMACWithKID creates a new JWTMACwithKID instance. 33func newMACWithKID(tm tink.MAC, algorithm string, customKID *string) (*macWithKID, error) { 34 if tm == nil { 35 return nil, fmt.Errorf("invalid mac") 36 } 37 return &macWithKID{ 38 tm: tm, 39 algorithm: algorithm, 40 customKID: customKID, 41 }, nil 42} 43 44// ComputeMACAndEncodeWithKID computes a MAC over a jwt token and encodes it using compact serialization. 45func (jm *macWithKID) ComputeMACAndEncodeWithKID(token *RawJWT, kid *string) (string, error) { 46 unsigned, err := createUnsigned(token, jm.algorithm, kid, jm.customKID) 47 if err != nil { 48 return "", err 49 } 50 tag, err := jm.tm.ComputeMAC([]byte(unsigned)) 51 if err != nil { 52 return "", err 53 } 54 return combineUnsignedAndSignature(unsigned, tag), nil 55} 56 57// VerifyMACAndDecodeWithKID verifies a MAC in a compact serialized JWT and returns a VerifiedJWT or an error. 58func (jm *macWithKID) VerifyMACAndDecodeWithKID(compact string, verifier *Validator, kid *string) (*VerifiedJWT, error) { 59 tag, content, err := splitSignedCompact(compact) 60 if err != nil { 61 return nil, errJwtVerification 62 } 63 if err := jm.tm.VerifyMAC(tag, []byte(content)); err != nil { 64 return nil, errJwtVerification 65 } 66 rawJWT, err := decodeUnsignedTokenAndValidateHeader(content, jm.algorithm, kid, jm.customKID) 67 if err != nil { 68 return nil, errJwtVerification 69 } 70 if err := verifier.Validate(rawJWT); err != nil { 71 return nil, err 72 } 73 return newVerifiedJWT(rawJWT) 74} 75