feat: invalidate old token after changing the password (close #5515)
This commit is contained in:
parent
a7421d8fc2
commit
3d51845f57
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
@ -24,6 +25,7 @@ type User struct {
|
|||||||
ID uint `json:"id" gorm:"primaryKey"` // unique key
|
ID uint `json:"id" gorm:"primaryKey"` // unique key
|
||||||
Username string `json:"username" gorm:"unique" binding:"required"` // username
|
Username string `json:"username" gorm:"unique" binding:"required"` // username
|
||||||
PwdHash string `json:"-"` // password hash
|
PwdHash string `json:"-"` // password hash
|
||||||
|
PwdTS int64 `json:"-"` // password timestamp
|
||||||
Salt string `json:"-"` // unique salt
|
Salt string `json:"-"` // unique salt
|
||||||
Password string `json:"password"` // password
|
Password string `json:"password"` // password
|
||||||
BasePath string `json:"base_path"` // base path
|
BasePath string `json:"base_path"` // base path
|
||||||
@ -71,6 +73,7 @@ func (u *User) ValidatePwdStaticHash(pwdStaticHash string) error {
|
|||||||
func (u *User) SetPassword(pwd string) *User {
|
func (u *User) SetPassword(pwd string) *User {
|
||||||
u.Salt = random.String(16)
|
u.Salt = random.String(16)
|
||||||
u.PwdHash = TwoHashPwd(pwd, u.Salt)
|
u.PwdHash = TwoHashPwd(pwd, u.Salt)
|
||||||
|
u.PwdTS = time.Now().Unix()
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v4"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -12,12 +13,14 @@ var SecretKey []byte
|
|||||||
|
|
||||||
type UserClaims struct {
|
type UserClaims struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
|
PwdTS int64 `json:"pwd_ts"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateToken(username string) (tokenString string, err error) {
|
func GenerateToken(user *model.User) (tokenString string, err error) {
|
||||||
claim := UserClaims{
|
claim := UserClaims{
|
||||||
Username: username,
|
Username: user.Username,
|
||||||
|
PwdTS: user.PwdTS,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(conf.Conf.TokenExpiresIn) * time.Hour)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(conf.Conf.TokenExpiresIn) * time.Hour)),
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
|
@ -78,7 +78,7 @@ func loginHash(c *gin.Context, req *LoginReq) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// generate token
|
// generate token
|
||||||
token, err := common.GenerateToken(user.Username)
|
token, err := common.GenerateToken(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400, true)
|
common.ErrorResp(c, err, 400, true)
|
||||||
return
|
return
|
||||||
|
@ -260,7 +260,7 @@ func OIDCLoginCallback(c *gin.Context) {
|
|||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token, err := common.GenerateToken(user.Username)
|
token, err := common.GenerateToken(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
}
|
}
|
||||||
@ -426,7 +426,7 @@ func SSOLoginCallback(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token, err := common.GenerateToken(user.Username)
|
token, err := common.GenerateToken(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400)
|
common.ErrorResp(c, err, 400)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ func FinishAuthnLogin(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := common.GenerateToken(user.Username)
|
token, err := common.GenerateToken(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 400, true)
|
common.ErrorResp(c, err, 400, true)
|
||||||
return
|
return
|
||||||
|
@ -57,6 +57,12 @@ func Auth(c *gin.Context) {
|
|||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// validate password timestamp
|
||||||
|
if userClaims.PwdTS != user.PwdTS {
|
||||||
|
common.ErrorStrResp(c, "Password has been changed, login please", 401)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
if user.Disabled {
|
if user.Disabled {
|
||||||
common.ErrorStrResp(c, "Current user is disabled, replace please", 401)
|
common.ErrorStrResp(c, "Current user is disabled, replace please", 401)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
@ -105,6 +111,12 @@ func Authn(c *gin.Context) {
|
|||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// validate password timestamp
|
||||||
|
if userClaims.PwdTS != user.PwdTS {
|
||||||
|
common.ErrorStrResp(c, "Password has been changed, login please", 401)
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
if user.Disabled {
|
if user.Disabled {
|
||||||
common.ErrorStrResp(c, "Current user is disabled, replace please", 401)
|
common.ErrorStrResp(c, "Current user is disabled, replace please", 401)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user