fix: session invalidation
This commit is contained in:
@@ -198,18 +198,19 @@ func ValidateAccessToken(gc *gin.Context, accessToken string) (map[string]interf
|
||||
return res, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
||||
savedSession, err := memorystore.Provider.GetState(accessToken)
|
||||
if savedSession == "" || err != nil {
|
||||
res, err := ParseJWTToken(accessToken)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
userID := res["sub"].(string)
|
||||
nonce, err := memorystore.Provider.GetUserSession(userID, accessToken)
|
||||
if nonce == "" || err != nil {
|
||||
return res, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
||||
savedSessionSplit := strings.Split(savedSession, "@")
|
||||
nonce := savedSessionSplit[0]
|
||||
userID := savedSessionSplit[1]
|
||||
|
||||
hostname := parsers.GetHost(gc)
|
||||
res, err = ParseJWTToken(accessToken, hostname, nonce, userID)
|
||||
if err != nil {
|
||||
if ok, err := ValidateJWTClaims(res, hostname, nonce, userID); !ok || err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
@@ -228,18 +229,19 @@ func ValidateRefreshToken(gc *gin.Context, refreshToken string) (map[string]inte
|
||||
return res, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
||||
savedSession, err := memorystore.Provider.GetState(refreshToken)
|
||||
if savedSession == "" || err != nil {
|
||||
res, err := ParseJWTToken(refreshToken)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
userID := res["sub"].(string)
|
||||
nonce, err := memorystore.Provider.GetUserSession(userID, refreshToken)
|
||||
if nonce == "" || err != nil {
|
||||
return res, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
||||
savedSessionSplit := strings.Split(savedSession, "@")
|
||||
nonce := savedSessionSplit[0]
|
||||
userID := savedSessionSplit[1]
|
||||
|
||||
hostname := parsers.GetHost(gc)
|
||||
res, err = ParseJWTToken(refreshToken, hostname, nonce, userID)
|
||||
if err != nil {
|
||||
if ok, err := ValidateJWTClaims(res, hostname, nonce, userID); !ok || err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
@@ -255,15 +257,6 @@ func ValidateBrowserSession(gc *gin.Context, encryptedSession string) (*SessionD
|
||||
return nil, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
||||
savedSession, err := memorystore.Provider.GetState(encryptedSession)
|
||||
if savedSession == "" || err != nil {
|
||||
return nil, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
||||
savedSessionSplit := strings.Split(savedSession, "@")
|
||||
nonce := savedSessionSplit[0]
|
||||
userID := savedSessionSplit[1]
|
||||
|
||||
decryptedFingerPrint, err := crypto.DecryptAES(encryptedSession)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -275,23 +268,20 @@ func ValidateBrowserSession(gc *gin.Context, encryptedSession string) (*SessionD
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.Nonce != nonce {
|
||||
return nil, fmt.Errorf(`unauthorized: invalid nonce`)
|
||||
nonce, err := memorystore.Provider.GetUserSession(res.Subject, encryptedSession)
|
||||
if nonce == "" || err != nil {
|
||||
log.Debug("invalid browser session:", err)
|
||||
return nil, fmt.Errorf(`unauthorized`)
|
||||
}
|
||||
|
||||
if res.Subject != userID {
|
||||
return nil, fmt.Errorf(`unauthorized: invalid user id`)
|
||||
if res.Nonce != nonce {
|
||||
return nil, fmt.Errorf(`unauthorized: invalid nonce`)
|
||||
}
|
||||
|
||||
if res.ExpiresAt < time.Now().Unix() {
|
||||
return nil, fmt.Errorf(`unauthorized: token expired`)
|
||||
}
|
||||
|
||||
// TODO validate scope
|
||||
// if !reflect.DeepEqual(res.Roles, roles) {
|
||||
// return res, "", fmt.Errorf(`unauthorized`)
|
||||
// }
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
|
@@ -60,7 +60,7 @@ func SignJWTToken(claims jwt.MapClaims) (string, error) {
|
||||
}
|
||||
|
||||
// ParseJWTToken common util to parse jwt token
|
||||
func ParseJWTToken(token, hostname, nonce, subject string) (jwt.MapClaims, error) {
|
||||
func ParseJWTToken(token string) (jwt.MapClaims, error) {
|
||||
jwtType, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -116,98 +116,48 @@ func ParseJWTToken(token, hostname, nonce, subject string) (jwt.MapClaims, error
|
||||
intIat := int64(claims["iat"].(float64))
|
||||
claims["exp"] = intExp
|
||||
claims["iat"] = intIat
|
||||
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
// ValidateJWTClaims common util to validate claims
|
||||
func ValidateJWTClaims(claims jwt.MapClaims, hostname, nonce, subject string) (bool, error) {
|
||||
clientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID)
|
||||
if err != nil {
|
||||
return claims, err
|
||||
return false, err
|
||||
}
|
||||
if claims["aud"] != clientID {
|
||||
return claims, errors.New("invalid audience")
|
||||
return false, errors.New("invalid audience")
|
||||
}
|
||||
|
||||
if claims["nonce"] != nonce {
|
||||
return claims, errors.New("invalid nonce")
|
||||
return false, errors.New("invalid nonce")
|
||||
}
|
||||
|
||||
if claims["iss"] != hostname {
|
||||
return claims, errors.New("invalid issuer")
|
||||
return false, errors.New("invalid issuer")
|
||||
}
|
||||
|
||||
if claims["sub"] != subject {
|
||||
return claims, errors.New("invalid subject")
|
||||
return false, errors.New("invalid subject")
|
||||
}
|
||||
|
||||
return claims, nil
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// ParseJWTTokenWithoutNonce common util to parse jwt token without nonce
|
||||
// used to validate ID token as it is not persisted in store
|
||||
func ParseJWTTokenWithoutNonce(token, hostname string) (jwt.MapClaims, error) {
|
||||
jwtType, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signingMethod := jwt.GetSigningMethod(jwtType)
|
||||
|
||||
var claims jwt.MapClaims
|
||||
|
||||
switch signingMethod {
|
||||
case jwt.SigningMethodHS256, jwt.SigningMethodHS384, jwt.SigningMethodHS512:
|
||||
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
|
||||
jwtSecret, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(jwtSecret), nil
|
||||
})
|
||||
case jwt.SigningMethodRS256, jwt.SigningMethodRS384, jwt.SigningMethodRS512:
|
||||
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
|
||||
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := crypto.ParseRsaPublicKeyFromPemStr(jwtPublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
})
|
||||
case jwt.SigningMethodES256, jwt.SigningMethodES384, jwt.SigningMethodES512:
|
||||
_, err = jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
|
||||
jwtPublicKey, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyJwtPublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key, err := crypto.ParseEcdsaPublicKeyFromPemStr(jwtPublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key, nil
|
||||
})
|
||||
default:
|
||||
err = errors.New("unsupported signing method")
|
||||
}
|
||||
if err != nil {
|
||||
return claims, err
|
||||
}
|
||||
|
||||
// claim parses exp & iat into float 64 with e^10,
|
||||
// but we expect it to be int64
|
||||
// hence we need to assert interface and convert to int64
|
||||
intExp := int64(claims["exp"].(float64))
|
||||
intIat := int64(claims["iat"].(float64))
|
||||
claims["exp"] = intExp
|
||||
claims["iat"] = intIat
|
||||
// ValidateJWTClaimsWithoutNonce common util to validate claims without nonce
|
||||
func ValidateJWTTokenWithoutNonce(claims jwt.MapClaims, hostname string) (bool, error) {
|
||||
clientID, err := memorystore.Provider.GetStringStoreEnvVariable(constants.EnvKeyClientID)
|
||||
if err != nil {
|
||||
return claims, err
|
||||
return false, err
|
||||
}
|
||||
if claims["aud"] != clientID {
|
||||
return claims, errors.New("invalid audience")
|
||||
return false, errors.New("invalid audience")
|
||||
}
|
||||
|
||||
if claims["iss"] != hostname {
|
||||
return claims, errors.New("invalid issuer")
|
||||
return false, errors.New("invalid issuer")
|
||||
}
|
||||
|
||||
return claims, nil
|
||||
return true, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user