RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/madebyaris/poinf-of-sales

Cursor rule

.cursor/rules/authentication-and-security-patterns.mdc

Complete authentication, security, and debugging patterns for React + Go POS system

Cursor rules

Quality

81/100

Scores the file, not the repository.

Length

1,332 words

38 headings · 16 code blocks

Repository

118

— · pushed 339 days ago

Last changed

3 days ago

First indexed 3 days ago.
madebyaris/poinf-of-sales/.cursor/rules/authentication-and-security-patterns.mdcRawGitHub
1---
2globs: **/routes/**,**/auth/**,**/login/**,**/*auth*,**/*security*
3description: Complete authentication, security, and debugging patterns for React + Go POS system
4---
5 
6# 🔐 Authentication & Security Patterns
7 
8## 🚀 Essential Authentication Architecture
9 
10### JWT-Based Authentication Flow
11```typescript
12// Complete authentication workflow
13class APIClient {
14 constructor() {
15 const apiUrl = import.meta.env?.VITE_API_URL || 'http://localhost:8080/api/v1';
16 console.log('🔧 API Client baseURL:', apiUrl);
17
18 this.client = axios.create({
19 baseURL: apiUrl,
20 timeout: 30000,
21 headers: { 'Content-Type': 'application/json' }
22 });
23 
24 // Auto-attach token from localStorage
25 this.loadStoredAuth();
26 }
27 
28 private loadStoredAuth(): void {
29 const token = localStorage.getItem('pos_token');
30 if (token) {
31 this.client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
32 }
33 }
34 
35 setAuthToken(token: string): void {
36 localStorage.setItem('pos_token', token);
37 this.client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
38 }
39 
40 clearAuth(): void {
41 localStorage.removeItem('pos_token');
42 localStorage.removeItem('pos_user');
43 delete this.client.defaults.headers.common['Authorization'];
44 }
45 
46 isAuthenticated(): boolean {
47 return !!localStorage.getItem('pos_token');
48 }
49}
50```
51 
52## 🏗️ React Authentication Components
53 
54### Protected Route Pattern (Avoid Infinite Redirects)
55```typescript
56function HomePage() {
57 // ✅ ALL HOOKS AT TOP LEVEL - NEVER after returns
58 const [user, setUser] = useState<User | null>(null);
59 const [isLoadingAuth, setIsLoadingAuth] = useState(true); // Critical: Start true
60 
61 const { isLoading: isVerifying, error } = useQuery({
62 queryKey: ['currentUser'],
63 queryFn: () => apiClient.getCurrentUser(),
64 enabled: false, // Control when to verify
65 retry: 1,
66 });
67 
68 // Load auth state from localStorage FIRST
69 useEffect(() => {
70 const loadAuthState = async () => {
71 const token = localStorage.getItem('pos_token');
72 const storedUser = localStorage.getItem('pos_user');
73
74 console.log('🔍 Loading auth - token:', token ? 'exists' : 'missing');
75 console.log('🔍 Loading auth - user:', storedUser ? 'exists' : 'missing');
76
77 if (storedUser && token) {
78 try {
79 const parsedUser = JSON.parse(storedUser);
80 setUser(parsedUser);
81 console.log('✅ Auth loaded - user role:', parsedUser.role);
82 } catch (error) {
83 console.error('❌ Invalid stored auth data, clearing');
84 apiClient.clearAuth();
85 }
86 }
87
88 setIsLoadingAuth(false);
89 };
90
91 loadAuthState();
92 }, []);
93 
94 // ✅ CRITICAL: Wait for localStorage loading before auth checks
95 if (isLoadingAuth) {
96 return <LoadingSpinner message="Loading authentication..." />;
97 }
98 
99 // Only check auth AFTER loading is complete
100 if (!apiClient.isAuthenticated() || !user) {
101 console.log('🔄 Not authenticated, redirecting to login');
102 return <Navigate to="/login" replace />;
103 }
104 
105 // Render protected content with user context
106 return <RoleBasedLayout user={user} />;
107}
108```
109 
110### Login Component Pattern
111```typescript
112function LoginPage() {
113 const [error, setError] = useState<string | null>(null);
114
115 // Redirect if already authenticated
116 if (apiClient.isAuthenticated()) {
117 return <Navigate to="/" replace />;
118 }
119 
120 const loginMutation = useMutation({
121 mutationFn: async (credentials: LoginRequest) => {
122 console.log('🔄 Attempting login...');
123 return await apiClient.login(credentials);
124 },
125 onSuccess: (data) => {
126 console.log('✅ Login success:', data.success);
127
128 if (data.success && data.data) {
129 // Set auth token first
130 apiClient.setAuthToken(data.data.token);
131
132 // Store user data
133 localStorage.setItem('pos_user', JSON.stringify(data.data.user));
134
135 console.log('✅ Auth stored - role:', data.data.user.role);
136
137 // Brief delay prevents race conditions
138 setTimeout(() => {
139 router.navigate({ to: '/' });
140 }, 100);
141 }
142 },
143 onError: (error: any) => {
144 console.error('❌ Login failed:', error.message);
145 setError(error.message || 'Login failed');
146 },
147 });
148 
149 return (
150 <LoginForm
151 onSubmit={loginMutation.mutate}
152 isLoading={loginMutation.isPending}
153 error={error}
154 />
155 );
156}
157```
158 
159## 🛡️ Backend Security Patterns
160 
161### Go JWT Middleware
162```go
163// JWT authentication middleware
164func AuthMiddleware() gin.HandlerFunc {
165 return func(c *gin.Context) {
166 tokenString := c.GetHeader("Authorization")
167 if tokenString == "" {
168 c.JSON(http.StatusUnauthorized, models.APIResponse{
169 Success: false,
170 Message: "Authorization header required",
171 Error: stringPtr("missing_auth_header"),
172 })
173 c.Abort()
174 return
175 }
176 
177 // Remove "Bearer " prefix
178 if len(tokenString) > 7 && tokenString[:7] == "Bearer " {
179 tokenString = tokenString[7:]
180 }
181 
182 token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
183 if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
184 return nil, fmt.Errorf("unexpected signing method")
185 }
186 return []byte(os.Getenv("JWT_SECRET")), nil
187 })
188 
189 if err != nil || !token.Valid {
190 c.JSON(http.StatusUnauthorized, models.APIResponse{
191 Success: false,
192 Message: "Invalid or expired token",
193 Error: stringPtr("invalid_token"),
194 })
195 c.Abort()
196 return
197 }
198 
199 if claims, ok := token.Claims.(jwt.MapClaims); ok {
200 c.Set("user_id", claims["user_id"])
201 c.Set("username", claims["username"])
202 c.Set("role", claims["role"])
203 }
204 
205 c.Next()
206 }
207}
208 
209// Role-based access control
210func RequireRoles(allowedRoles ...string) gin.HandlerFunc {
211 return func(c *gin.Context) {
212 userRole, exists := c.Get("role")
213 if !exists {
214 c.JSON(http.StatusForbidden, models.APIResponse{
215 Success: false,
216 Message: "Role information not found",
217 Error: stringPtr("missing_role"),
218 })
219 c.Abort()
220 return
221 }
222 
223 role := userRole.(string)
224 for _, allowedRole := range allowedRoles {
225 if role == allowedRole {
226 c.Next()
227 return
228 }
229 }
230 
231 c.JSON(http.StatusForbidden, models.APIResponse{
232 Success: false,
233 Message: "Insufficient permissions",
234 Error: stringPtr("insufficient_permissions"),
235 })
236 c.Abort()
237 }
238}
239```
240 
241### CORS Configuration for Development
242```go
243// Dynamic port CORS for development flexibility
244func setupCORS(router *gin.Engine) {
245 config := cors.New(cors.Config{
246 AllowOrigins: []string{
247 "http://localhost:3000",
248 "http://localhost:3001",
249 "http://localhost:3002",
250 "http://localhost:3003",
251 "http://localhost:5173", // Vite default
252 },
253 AllowMethods: []string{
254 "GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS",
255 },
256 AllowHeaders: []string{
257 "Origin", "Content-Type", "Content-Length",
258 "Accept-Encoding", "X-CSRF-Token", "Authorization",
259 "X-Requested-With",
260 },
261 AllowCredentials: true,
262 MaxAge: 12 * time.Hour,
263 })
264
265 router.Use(config)
266}
267```
268 
269## 🐛 Common Issues & Solutions
270 
271### 1. Infinite Redirect Loop
272**Symptoms:** Continuous redirects between `/login` and `/`
273 
274**Root Cause:**
275```typescript
276// ❌ WRONG - Auth check before localStorage loading
277if (!apiClient.isAuthenticated() || !user) {
278 return <Navigate to="/login" />; // Creates loop
279}
280```
281 
282**Solution:**
283```typescript
284// ✅ CORRECT - Wait for loading state
285if (isLoadingAuth) {
286 return <LoadingSpinner />;
287}
288 
289if (!apiClient.isAuthenticated() || !user) {
290 return <Navigate to="/login" replace />;
291}
292```
293 
294### 2. React Hooks Rules Violation
295**Symptoms:** "Rendered more hooks than during the previous render"
296 
297**Solution:**
298```typescript
299// ✅ CORRECT - All hooks at top level
300function Component() {
301 const { data } = useQuery(...); // Hook at top
302
303 if (someCondition) {
304 return <div>Early return</div>; // Return after hooks
305 }
306}
307```
308 
309### 3. CORS Debugging
310**Test CORS Configuration:**
311```bash
312# Test preflight request
313curl -s -H &quot;Origin: http://localhost:3001&quot; \
314 -X OPTIONS http://localhost:8080/api/v1/auth/login -I
315 
316# Expected headers:
317# Access-Control-Allow-Origin: http://localhost:3001
318# Access-Control-Allow-Methods: GET,POST,PUT,DELETE,PATCH,OPTIONS
319```
320 
321**Quick CORS Fix:**
322```bash
323# Add new port to CORS (adjust port as needed)
324# Edit backend/main.go CORS configuration
325# Restart backend container
326docker compose restart backend
327```
328 
329### 4. Environment Variables
330**Common Issue:** API requests to wrong URLs
331 
332**Solution:**
333```bash
334# Set environment variables in both locations
335echo &quot;VITE_API_URL=http://localhost:8080/api/v1&quot; &gt; .env
336echo &quot;VITE_API_URL=http://localhost:8080/api/v1&quot; &gt; frontend/.env
337 
338# Recreate containers (restart isn't enough for env vars)
339make down
340make dev
341```
342 
343## 🔍 Authentication Debugging Checklist
344 
345### Frontend Issues
346- [ ] Check browser localStorage: `pos_token` and `pos_user`
347- [ ] Verify API client baseURL in console logs
348- [ ] Check Network tab for 401/404 vs CORS errors
349- [ ] Confirm hooks are at component top level
350- [ ] Test with cleared localStorage
351 
352### Backend Issues
353- [ ] Check backend logs: `docker logs pos-backend-dev --tail 50`
354- [ ] Verify JWT_SECRET environment variable
355- [ ] Test API endpoints with curl
356- [ ] Confirm CORS includes frontend port
357- [ ] Check route registration patterns
358 
359### CORS Issues
360- [ ] Check current frontend port in terminal
361- [ ] Test CORS preflight with curl
362- [ ] Verify backend CORS allows current port
363- [ ] Restart backend after CORS changes
364- [ ] Clear browser cache/storage
365 
366## 🏛️ Security Best Practices
367 
368### Password Security
369```go
370import "golang.org/x/crypto/bcrypt"
371 
372func HashPassword(password string) (string, error) {
373 bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
374 return string(bytes), err
375}
376 
377func VerifyPassword(hashedPassword, password string) error {
378 return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
379}
380```
381 
382### Input Validation
383```go
384// Validate UUIDs
385orderID, err := uuid.Parse(c.Param("id"))
386if err != nil {
387 c.JSON(http.StatusBadRequest, models.APIResponse{
388 Success: false,
389 Message: "Invalid order ID format",
390 Error: stringPtr("invalid_uuid"),
391 })
392 return
393}
394 
395// Validate enums
396validStatuses := []string{"pending", "confirmed", "preparing", "ready", "served", "completed", "cancelled"}
397if !contains(validStatuses, req.Status) {
398 c.JSON(http.StatusBadRequest, models.APIResponse{
399 Success: false,
400 Message: "Invalid order status",
401 Error: stringPtr("invalid_status"),
402 })
403 return
404}
405```
406 
407### Security Logging
408```go
409// Log security events
410log.Printf("LOGIN_SUCCESS: user=%s, ip=%s, role=%s", username, c.ClientIP(), user.Role)
411log.Printf("LOGIN_FAILED: username=%s, ip=%s", username, c.ClientIP())
412log.Printf("ACCESS_DENIED: user=%s, role=%s, endpoint=%s", username, role, c.Request.URL.Path)
413```
414 
415## 🚀 Development Workflow
416 
417### Environment Setup Commands
418```bash
419# Essential development commands
420make dev # Start with proper environment variables
421make logs # Monitor authentication flow
422make status # Check system health
423 
424# Authentication debugging
425make logs-backend # Check JWT processing
426make logs-frontend# Check client-side auth
427 
428# Reset authentication state
429make db-reset # Fresh database with demo users
430make clean # Clear all Docker state
431```
432 
433### Demo Accounts for Testing
434| Role | Username | Password | Permissions |
435|------|----------|----------|-------------|
436| **👑 Admin** | `admin` | `admin123` | Full system access |
437| **🍽️ Server** | `server1` | `server123` | Dine-in orders only |
438| **💰 Counter** | `counter1` | `counter123` | All orders + payments |
439| **👨‍🍳 Kitchen** | `kitchen1` | `kitchen123` | Order preparation |
440 
441### Quick Authentication Test
442```typescript
443// Test authentication in browser console
444console.log('Token:', localStorage.getItem('pos_token'));
445console.log('User:', JSON.parse(localStorage.getItem('pos_user') || 'null'));
446console.log('API authenticated:', apiClient.isAuthenticated());
447 
448// Clear auth for testing
449apiClient.clearAuth();
450```

Commands it names

  • docker compose restart backend
  • make down
  • make dev
  • make logs
  • make status
  • make logs-backend
  • make logs-frontend# Check client-side auth
  • make db-reset
  • make clean
  • docker logs pos-backend-dev --tail 50

Sections

  • 🔐 Authentication & Security Patterns
  • 🚀 Essential Authentication Architecture
  • JWT-Based Authentication Flow
  • 🏗️ React Authentication Components
  • Protected Route Pattern (Avoid Infinite Redirects)
  • Login Component Pattern
  • 🛡️ Backend Security Patterns
  • Go JWT Middleware
  • CORS Configuration for Development
  • 🐛 Common Issues & Solutions
  • 1. Infinite Redirect Loop
  • 2. React Hooks Rules Violation
  • 3. CORS Debugging
  • Test preflight request
  • Expected headers:
  • Access-Control-Allow-Origin: http://localhost:3001
  • Access-Control-Allow-Methods: GET,POST,PUT,DELETE,PATCH,OPTIONS
  • Add new port to CORS (adjust port as needed)
  • Edit backend/main.go CORS configuration
  • Restart backend container
  • 4. Environment Variables
  • Set environment variables in both locations
  • Recreate containers (restart isn't enough for env vars)
  • 🔍 Authentication Debugging Checklist
  • Frontend Issues
  • Backend Issues
  • CORS Issues
  • 🏛️ Security Best Practices
  • Password Security
  • Input Validation
  • Security Logging
  • 🚀 Development Workflow
  • Environment Setup Commands
  • Essential development commands
  • Authentication debugging
  • Reset authentication state
  • Demo Accounts for Testing
  • Quick Authentication Test

What it covers

setuptestcode-stylesecurityapiuido-notagent-behaviour

Stack — with the evidence

typescript

(1.00)

react

(1.00)

tailwind

(1.00)

docker

(1.00)

vite

(0.70)

eslint

(0.70)

javascript

(0.50)

Glob targeting

  • **/routes/**
  • **/auth/**
  • **/login/**
  • **/*auth*
  • **/*security*

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
madebyaris
Language
—
License
—
Archived
no

All configs in this repo

Also in madebyaris/poinf-of-sales

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
madebyaris/poinf-of-sales.cursor/rules/admin-interface-patterns.mdc · 118Cursor rulestypescriptreact+5stylearchsecurityapi+262/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/api-patterns.mdc · 118Cursor rulestypescriptreact+5lint-formatstylesecuritydatabase+362/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/backend-golang.mdc · 118Cursor rulestypescriptreact+5testlint-formatstylearch+569/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/business-logic-patterns.mdc · 118Cursor rulestypescriptreact+5teststyledatabaseperformance+150/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/database-patterns.mdc · 118Cursor rulestypescriptreact+5stylearchtypessecurity+262/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/development-workflow.mdc · 118Cursor rulestypescriptreact+5setupbuildteststyle+386/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/docker-deployment.mdc · 118Cursor rulestypescriptreact+6setupbuildteststyle+877/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/frontend-react.mdc · 118Cursor rulestypescriptreact+5buildtestlint-formatstyle+469/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/makefile-scripting.mdc · 118Cursor rulestypescriptreact+5setuplint-formatstylearch+281/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/performance-optimization-patterns.mdc · 118Cursor rulestypescriptreact+5buildteststyledatabase+366/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/project-architecture.mdc · 118Cursor rulestypescriptreact+5setupteststylearch+678/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/react-native-mobile-patterns.mdc · 118Cursor rulestypescriptreact+5buildstylearchui+274/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/role-based-access-patterns.mdc · 118Cursor rulestypescriptreact+5styletypessecuritydatabase+258/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/tech-debt-prevention.mdc · 118Cursor rulestypescriptreact+5styletesting-strategyui50/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/testing-patterns.mdc · 118Cursor rulestypescriptreact+6setupteststylearch+474/1003 days ago
madebyaris/poinf-of-sales.cursor/rules/user-journey-optimization.mdc · 118Cursor rulestypescriptreact+5styleperformanceagent-behaviour50/1003 days ago
Diff against .cursor/rules/admin-interface-patterns.mdc Diff against .cursor/rules/api-patterns.mdc Diff against .cursor/rules/backend-golang.mdc Diff against .cursor/rules/business-logic-patterns.mdc Diff against .cursor/rules/database-patterns.mdc Diff against .cursor/rules/development-workflow.mdc Diff against .cursor/rules/docker-deployment.mdc Diff against .cursor/rules/frontend-react.mdc Diff against .cursor/rules/makefile-scripting.mdc Diff against .cursor/rules/performance-optimization-patterns.mdc Diff against .cursor/rules/project-architecture.mdc Diff against .cursor/rules/react-native-mobile-patterns.mdc Diff against .cursor/rules/role-based-access-patterns.mdc Diff against .cursor/rules/tech-debt-prevention.mdc Diff against .cursor/rules/testing-patterns.mdc Diff against .cursor/rules/user-journey-optimization.mdc

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126Cursor rulesgobun+5setupbuildtestlint-format+6100/1003 days ago
TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 45Cursor rulestypescriptpytest+15testlint-formatstylearch+5100/1003 days ago
markstev/mark-starter.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+14setuptestlint-formatstyle+699/1003 days ago
Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+13setuptestlint-formatstyle+799/1003 days ago
dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0Cursor rulestypescriptturborepo+15setuptestlint-formatstyle+799/1003 days ago
deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1Cursor rulestypescriptnextjs+5setuptestlint-formatstyle+799/1003 days ago
langflow-ai/langflow.cursor/rules/docs_development.mdc · 153kCursor rulespythonnode+16setupbuildtestlint-format+797/1003 days ago
TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 45Cursor rulestypescriptpytest+15teststyletesting-strategysecurity+397/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack