| Abhay Kumar | a2ae599 | 2025-11-10 14:02:24 +0000 | [diff] [blame^] | 1 | package jwt |
| 2 | |
| 3 | import ( |
| 4 | "crypto" |
| 5 | "encoding/base64" |
| 6 | "encoding/json" |
| 7 | ) |
| 8 | |
| 9 | // Keyfunc will be used by the Parse methods as a callback function to supply |
| 10 | // the key for verification. The function receives the parsed, but unverified |
| 11 | // Token. This allows you to use properties in the Header of the token (such as |
| 12 | // `kid`) to identify which key to use. |
| 13 | // |
| 14 | // The returned interface{} may be a single key or a VerificationKeySet containing |
| 15 | // multiple keys. |
| 16 | type Keyfunc func(*Token) (interface{}, error) |
| 17 | |
| 18 | // VerificationKey represents a public or secret key for verifying a token's signature. |
| 19 | type VerificationKey interface { |
| 20 | crypto.PublicKey | []uint8 |
| 21 | } |
| 22 | |
| 23 | // VerificationKeySet is a set of public or secret keys. It is used by the parser to verify a token. |
| 24 | type VerificationKeySet struct { |
| 25 | Keys []VerificationKey |
| 26 | } |
| 27 | |
| 28 | // Token represents a JWT Token. Different fields will be used depending on |
| 29 | // whether you're creating or parsing/verifying a token. |
| 30 | type Token struct { |
| 31 | Raw string // Raw contains the raw token. Populated when you [Parse] a token |
| 32 | Method SigningMethod // Method is the signing method used or to be used |
| 33 | Header map[string]interface{} // Header is the first segment of the token in decoded form |
| 34 | Claims Claims // Claims is the second segment of the token in decoded form |
| 35 | Signature []byte // Signature is the third segment of the token in decoded form. Populated when you Parse a token |
| 36 | Valid bool // Valid specifies if the token is valid. Populated when you Parse/Verify a token |
| 37 | } |
| 38 | |
| 39 | // New creates a new [Token] with the specified signing method and an empty map |
| 40 | // of claims. Additional options can be specified, but are currently unused. |
| 41 | func New(method SigningMethod, opts ...TokenOption) *Token { |
| 42 | return NewWithClaims(method, MapClaims{}, opts...) |
| 43 | } |
| 44 | |
| 45 | // NewWithClaims creates a new [Token] with the specified signing method and |
| 46 | // claims. Additional options can be specified, but are currently unused. |
| 47 | func NewWithClaims(method SigningMethod, claims Claims, opts ...TokenOption) *Token { |
| 48 | return &Token{ |
| 49 | Header: map[string]interface{}{ |
| 50 | "typ": "JWT", |
| 51 | "alg": method.Alg(), |
| 52 | }, |
| 53 | Claims: claims, |
| 54 | Method: method, |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | // SignedString creates and returns a complete, signed JWT. The token is signed |
| 59 | // using the SigningMethod specified in the token. Please refer to |
| 60 | // https://golang-jwt.github.io/jwt/usage/signing_methods/#signing-methods-and-key-types |
| 61 | // for an overview of the different signing methods and their respective key |
| 62 | // types. |
| 63 | func (t *Token) SignedString(key interface{}) (string, error) { |
| 64 | sstr, err := t.SigningString() |
| 65 | if err != nil { |
| 66 | return "", err |
| 67 | } |
| 68 | |
| 69 | sig, err := t.Method.Sign(sstr, key) |
| 70 | if err != nil { |
| 71 | return "", err |
| 72 | } |
| 73 | |
| 74 | return sstr + "." + t.EncodeSegment(sig), nil |
| 75 | } |
| 76 | |
| 77 | // SigningString generates the signing string. This is the most expensive part |
| 78 | // of the whole deal. Unless you need this for something special, just go |
| 79 | // straight for the SignedString. |
| 80 | func (t *Token) SigningString() (string, error) { |
| 81 | h, err := json.Marshal(t.Header) |
| 82 | if err != nil { |
| 83 | return "", err |
| 84 | } |
| 85 | |
| 86 | c, err := json.Marshal(t.Claims) |
| 87 | if err != nil { |
| 88 | return "", err |
| 89 | } |
| 90 | |
| 91 | return t.EncodeSegment(h) + "." + t.EncodeSegment(c), nil |
| 92 | } |
| 93 | |
| 94 | // EncodeSegment encodes a JWT specific base64url encoding with padding |
| 95 | // stripped. In the future, this function might take into account a |
| 96 | // [TokenOption]. Therefore, this function exists as a method of [Token], rather |
| 97 | // than a global function. |
| 98 | func (*Token) EncodeSegment(seg []byte) string { |
| 99 | return base64.RawURLEncoding.EncodeToString(seg) |
| 100 | } |