blob: d637e0867c65bce725f9b08da469111ed7cf05e9 [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001package jwt
2
3import (
4 "encoding/base64"
5 "encoding/json"
6 "strings"
7 "time"
8)
9
10// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
11// You can override it to use another time value. This is useful for testing or if your
12// server uses a different time zone than your tokens.
13var TimeFunc = time.Now
14
15// Parse methods use this callback function to supply
16// the key for verification. The function receives the parsed,
17// but unverified Token. This allows you to use properties in the
18// Header of the token (such as `kid`) to identify which key to use.
19type Keyfunc func(*Token) (interface{}, error)
20
21// A JWT Token. Different fields will be used depending on whether you're
22// creating or parsing/verifying a token.
23type Token struct {
24 Raw string // The raw token. Populated when you Parse a token
25 Method SigningMethod // The signing method used or to be used
26 Header map[string]interface{} // The first segment of the token
27 Claims Claims // The second segment of the token
28 Signature string // The third segment of the token. Populated when you Parse a token
29 Valid bool // Is the token valid? Populated when you Parse/Verify a token
30}
31
32// Create a new Token. Takes a signing method
33func New(method SigningMethod) *Token {
34 return NewWithClaims(method, MapClaims{})
35}
36
37func NewWithClaims(method SigningMethod, claims Claims) *Token {
38 return &Token{
39 Header: map[string]interface{}{
40 "typ": "JWT",
41 "alg": method.Alg(),
42 },
43 Claims: claims,
44 Method: method,
45 }
46}
47
48// Get the complete, signed token
49func (t *Token) SignedString(key interface{}) (string, error) {
50 var sig, sstr string
51 var err error
52 if sstr, err = t.SigningString(); err != nil {
53 return "", err
54 }
55 if sig, err = t.Method.Sign(sstr, key); err != nil {
56 return "", err
57 }
58 return strings.Join([]string{sstr, sig}, "."), nil
59}
60
61// Generate the signing string. This is the
62// most expensive part of the whole deal. Unless you
63// need this for something special, just go straight for
64// the SignedString.
65func (t *Token) SigningString() (string, error) {
66 var err error
67 parts := make([]string, 2)
68 for i, _ := range parts {
69 var jsonValue []byte
70 if i == 0 {
71 if jsonValue, err = json.Marshal(t.Header); err != nil {
72 return "", err
73 }
74 } else {
75 if jsonValue, err = json.Marshal(t.Claims); err != nil {
76 return "", err
77 }
78 }
79
80 parts[i] = EncodeSegment(jsonValue)
81 }
82 return strings.Join(parts, "."), nil
83}
84
85// Parse, validate, and return a token.
86// keyFunc will receive the parsed token and should return the key for validating.
87// If everything is kosher, err will be nil
88func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
89 return new(Parser).Parse(tokenString, keyFunc)
90}
91
92func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
93 return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
94}
95
96// Encode JWT specific base64url encoding with padding stripped
97func EncodeSegment(seg []byte) string {
98 return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
99}
100
101// Decode JWT specific base64url encoding with padding stripped
102func DecodeSegment(seg string) ([]byte, error) {
103 if l := len(seg) % 4; l > 0 {
104 seg += strings.Repeat("=", 4-l)
105 }
106
107 return base64.URLEncoding.DecodeString(seg)
108}