From 5431dd113eb586066e5a5b9ab4982583903a0730 Mon Sep 17 00:00:00 2001 From: Lou Knauer Date: Mon, 14 Mar 2022 08:50:28 +0100 Subject: [PATCH] Cache decoded tokens (signature check is expensive) --- api.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/api.go b/api.go index 3fca3e5..9244052 100644 --- a/api.go +++ b/api.go @@ -14,6 +14,7 @@ import ( "net/http" "strconv" "strings" + "sync" "time" "github.com/golang-jwt/jwt/v4" @@ -280,6 +281,9 @@ func handleQuery(rw http.ResponseWriter, r *http.Request) { } func authentication(next http.Handler, publicKey ed25519.PublicKey) http.Handler { + cacheLock := sync.RWMutex{} + cache := map[string]*jwt.Token{} + return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { authheader := r.Header.Get("Authorization") if authheader == "" || !strings.HasPrefix(authheader, "Bearer ") { @@ -287,10 +291,20 @@ func authentication(next http.Handler, publicKey ed25519.PublicKey) http.Handler return } + rawtoken := authheader[len("Bearer "):] + cacheLock.RLock() + token, ok := cache[rawtoken] + cacheLock.RUnlock() + if ok && token.Claims.Valid() == nil { + next.ServeHTTP(rw, r) + return + } + // The actual token is ignored for now. // In case expiration and so on are specified, the Parse function // already returns an error for expired tokens. - _, err := jwt.Parse(authheader[len("Bearer "):], func(t *jwt.Token) (interface{}, error) { + var err error + token, err = jwt.Parse(rawtoken, func(t *jwt.Token) (interface{}, error) { if t.Method != jwt.SigningMethodEdDSA { return nil, errors.New("only Ed25519/EdDSA supported") } @@ -303,6 +317,10 @@ func authentication(next http.Handler, publicKey ed25519.PublicKey) http.Handler return } + cacheLock.Lock() + cache[rawtoken] = token + cacheLock.Unlock() + // Let request through... next.ServeHTTP(rw, r) })