Skip to content

Commit

Permalink
feat: invalidate old token after changing the password (close #5515)
Browse files Browse the repository at this point in the history
  • Loading branch information
xhofe committed Nov 13, 2023
1 parent a7421d8 commit 3d51845
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 6 deletions.
3 changes: 3 additions & 0 deletions internal/model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
"time"

"github.com/alist-org/alist/v3/internal/errs"
"github.com/alist-org/alist/v3/pkg/utils"
Expand All @@ -24,6 +25,7 @@ type User struct {
ID uint `json:"id" gorm:"primaryKey"` // unique key
Username string `json:"username" gorm:"unique" binding:"required"` // username
PwdHash string `json:"-"` // password hash
PwdTS int64 `json:"-"` // password timestamp
Salt string `json:"-"` // unique salt
Password string `json:"password"` // password
BasePath string `json:"base_path"` // base path
Expand Down Expand Up @@ -71,6 +73,7 @@ func (u *User) ValidatePwdStaticHash(pwdStaticHash string) error {
func (u *User) SetPassword(pwd string) *User {
u.Salt = random.String(16)
u.PwdHash = TwoHashPwd(pwd, u.Salt)
u.PwdTS = time.Now().Unix()
return u
}

Expand Down
7 changes: 5 additions & 2 deletions server/common/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

"github.com/alist-org/alist/v3/internal/conf"
"github.com/alist-org/alist/v3/internal/model"
"github.com/golang-jwt/jwt/v4"
"github.com/pkg/errors"
)
Expand All @@ -12,12 +13,14 @@ var SecretKey []byte

type UserClaims struct {
Username string `json:"username"`
PwdTS int64 `json:"pwd_ts"`
jwt.RegisteredClaims
}

func GenerateToken(username string) (tokenString string, err error) {
func GenerateToken(user *model.User) (tokenString string, err error) {
claim := UserClaims{
Username: username,
Username: user.Username,
PwdTS: user.PwdTS,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(conf.Conf.TokenExpiresIn) * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Expand Down
2 changes: 1 addition & 1 deletion server/handles/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func loginHash(c *gin.Context, req *LoginReq) {
}
}
// generate token
token, err := common.GenerateToken(user.Username)
token, err := common.GenerateToken(user)
if err != nil {
common.ErrorResp(c, err, 400, true)
return
Expand Down
4 changes: 2 additions & 2 deletions server/handles/ssologin.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ func OIDCLoginCallback(c *gin.Context) {
common.ErrorResp(c, err, 400)
}
}
token, err := common.GenerateToken(user.Username)
token, err := common.GenerateToken(user)
if err != nil {
common.ErrorResp(c, err, 400)
}
Expand Down Expand Up @@ -426,7 +426,7 @@ func SSOLoginCallback(c *gin.Context) {
return
}
}
token, err := common.GenerateToken(user.Username)
token, err := common.GenerateToken(user)
if err != nil {
common.ErrorResp(c, err, 400)
}
Expand Down
2 changes: 1 addition & 1 deletion server/handles/webauthn.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func FinishAuthnLogin(c *gin.Context) {
return
}

token, err := common.GenerateToken(user.Username)
token, err := common.GenerateToken(user)
if err != nil {
common.ErrorResp(c, err, 400, true)
return
Expand Down
12 changes: 12 additions & 0 deletions server/middlewares/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ func Auth(c *gin.Context) {
c.Abort()
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 {
common.ErrorStrResp(c, "Current user is disabled, replace please", 401)
c.Abort()
Expand Down Expand Up @@ -105,6 +111,12 @@ func Authn(c *gin.Context) {
c.Abort()
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 {
common.ErrorStrResp(c, "Current user is disabled, replace please", 401)
c.Abort()
Expand Down

0 comments on commit 3d51845

Please sign in to comment.