Add refresh token authentication system
Implement complete refresh token flow for improved security: - Short-lived access tokens (configurable, default 1h) - Long-lived refresh tokens (configurable, default 7d) - Automatic token rotation on refresh - Token revocation for proper logout Domain layer: - Add RefreshToken entity with validation and revocation - Add RefreshTokenRepository interface Application layer: - Add RefreshTokenHandler for token refresh operations - Add RevokeTokenHandler for single token revocation - Add RevokeAllTokensHandler for user-wide revocation Infrastructure layer: - Implement SQLite RefreshTokenRepository - Add refresh_tokens table migration with indexes - Add parseDuration helper for flexible time configuration HTTP layer: - Add POST /api/v1/auth/refresh endpoint - Add POST /api/v1/auth/logout endpoint - Update login/register to return refresh tokens - Improve Swagger documentation with clear descriptions Configuration: - Update .env.example with secure token expiry defaults - Add support for minute/hour/day duration formats Tests: - Fix test suite to work with new signatures - All existing tests passing
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
package entities
|
||||
|
||||
import "time"
|
||||
|
||||
type RefreshToken struct {
|
||||
ID string
|
||||
UserID string
|
||||
Token string
|
||||
ExpiresAt time.Time
|
||||
CreatedAt time.Time
|
||||
RevokedAt *time.Time
|
||||
}
|
||||
|
||||
func NewRefreshToken(userID, token string, expiresAt time.Time) *RefreshToken {
|
||||
return &RefreshToken{
|
||||
UserID: userID,
|
||||
Token: token,
|
||||
ExpiresAt: expiresAt,
|
||||
CreatedAt: time.Now(),
|
||||
RevokedAt: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *RefreshToken) IsValid() bool {
|
||||
if rt.RevokedAt != nil {
|
||||
return false
|
||||
}
|
||||
return time.Now().Before(rt.ExpiresAt)
|
||||
}
|
||||
|
||||
func (rt *RefreshToken) Revoke() {
|
||||
now := time.Now()
|
||||
rt.RevokedAt = &now
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"apocapoc-api/internal/domain/entities"
|
||||
)
|
||||
|
||||
type RefreshTokenRepository interface {
|
||||
Create(ctx context.Context, token *entities.RefreshToken) error
|
||||
FindByToken(ctx context.Context, token string) (*entities.RefreshToken, error)
|
||||
FindByUserID(ctx context.Context, userID string) ([]*entities.RefreshToken, error)
|
||||
RevokeByToken(ctx context.Context, token string) error
|
||||
RevokeAllByUserID(ctx context.Context, userID string) error
|
||||
DeleteExpired(ctx context.Context) error
|
||||
}
|
||||
Reference in New Issue
Block a user