MCPcopy Index your code
hub / github.com/PatchMon/PatchMon / AuthWithSessionCheck

Function AuthWithSessionCheck

server-source-code/internal/middleware/auth.go:28–100  ·  view source on GitHub ↗

AuthWithSessionCheck returns Auth middleware with session inactivity validation.

(cfg *config.Config, sessionsStore *store.SessionsStore, resolved *config.ResolvedConfig, log *slog.Logger)

Source from the content-addressed store, hash-verified

26
27// AuthWithSessionCheck returns Auth middleware with session inactivity validation.
28func AuthWithSessionCheck(cfg *config.Config, sessionsStore *store.SessionsStore, resolved *config.ResolvedConfig, log *slog.Logger) func(http.Handler) http.Handler {
29 return func(next http.Handler) http.Handler {
30 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
31 token, source := extractToken(r)
32 if token == "" {
33 if log != nil {
34 log.Debug("auth failed: no token", "path", r.URL.Path, "method", r.Method)
35 }
36 http.Error(w, `{"error":"Unauthorized"}`, http.StatusUnauthorized)
37 return
38 }
39
40 if log != nil {
41 log.Debug("auth validating token", "path", r.URL.Path, "source", source, "token_len", len(token))
42 }
43
44 claims := jwt.MapClaims{}
45 t, err := jwt.ParseWithClaims(token, &claims, func(_ *jwt.Token) (interface{}, error) {
46 return []byte(cfg.JWTSecret), nil
47 })
48 if err != nil || !t.Valid {
49 if log != nil {
50 log.Debug("auth token invalid", "path", r.URL.Path, "error", err, "valid", t != nil && t.Valid)
51 }
52 http.Error(w, `{"error":"Invalid token"}`, http.StatusUnauthorized)
53 return
54 }
55
56 userID, _ := claims["sub"].(string)
57 role, _ := claims["role"].(string)
58 sessionID, _ := claims["sessionId"].(string)
59 if userID == "" {
60 if log != nil {
61 log.Debug("auth token missing sub claim", "path", r.URL.Path)
62 }
63 http.Error(w, `{"error":"Invalid token"}`, http.StatusUnauthorized)
64 return
65 }
66
67 // Session inactivity check: when sessionID present, validate and update last_activity
68 if sessionID != "" && sessionsStore != nil && resolved != nil && resolved.SessionInactivityTimeoutMin > 0 {
69 sess, err := sessionsStore.GetByID(r.Context(), sessionID, userID)
70 if err != nil || sess == nil {
71 http.Error(w, `{"error":"Session expired"}`, http.StatusUnauthorized)
72 return
73 }
74 inactive := time.Since(sess.LastActivity) > time.Duration(resolved.SessionInactivityTimeoutMin)*time.Minute
75 if inactive {
76 if err := sessionsStore.RevokeByID(r.Context(), sessionID, userID); err != nil {
77 slog.Error("auth: failed to revoke inactive session", "session_id", sessionID, "error", err)
78 }
79 http.Error(w, `{"error":"Session expired due to inactivity"}`, http.StatusUnauthorized)
80 return
81 }
82 if err := sessionsStore.UpdateActivity(r.Context(), sessionID); err != nil {
83 slog.Error("auth: failed to update session activity", "session_id", sessionID, "error", err)
84 }
85 }

Callers 1

AuthFunction · 0.85

Calls 5

extractTokenFunction · 0.85
ErrorMethod · 0.80
UpdateActivityMethod · 0.80
GetByIDMethod · 0.45
RevokeByIDMethod · 0.45

Tested by

no test coverage detected