| package jwt |
| |
| import ( |
| "encoding/base64" |
| "encoding/json" |
| "strings" |
| "time" |
| ) |
| |
| // TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). |
| // You can override it to use another time value. This is useful for testing or if your |
| // server uses a different time zone than your tokens. |
| var TimeFunc = time.Now |
| |
| // Parse methods use this callback function to supply |
| // the key for verification. The function receives the parsed, |
| // but unverified Token. This allows you to use properties in the |
| // Header of the token (such as `kid`) to identify which key to use. |
| type Keyfunc func(*Token) (interface{}, error) |
| |
| // A JWT Token. Different fields will be used depending on whether you're |
| // creating or parsing/verifying a token. |
| type Token struct { |
| Raw string // The raw token. Populated when you Parse a token |
| Method SigningMethod // The signing method used or to be used |
| Header map[string]interface{} // The first segment of the token |
| Claims Claims // The second segment of the token |
| Signature string // The third segment of the token. Populated when you Parse a token |
| Valid bool // Is the token valid? Populated when you Parse/Verify a token |
| } |
| |
| // Create a new Token. Takes a signing method |
| func New(method SigningMethod) *Token { |
| return NewWithClaims(method, MapClaims{}) |
| } |
| |
| func NewWithClaims(method SigningMethod, claims Claims) *Token { |
| return &Token{ |
| Header: map[string]interface{}{ |
| "typ": "JWT", |
| "alg": method.Alg(), |
| }, |
| Claims: claims, |
| Method: method, |
| } |
| } |
| |
| // Get the complete, signed token |
| func (t *Token) SignedString(key interface{}) (string, error) { |
| var sig, sstr string |
| var err error |
| if sstr, err = t.SigningString(); err != nil { |
| return "", err |
| } |
| if sig, err = t.Method.Sign(sstr, key); err != nil { |
| return "", err |
| } |
| return strings.Join([]string{sstr, sig}, "."), nil |
| } |
| |
| // Generate the signing string. This is the |
| // most expensive part of the whole deal. Unless you |
| // need this for something special, just go straight for |
| // the SignedString. |
| func (t *Token) SigningString() (string, error) { |
| var err error |
| parts := make([]string, 2) |
| for i, _ := range parts { |
| var jsonValue []byte |
| if i == 0 { |
| if jsonValue, err = json.Marshal(t.Header); err != nil { |
| return "", err |
| } |
| } else { |
| if jsonValue, err = json.Marshal(t.Claims); err != nil { |
| return "", err |
| } |
| } |
| |
| parts[i] = EncodeSegment(jsonValue) |
| } |
| return strings.Join(parts, "."), nil |
| } |
| |
| // Parse, validate, and return a token. |
| // keyFunc will receive the parsed token and should return the key for validating. |
| // If everything is kosher, err will be nil |
| func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { |
| return new(Parser).Parse(tokenString, keyFunc) |
| } |
| |
| func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { |
| return new(Parser).ParseWithClaims(tokenString, claims, keyFunc) |
| } |
| |
| // Encode JWT specific base64url encoding with padding stripped |
| func EncodeSegment(seg []byte) string { |
| return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=") |
| } |
| |
| // Decode JWT specific base64url encoding with padding stripped |
| func DecodeSegment(seg string) ([]byte, error) { |
| if l := len(seg) % 4; l > 0 { |
| seg += strings.Repeat("=", 4-l) |
| } |
| |
| return base64.URLEncoding.DecodeString(seg) |
| } |