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