@@ -22,6 +22,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/klog"
|
||||
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
@@ -53,22 +54,28 @@ func (s *jwtTokenIssuer) Verify(tokenString string) (User, error) {
|
||||
if len(tokenString) == 0 {
|
||||
return nil, errInvalidToken
|
||||
}
|
||||
_, err := s.cache.Get(tokenCacheKey(tokenString))
|
||||
|
||||
if err != nil {
|
||||
if err == cache.ErrNoSuchKey {
|
||||
return nil, errTokenExpired
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clm := &Claims{}
|
||||
|
||||
_, err = jwt.ParseWithClaims(tokenString, clm, s.keyFunc)
|
||||
_, err := jwt.ParseWithClaims(tokenString, clm, s.keyFunc)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 0 means no expiration.
|
||||
// validate token cache
|
||||
if s.options.OAuthOptions.AccessTokenMaxAge > 0 {
|
||||
_, err = s.cache.Get(tokenCacheKey(tokenString))
|
||||
|
||||
if err != nil {
|
||||
if err == cache.ErrNoSuchKey {
|
||||
return nil, errTokenExpired
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &user.DefaultInfo{Name: clm.Username, UID: clm.UID}, nil
|
||||
}
|
||||
|
||||
@@ -92,16 +99,28 @@ func (s *jwtTokenIssuer) IssueTo(user User, expiresIn time.Duration) (string, er
|
||||
tokenString, err := token.SignedString([]byte(s.options.JwtSecret))
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
s.cache.Set(tokenCacheKey(tokenString), tokenString, expiresIn)
|
||||
// 0 means no expiration.
|
||||
// validate token cache
|
||||
if s.options.OAuthOptions.AccessTokenMaxAge > 0 {
|
||||
err = s.cache.Set(tokenCacheKey(tokenString), tokenString, s.options.OAuthOptions.AccessTokenMaxAge)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
func (s *jwtTokenIssuer) Revoke(token string) error {
|
||||
return s.cache.Del(tokenCacheKey(token))
|
||||
if s.options.OAuthOptions.AccessTokenMaxAge > 0 {
|
||||
return s.cache.Del(tokenCacheKey(token))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewJwtTokenIssuer(issuerName string, options *authoptions.AuthenticationOptions, cache cache.Interface) Issuer {
|
||||
|
||||
@@ -21,6 +21,7 @@ package token
|
||||
import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/oauth"
|
||||
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
"testing"
|
||||
@@ -70,3 +71,39 @@ func TestJwtTokenIssuer(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenVerifyWithoutCacheValidate(t *testing.T) {
|
||||
options := authoptions.NewAuthenticateOptions()
|
||||
|
||||
// do not set token cache and disable token cache validate,
|
||||
options.OAuthOptions = &oauth.Options{AccessTokenMaxAge: 0}
|
||||
options.JwtSecret = "kubesphere"
|
||||
issuer := NewJwtTokenIssuer(DefaultIssuerName, options, nil)
|
||||
|
||||
client, err := options.OAuthOptions.OAuthClient("default")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
user := &user.DefaultInfo{
|
||||
Name: "admin",
|
||||
UID: "admin",
|
||||
}
|
||||
|
||||
tokenString, err := issuer.IssueTo(user, *client.AccessTokenMaxAge)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := issuer.Verify(tokenString)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, user); diff != "" {
|
||||
t.Error("token validate failed")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user