fix: harden auth flows and align api contracts
This commit is contained in:
@@ -61,17 +61,18 @@ type SSOTokenInfo struct {
|
||||
ClientID string
|
||||
}
|
||||
|
||||
// SSOSession SSO Session
|
||||
type SSOSession struct {
|
||||
SessionID string
|
||||
UserID int64
|
||||
Username string
|
||||
ClientID string
|
||||
CreatedAt time.Time
|
||||
ExpiresAt time.Time
|
||||
Scope string
|
||||
SessionID string
|
||||
UserID int64
|
||||
Username string
|
||||
ClientID string
|
||||
RedirectURI string
|
||||
CreatedAt time.Time
|
||||
ExpiresAt time.Time
|
||||
Scope string
|
||||
}
|
||||
|
||||
|
||||
// SSOManager SSO 管理器
|
||||
type SSOManager struct {
|
||||
mu sync.RWMutex
|
||||
@@ -113,20 +114,19 @@ func (m *SSOManager) GenerateAuthorizationCode(clientID, redirectURI, scope stri
|
||||
}
|
||||
|
||||
session := &SSOSession{
|
||||
SessionID: sessionID,
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
ClientID: clientID,
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: time.Now().Add(10 * time.Minute), // 授权码 10 分钟有效期
|
||||
Scope: scope,
|
||||
SessionID: sessionID,
|
||||
UserID: userID,
|
||||
Username: username,
|
||||
ClientID: clientID,
|
||||
RedirectURI: redirectURI,
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: time.Now().Add(10 * time.Minute),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
// 检查并清理过期 session,如果超过限制则淘汰最旧的
|
||||
if len(m.sessions) >= MaxSessions {
|
||||
m.cleanupExpiredLocked()
|
||||
// 如果仍然满,淘汰最早的
|
||||
if len(m.sessions) >= MaxSessions {
|
||||
m.evictOldest()
|
||||
}
|
||||
@@ -137,6 +137,7 @@ func (m *SSOManager) GenerateAuthorizationCode(clientID, redirectURI, scope stri
|
||||
return code, nil
|
||||
}
|
||||
|
||||
|
||||
// ValidateAuthorizationCode 验证授权码
|
||||
func (m *SSOManager) ValidateAuthorizationCode(code string) (*SSOSession, error) {
|
||||
m.mu.Lock()
|
||||
@@ -167,13 +168,14 @@ func (m *SSOManager) GenerateAccessToken(clientID string, session *SSOSession) (
|
||||
expiresAt := time.Now().Add(2 * time.Hour) // Access token 2 小时有效期
|
||||
|
||||
accessSession := &SSOSession{
|
||||
SessionID: token,
|
||||
UserID: session.UserID,
|
||||
Username: session.Username,
|
||||
ClientID: clientID,
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: expiresAt,
|
||||
Scope: session.Scope,
|
||||
SessionID: token,
|
||||
UserID: session.UserID,
|
||||
Username: session.Username,
|
||||
ClientID: clientID,
|
||||
RedirectURI: session.RedirectURI,
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: expiresAt,
|
||||
Scope: session.Scope,
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
@@ -225,6 +227,27 @@ func (m *SSOManager) RevokeToken(token string) error {
|
||||
delete(m.sessions, token)
|
||||
return nil
|
||||
}
|
||||
func (m *SSOManager) ValidateAccessToken(token string) (*SSOSession, error) {
|
||||
m.mu.RLock()
|
||||
session, ok := m.sessions[token]
|
||||
if !ok {
|
||||
m.mu.RUnlock()
|
||||
return nil, errors.New("invalid access token")
|
||||
}
|
||||
if time.Now().After(session.ExpiresAt) {
|
||||
m.mu.RUnlock()
|
||||
m.mu.Lock()
|
||||
delete(m.sessions, token)
|
||||
m.mu.Unlock()
|
||||
return nil, errors.New("access token expired")
|
||||
}
|
||||
if session.RedirectURI == "" {
|
||||
m.mu.RUnlock()
|
||||
return nil, errors.New("not an access token")
|
||||
}
|
||||
m.mu.RUnlock()
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// CleanupExpired 清理过期的 session
|
||||
func (m *SSOManager) CleanupExpired() {
|
||||
|
||||
Reference in New Issue
Block a user