mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-09-19 09:40:12 +00:00
feat(jwt): server-side session table with keyId + obfuscated uid claims
Replace the {user_id, ip} claim pair with {keyId, uid}:
- keyId is a 32-byte random id that points to a row in the new
jwt_sessions table holding the real user id, bound IP, UA hash,
TokenVersion and expiry.
- uid is the user id encoded through pkg/idcodec; mismatch between
claim uid and session.UserID trips WAF block on the caller IP.
- identityHandler now rejects unknown/revoked/expired sessions, IP
drift and stale TokenVersion. Refresh updates session.ExpiresAt.
User.TokenVersion bumps on password change and revokes outstanding
sessions, so a leaked JWT secret alone is no longer enough to forge
a token. JWTSession rows are GC'd every 10 minutes (expired + grace
or revoked >24h). OAuth2 callback shares the same issue path.
Includes regression tests for happy path, mismatched claim uid,
revoked session, TokenVersion bump, IP drift and unknown keyId.
Co-authored-by: cloudcode <cloudcode@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type JWTSession struct {
|
||||
KeyID string `gorm:"primaryKey;type:char(64)" json:"key_id"`
|
||||
UserID uint64 `gorm:"index:idx_jwt_sessions_user_revoked" json:"user_id"`
|
||||
IP string `gorm:"type:varchar(64)" json:"ip"`
|
||||
UAHash string `gorm:"type:char(64)" json:"ua_hash"`
|
||||
TokenVersion uint64 `json:"token_version"`
|
||||
ExpiresAt time.Time `gorm:"index" json:"expires_at"`
|
||||
RevokedAt *time.Time `gorm:"index:idx_jwt_sessions_user_revoked" json:"revoked_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
LastUsedAt time.Time `json:"last_used_at"`
|
||||
}
|
||||
|
||||
func (JWTSession) TableName() string {
|
||||
return "jwt_sessions"
|
||||
}
|
||||
@@ -28,6 +28,7 @@ type User struct {
|
||||
Role Role `json:"role,omitempty"`
|
||||
AgentSecret string `json:"agent_secret,omitempty" gorm:"type:char(32)"`
|
||||
RejectPassword bool `json:"reject_password,omitempty"`
|
||||
TokenVersion uint64 `json:"-" gorm:"not null;default:0"`
|
||||
}
|
||||
|
||||
type UserInfo struct {
|
||||
|
||||
Reference in New Issue
Block a user