|
- 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)
- }
|