moved sync out of JWT and added new secret reader

This commit is contained in:
ston1th 2018-01-17 22:33:58 +01:00
commit 9b4adfe863
3 changed files with 82 additions and 33 deletions

37
jwt.go
View file

@ -9,8 +9,8 @@ import (
"encoding/base64"
"encoding/json"
"errors"
"io"
"strings"
"sync"
"time"
)
@ -19,11 +19,15 @@ const (
Header = "Authorization"
// DefaultExpiry is the default token expiration time
DefaultExpiry = time.Hour * 12
// KeySize is the secret key size
KeySize = 64
typ = "JWT"
keySize = 64
typ = "JWT"
)
// DefaultSecretReader is the default secret key generator
var DefaultSecretReader = rand.Reader
var (
ErrNoJWT = errors.New("not a json web token")
ErrEmptyToken = errors.New("token is empty")
@ -37,6 +41,7 @@ var (
ErrMissingTokenParts = errors.New("missing token parts")
ErrEmptySignature = errors.New("token signature is empty")
ErrTokenIsNil = errors.New("token is nil")
ErrInvalidKeySize = errors.New("invalid secret key size")
)
// JWT represents the JSON Web Token signing and blacklisting infrastructure
@ -44,8 +49,6 @@ type JWT struct {
key []byte
expiry time.Duration
// protects list
sync.RWMutex
blacklist Blacklist
done chan struct{}
}
@ -54,12 +57,22 @@ type JWT struct {
// If the timeout is less or equal to zero the default expiry (12 hours) is used.
// If blacklisting is enabled, the JWT object leaks a goroutine to garbage-collect expired blacklisted tokens.
// Call the Stop() method to exit the goroutine.
func New(expiry time.Duration, blacklist Blacklist) *JWT {
func New(expiry time.Duration, blacklist Blacklist, secret io.Reader) (*JWT, error) {
if expiry <= 0 {
expiry = DefaultExpiry
}
key := make([]byte, keySize)
rand.Read(key)
if secret == nil {
secret = DefaultSecretReader
}
secret = io.LimitReader(secret, KeySize)
key := make([]byte, KeySize)
i, err := secret.Read(key)
if err != nil {
return nil, errors.New("secret reader error: " + err.Error())
}
if i < KeySize {
return nil, ErrInvalidKeySize
}
jwt := &JWT{
key: key,
expiry: expiry,
@ -69,7 +82,7 @@ func New(expiry time.Duration, blacklist Blacklist) *JWT {
jwt.done = make(chan struct{})
go jwt.clean()
}
return jwt
return jwt, nil
}
func (jwt *JWT) sum(token string, h Hash) []byte {
@ -107,8 +120,6 @@ func (jwt *JWT) Invalidate(t *Token) error {
if err := jwt.blacklisted(t.Sig()); err != nil {
return err
}
jwt.Lock()
defer jwt.Unlock()
jwt.blacklist.Add(t.Sig(), exp)
return nil
}
@ -118,8 +129,6 @@ func (jwt *JWT) blacklisted(sig string) error {
if sig == "" {
return ErrEmptySignature
}
jwt.RLock()
defer jwt.RUnlock()
if jwt.blacklist.Check(sig) {
return ErrBlacklisted
}
@ -137,13 +146,11 @@ func (jwt *JWT) clean() {
return
}
now := time.Now().UTC().Unix()
jwt.Lock()
for k, v := range jwt.blacklist.Map() {
if now > v {
jwt.blacklist.Remove(k)
}
}
jwt.Unlock()
}
}