vednor with auth 0.2.1 to minimize multiple token refreshes

This commit is contained in:
Umputun
2019-01-03 15:58:43 -06:00
parent 72a264b771
commit dcd40c42e2
6 changed files with 42 additions and 15 deletions
+22 -6
View File
@@ -2,6 +2,7 @@
package middleware
import (
"math/rand"
"net/http"
"github.com/pkg/errors"
@@ -14,10 +15,11 @@ import (
// Authenticator is top level auth object providing middlewares
type Authenticator struct {
logger.L
JWTService TokenService
Providers []provider.Service
Validator token.Validator
AdminPasswd string
JWTService TokenService
Providers []provider.Service
Validator token.Validator
AdminPasswd string
RefreshFactor int
}
// TokenService defines interface accessing tokens
@@ -96,7 +98,7 @@ func (a *Authenticator) auth(reqAuth bool) func(http.Handler) http.Handler {
return
}
if a.JWTService.IsExpired(claims) {
if a.shouldRefresh(claims) {
if claims, err = a.refreshExpiredToken(w, claims); err != nil {
a.JWTService.Reset(w)
onError(h, w, r, errors.Wrap(err, "can't refresh token"))
@@ -117,7 +119,6 @@ func (a *Authenticator) auth(reqAuth bool) func(http.Handler) http.Handler {
// refreshExpiredToken makes a new token with passed claims
func (a *Authenticator) refreshExpiredToken(w http.ResponseWriter, claims token.Claims) (token.Claims, error) {
claims.ExpiresAt = 0 // this will cause now+duration for refreshed token
if err := a.JWTService.Set(w, claims); err != nil {
return token.Claims{}, err
@@ -125,6 +126,21 @@ func (a *Authenticator) refreshExpiredToken(w http.ResponseWriter, claims token.
return claims, nil
}
// shouldRefresh checks if token expired with an optional random rejection of refresh.
// the goal is to prevent multiple refresh request executed at the same time by allowing only some of them
func (a *Authenticator) shouldRefresh(claims token.Claims) bool {
if !a.JWTService.IsExpired(claims) {
return false
}
// disable randomizing with 0 factor
if a.RefreshFactor == 0 {
return true
}
return rand.Int31n(int32(a.RefreshFactor)) == 0 // randomize selection
}
// AdminOnly middleware allows access for admins only
// this handler internally wrapped with auth(true) to avoid situation if AdminOnly defined without prior Auth
func (a *Authenticator) AdminOnly(next http.Handler) http.Handler {