package auth import ( "context" "log" "net/http" "strings" "com.sismedika.com.absensi/graph/model" "com.sismedika.com.absensi/pkg/jwt" ) var userCtxKey = &contextKey{"user"} type contextKey struct { name string } type AuthRequest struct { isAuthenticated bool staff model.Staff } func Middleware() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { header := r.Header.Get("Authorization") AuthStatus := AuthRequest{isAuthenticated: false} // Allow unauthenticated users in if header == "" { ctx := context.WithValue(r.Context(), userCtxKey, &AuthStatus) r = r.WithContext(ctx) next.ServeHTTP(w, r) return } // validate jwt token tokenParts := strings.Split(header, " ") var tokenStr string if len(tokenParts) == 2 && tokenParts[0] == "Bearer" { tokenStr = tokenParts[1] } email, idGoogleSignIn, err := jwt.ParseToken(tokenStr) if err != nil { log.Printf("ParseToken: %v\n", err) ctx := context.WithValue(r.Context(), userCtxKey, &AuthStatus) r = r.WithContext(ctx) next.ServeHTTP(w, r) // boom.Unathorized(w, fmt.Errorf("AUTHORIZATION_HEADER_INVALID")) return } AuthStatus.staff = model.Staff{ Email: email, IDGoogleSignIn: idGoogleSignIn, } // put it in context ctx := context.WithValue(r.Context(), userCtxKey, &AuthStatus) // and call the next with our new context r = r.WithContext(ctx) next.ServeHTTP(w, r) }) } } // ForContext finds the user from the context. REQUIRES Middleware to have run. func ForContext(ctx context.Context) *model.Staff { raw, _ := ctx.Value(userCtxKey).(*model.Staff) return raw }