1package 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} 109