jwt.go raw

   1  // Copyright (c) 2016, 2018, 2025, Oracle and/or its affiliates.  All rights reserved.
   2  // This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
   3  
   4  package auth
   5  
   6  import (
   7  	"bytes"
   8  	"encoding/base64"
   9  	"encoding/json"
  10  	"fmt"
  11  	"strings"
  12  	"time"
  13  
  14  	"github.com/nrdcg/oci-go-sdk/common/v1065"
  15  )
  16  
  17  type jwtToken struct {
  18  	raw     string
  19  	header  map[string]interface{}
  20  	payload map[string]interface{}
  21  }
  22  
  23  const bufferTimeBeforeTokenExpiration = 5 * time.Minute
  24  
  25  func (t *jwtToken) expired() bool {
  26  	exp := int64(t.payload["exp"].(float64))
  27  	expTime := time.Unix(exp, 0)
  28  	expired := exp <= time.Now().Unix()+int64(bufferTimeBeforeTokenExpiration.Seconds())
  29  	if expired {
  30  		common.Debugf("Token expires at:  %v, currently expired due to bufferTime: %v", expTime.Format("15:04:05.000"), expired)
  31  	}
  32  	return expired
  33  }
  34  
  35  func parseJwt(tokenString string) (*jwtToken, error) {
  36  	parts := strings.Split(tokenString, ".")
  37  	if len(parts) != 3 {
  38  		return nil, fmt.Errorf("the given token string contains an invalid number of parts")
  39  	}
  40  
  41  	token := &jwtToken{raw: tokenString}
  42  	var err error
  43  
  44  	// Parse Header part
  45  	var headerBytes []byte
  46  	if headerBytes, err = decodePart(parts[0]); err != nil {
  47  		return nil, fmt.Errorf("failed to decode the header bytes: %s", err.Error())
  48  	}
  49  	if err = json.Unmarshal(headerBytes, &token.header); err != nil {
  50  		return nil, err
  51  	}
  52  
  53  	// Parse Payload part
  54  	var payloadBytes []byte
  55  	if payloadBytes, err = decodePart(parts[1]); err != nil {
  56  		return nil, fmt.Errorf("failed to decode the payload bytes: %s", err.Error())
  57  	}
  58  	decoder := json.NewDecoder(bytes.NewBuffer(payloadBytes))
  59  	if err = decoder.Decode(&token.payload); err != nil {
  60  		return nil, fmt.Errorf("failed to decode the payload json: %s", err.Error())
  61  	}
  62  
  63  	return token, nil
  64  }
  65  
  66  func decodePart(partString string) ([]byte, error) {
  67  	if l := len(partString) % 4; 0 < l {
  68  		partString += strings.Repeat("=", 4-l)
  69  	}
  70  	return base64.URLEncoding.DecodeString(partString)
  71  }
  72