ilk
This commit is contained in:
92
svc/routes/auth_refresh.go
Normal file
92
svc/routes/auth_refresh.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"bssapp-backend/auth"
|
||||
"bssapp-backend/internal/security"
|
||||
"bssapp-backend/repository"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func setRefreshCookie(w http.ResponseWriter, plain string, exp time.Time) {
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "mk_refresh",
|
||||
Value: plain,
|
||||
Path: "/",
|
||||
Expires: exp,
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
Secure: false, // prod: true
|
||||
})
|
||||
}
|
||||
|
||||
func AuthRefreshHandler(db *sql.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
// 1) refresh cookie
|
||||
c, err := r.Cookie("mk_refresh")
|
||||
if err != nil || c.Value == "" {
|
||||
http.Error(w, "refresh token missing", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
hash := security.HashRefreshToken(c.Value)
|
||||
rtRepo := repository.NewRefreshTokenRepository(db)
|
||||
|
||||
// 2) validate + consume
|
||||
mkUserID, err := rtRepo.ConsumeValid(hash)
|
||||
if err != nil {
|
||||
http.Error(w, "refresh token invalid", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// 3) rotate
|
||||
newPlain, newHash, err := security.GenerateRefreshToken()
|
||||
if err != nil {
|
||||
http.Error(w, "refresh gen failed", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
refreshExp := time.Now().Add(14 * 24 * time.Hour)
|
||||
if err := rtRepo.IssueRefreshToken(mkUserID, newHash, refreshExp); err != nil {
|
||||
http.Error(w, "refresh store failed", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
setRefreshCookie(w, newPlain, refreshExp)
|
||||
|
||||
// 4) mk user reload
|
||||
mkRepo := repository.NewMkUserRepository(db)
|
||||
mkUser, err := mkRepo.GetByID(mkUserID)
|
||||
if err != nil || !mkUser.IsActive {
|
||||
http.Error(w, "user invalid", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if mkUser.ForcePasswordChange {
|
||||
http.Error(w, "password change required", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// 5) new access token
|
||||
claims := auth.BuildClaimsFromUser(mkUser, 15*time.Minute)
|
||||
|
||||
token, err := auth.GenerateToken(
|
||||
claims,
|
||||
mkUser.Username,
|
||||
mkUser.ForcePasswordChange,
|
||||
)
|
||||
if err != nil {
|
||||
http.Error(w, "access token gen failed", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// 6) response
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"success": true,
|
||||
"token": token,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user