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