# Authentication System - Technical Documentation

## 📑 Table of Contents

- [Arsitektur](#arsitektur)
- [Flow Diagram](#flow-diagram)
- [API Integration](#api-integration)
- [Component Reference](#component-reference)
- [Security Considerations](#security-considerations)
- [Error Handling](#error-handling)
- [Testing Guide](#testing-guide)
- [Troubleshooting](#troubleshooting)

---

## 🏗️ Arsitektur

### Authentication Stack

```
┌─────────────────────────────────────────┐
│         User Interface (Pages)          │
│  - Login Page (GuestRoute)              │
│  - Register Page (GuestRoute)           │
│  - Protected Pages (ProtectedRoute)     │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│        Authentication Layer             │
│  - AuthContext (State Management)       │
│  - useAuth() Hook                       │
│  - Login/Logout Functions               │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│          HTTP Client Layer              │
│  - cifClient (Axios Instance)           │
│  - Auto Token Injection                 │
│  - Auto 401 Handling                    │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│         Backend API Server              │
│  - POST /v1/user/login                  │
│  - POST /v1/user/register               │
│  - Protected Endpoints                  │
└─────────────────────────────────────────┘
```

### Data Flow

```
localStorage
  ├── auth_token   (JWT Token)
  └── user         (User Object: { username, email, ... })
       │
       │ Loaded on App Mount
       ▼
   AuthContext
       │
       │ Provided via Context
       ▼
   All Components (via useAuth hook)
       │
       │ Token injection
       ▼
   HTTP Requests (Axios Interceptor)
       │
       │ Authorization: Bearer {token}
       ▼
   Backend API
```

---

## 🔄 Flow Diagram

### Login Flow

```
User                Login Page           AuthContext          cifClient           Backend API
 │                      │                     │                    │                   │
 │ Enter credentials    │                     │                    │                   │
 │─────────────────────>│                     │                    │                   │
 │                      │                     │                    │                   │
 │                      │ loginCabinet()      │                    │                   │
 │                      │────────────────────────────────────────>│                   │
 │                      │                     │                    │                   │
 │                      │                     │                    │  POST /v1/user/login
 │                      │                     │                    │──────────────────>│
 │                      │                     │                    │                   │
 │                      │                     │                    │  { token, user }  │
 │                      │                     │                    │<──────────────────│
 │                      │<────────────────────────────────────────│                   │
 │                      │                     │                    │                   │
 │                      │ login(user, token)  │                    │                   │
 │                      │────────────────────>│                    │                   │
 │                      │                     │                    │                   │
 │                      │                     │ Save to localStorage                  │
 │                      │                     │ - auth_token       │                   │
 │                      │                     │ - user             │                   │
 │                      │                     │                    │                   │
 │                      │ Redirect to Home    │                    │                   │
 │<─────────────────────│                     │                    │                   │
```

### Authenticated Request Flow

```
Component            cifClient          Interceptor        Backend API
    │                    │                   │                  │
    │ API Request        │                   │                  │
    │───────────────────>│                   │                  │
    │                    │                   │                  │
    │                    │ Request           │                  │
    │                    │──────────────────>│                  │
    │                    │                   │                  │
    │                    │                   │ Get token from   │
    │                    │                   │ localStorage     │
    │                    │                   │                  │
    │                    │                   │ Add header:      │
    │                    │                   │ Authorization:   │
    │                    │                   │ Bearer {token}   │
    │                    │                   │                  │
    │                    │                   │ Send request     │
    │                    │                   │─────────────────>│
    │                    │                   │                  │
    │                    │                   │  Response        │
    │                    │                   │<─────────────────│
    │                    │<──────────────────│                  │
    │<───────────────────│                   │                  │
```

### Logout Flow

```
User              Header              AuthContext         localStorage
 │                  │                      │                   │
 │ Click Logout     │                      │                   │
 │─────────────────>│                      │                   │
 │                  │                      │                   │
 │                  │ logout()             │                   │
 │                  │─────────────────────>│                   │
 │                  │                      │                   │
 │                  │                      │ Remove auth_token │
 │                  │                      │──────────────────>│
 │                  │                      │                   │
 │                  │                      │ Remove user       │
 │                  │                      │──────────────────>│
 │                  │                      │                   │
 │                  │ Redirect to Home     │                   │
 │<─────────────────│                      │                   │
```

---

## 🔌 API Integration

### Backend API Endpoints

#### 1. Login API

**Endpoint:** `POST /v1/user/login`

**Request:**
```json
{
  "email": "user@example.com",
  "password": "User@123"
}
```

**Success Response (200):**
```json
{
  "version": "v.1.0.0",
  "status": true,
  "message": "Login successful",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "username": "johndoe",
      "email": "user@example.com",
      "createdAt": "2026-02-11T10:00:00.000Z"
    }
  }
}
```

**Error Response (400/401):**
```json
{
  "version": "v.1.0.0",
  "status": false,
  "message": "Invalid credentials"
}
```

#### 2. Register API

**Endpoint:** `POST /v1/user/register`

**Request:**
```json
{
  "email": "newuser@example.com",
  "username": "newuser",
  "password": "NewUser@123"
}
```

**Success Response (201):**
```json
{
  "version": "v.1.0.0",
  "status": true,
  "message": "Registration successful",
  "data": {
    "user": {
      "id": 2,
      "username": "newuser",
      "email": "newuser@example.com"
    }
  }
}
```

**Error Response (400):**
```json
{
  "version": "v.1.0.0",
  "status": false,
  "message": "Your password must be at least 6 characters, 1 uppercase character, 1 lowercase character, 1 numeric character, and one special character"
}
```

### Token Format

JWT Token yang diterima dari backend akan digunakan sebagai Bearer token di setiap request:

```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

---

## 📦 Component Reference

### AuthContext

**File:** `src/context/AuthContext.jsx`

**Provider:**
```jsx
<AuthProvider>
  {children}
</AuthProvider>
```

**Hook:**
```jsx
const { user, token, login, logout, isAuthenticated, loading } = useAuth();
```

**Properties:**
- `user: Object | null` - Current user data
- `token: string | null` - Authentication token
- `loading: boolean` - Loading state during initialization
- `login: (userData, authToken) => void` - Function to login
- `logout: () => void` - Function to logout
- `isAuthenticated: () => boolean` - Check if user is authenticated

**Example Usage:**
```jsx
'use client';

import { useAuth } from '@/context/AuthContext';

export default function ProfilePage() {
  const { user, isAuthenticated, logout } = useAuth();

  if (!isAuthenticated()) {
    return <div>Please login</div>;
  }

  return (
    <div>
      <h1>Welcome, {user.username}!</h1>
      <p>Email: {user.email}</p>
      <button onClick={logout}>Logout</button>
    </div>
  );
}
```

### ProtectedRoute

**File:** `src/components/ProtectedRoute.jsx`

**Usage:**
```jsx
import ProtectedRoute from '@/components/ProtectedRoute';

export default function DashboardPage() {
  return (
    <ProtectedRoute>
      <div>
        {/* Protected content - only accessible when logged in */}
        <h1>Dashboard</h1>
      </div>
    </ProtectedRoute>
  );
}
```

**Behavior:**
- Shows loading spinner while checking authentication
- Redirects to `/pages/auth/login-cabinet` if not authenticated
- Renders children if authenticated

### GuestRoute

**File:** `src/components/GuestRoute.jsx`

**Usage:**
```jsx
import GuestRoute from '@/components/GuestRoute';

export default function LoginPage() {
  return (
    <GuestRoute>
      <div>
        {/* Guest-only content - redirects to home if already logged in */}
        <h1>Login</h1>
      </div>
    </GuestRoute>
  );
}
```

**Behavior:**
- Shows loading spinner while checking authentication
- Redirects to `/` (home) if already authenticated
- Renders children if not authenticated

### HTTP Client

**File:** `src/services/httpClient.js`

**Features:**

1. **Auto Token Injection:**
```javascript
// Request interceptor automatically adds token
config.headers.Authorization = `Bearer ${localStorage.getItem('auth_token')}`;
```

2. **Auto 401 Handling:**
```javascript
// Response interceptor handles unauthorized requests
if (error.response?.status === 401) {
  // Clear auth data
  localStorage.removeItem('auth_token');
  localStorage.removeItem('user');
  // Redirect to login
  window.location.href = '/pages/auth/login-cabinet';
}
```

**Example API Calls:**
```javascript
import { cifClient } from '@/services/cifClient';

// GET request
const profile = await cifClient.get('/v1/user/profile');

// POST request
const transaction = await cifClient.post('/v1/transaction', {
  amount: 1000,
  type: 'deposit'
});

// PUT request
const updated = await cifClient.put('/v1/user/profile', {
  username: 'newname'
});

// DELETE request
await cifClient.delete('/v1/user/session');
```

---

## 🔒 Security Considerations

### Current Implementation (localStorage)

**Pros:**
- ✅ Simple implementation
- ✅ Easy to access from client-side
- ✅ Persists across page reloads
- ✅ No server-side configuration needed

**Cons:**
- ⚠️ Vulnerable to XSS (Cross-Site Scripting) attacks
- ⚠️ Token exposed to JavaScript
- ⚠️ Not HTTP-only

### Best Practices Applied

1. **Token Auto-Expiration:**
   - Backend should implement token expiration
   - Frontend auto-redirects on 401 Unauthorized

2. **HTTPS Only:**
   - Always use HTTPS in production
   - Prevents man-in-the-middle attacks

3. **Input Validation:**
   - Validate user inputs before sending to API
   - Prevent XSS injection

4. **No Sensitive Data in localStorage:**
   - Only store token and basic user info
   - Never store passwords or credit card info

### Recommended Improvements

For production environment, consider:

1. **HTTP-Only Cookies:**
   - More secure than localStorage
   - Protected from XSS
   - Requires backend support

2. **Refresh Token Mechanism:**
   - Short-lived access tokens
   - Long-lived refresh tokens
   - Auto token renewal

3. **CSRF Protection:**
   - Add CSRF tokens for state-changing operations
   - Use SameSite cookies

---

## ⚠️ Error Handling

### API Errors

**Login Errors:**
```javascript
try {
  await loginCabinet({ email, password });
} catch (err) {
  // Extract error message from response
  const errorMessage = err.response?.data?.message || 'Login failed';
  setError(errorMessage);
}
```

**Common Error Messages:**
- `"Invalid credentials"` - Wrong email/password
- `"User not found"` - Email doesn't exist
- `"Account locked"` - Too many failed attempts

**Register Errors:**
```javascript
try {
  await regisCabinet({ email, username, password });
} catch (err) {
  const errorMessage = err.response?.data?.message || 'Registration failed';
  setError(errorMessage);
}
```

**Common Error Messages:**
- `"Email already exists"` - Duplicate email
- `"Username already taken"` - Duplicate username
- `"Password too weak"` - Password validation failed

### Network Errors

```javascript
// Handled in httpClient.js
axios.create({
  timeout: 10000, // 10 seconds
});

// If request takes too long
catch (error) {
  if (error.code === 'ECONNABORTED') {
    console.error('Request timeout');
  }
  if (!error.response) {
    console.error('Network error - check internet connection');
  }
}
```

### Token Expiration

```javascript
// Auto-handled in httpClient response interceptor
if (error.response?.status === 401) {
  // Clear auth and redirect to login
  localStorage.removeItem('auth_token');
  localStorage.removeItem('user');
  window.location.href = '/pages/auth/login-cabinet';
}
```

---

## 🧪 Testing Guide

### Manual Testing

#### 1. Test Login Flow

```
✓ Navigate to /pages/auth/login-cabinet
✓ Enter valid credentials
✓ Click "Masuk" button
✓ Verify redirect to homepage
✓ Verify header shows username and logout button
✓ Verify localStorage contains auth_token and user
```

#### 2. Test Registration Flow

```
✓ Navigate to /pages/auth/regis-cabinet
✓ Fill in all fields (email, username, password, confirm password)
✓ Click "Daftar" button
✓ Verify redirect to login page
✓ Login with new credentials
```

#### 3. Test Protected Routes

```
✓ Logout if logged in
✓ Try to access protected page (e.g., /pages/dashboard)
✓ Verify redirect to login page
✓ Login
✓ Try to access protected page again
✓ Verify page loads successfully
```

#### 4. Test Guest Routes

```
✓ Login to the app
✓ Try to access /pages/auth/login-cabinet
✓ Verify redirect to homepage
✓ Try to access /pages/auth/regis-cabinet
✓ Verify redirect to homepage
```

#### 5. Test Logout Flow

```
✓ Login to the app
✓ Verify header shows user info
✓ Click "Logout" button
✓ Verify redirect to homepage
✓ Verify header shows "Real Account" button
✓ Verify localStorage is cleared
✓ Try to access protected page
✓ Verify redirect to login
```

#### 6. Test Token Auto-Injection

```
✓ Login to the app
✓ Open browser DevTools > Network tab
✓ Make any API request (e.g., fetch profile)
✓ Check request headers
✓ Verify "Authorization: Bearer {token}" is present
```

#### 7. Test 401 Handling

```
✓ Login to the app
✓ Manually delete auth_token from localStorage
✓ Make any API request
✓ Verify automatic redirect to login page
```

### Automated Testing Examples

**Test Login Component:**
```javascript
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import LoginPage from '@/app/pages/auth/login-cabinet/page';

test('should login successfully with valid credentials', async () => {
  render(<LoginPage />);
  
  fireEvent.change(screen.getByLabelText(/email/i), {
    target: { value: 'test@example.com' }
  });
  
  fireEvent.change(screen.getByLabelText(/password/i), {
    target: { value: 'Test@123' }
  });
  
  fireEvent.click(screen.getByRole('button', { name: /masuk/i }));
  
  await waitFor(() => {
    expect(localStorage.getItem('auth_token')).toBeTruthy();
  });
});
```

---

## 🔧 Troubleshooting

### Common Issues

#### 1. "Cannot read property 'user' of undefined"

**Cause:** useAuth() called outside AuthProvider  
**Solution:** Ensure component is wrapped with AuthProvider in layout.js

```jsx
// layout.js
import ClientProviders from '@/components/ClientProviders';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ClientProviders>
          {children}
        </ClientProviders>
      </body>
    </html>
  );
}
```

#### 2. Token not being sent with requests

**Cause:** cifClient not being used, or localStorage not set  
**Solution:** 
- Use `cifClient` instead of `axios` or `fetch`
- Check if auth_token exists in localStorage
- Verify httpClient.js interceptor is configured

#### 3. Infinite redirect loop between login and home

**Cause:** GuestRoute and authentication check conflict  
**Solution:** 
- Check if token is valid
- Clear localStorage and try again
- Verify isAuthenticated() logic

#### 4. User data not persisting after page reload

**Cause:** localStorage not being loaded on mount  
**Solution:** Check AuthContext useEffect hook

```jsx
useEffect(() => {
  const savedUser = localStorage.getItem('user');
  const savedToken = localStorage.getItem('auth_token');
  
  if (savedUser && savedToken) {
    setUser(JSON.parse(savedUser));
    setToken(savedToken);
  }
  setLoading(false);
}, []);
```

#### 5. CORS errors when calling API

**Cause:** Backend not configured to allow frontend origin  
**Solution:** Configure CORS on backend

```javascript
// Backend (Express.js example)
app.use(cors({
  origin: process.env.FRONTEND_URL,
  credentials: true
}));
```

#### 6. "Network Error" on API calls

**Possible Causes:**
- Backend server not running
- Wrong API URL in .env
- Network/firewall blocking requests

**Solution:**
```bash
# Check .env file
NEXT_PUBLIC_CIF_URL=http://localhost:5000/api

# Verify backend is running
curl http://localhost:5000/api/v1/user/login

# Check network tab in DevTools for detailed error
```

---

## 📚 Additional Resources

### Environment Variables

Create `.env.local` file in root directory:

```env
NEXT_PUBLIC_CIF_URL=https://api.yourdomain.com/api
```

### File Structure Summary

```
src/
├── context/
│   └── AuthContext.jsx          # Auth state management
├── components/
│   ├── ClientProviders.jsx      # Client-side providers wrapper
│   ├── ProtectedRoute.jsx       # Protected page wrapper
│   ├── GuestRoute.jsx           # Guest-only page wrapper
│   └── Header.jsx               # Header with auth UI
├── services/
│   ├── httpClient.js            # Axios with interceptors
│   └── cifClient.js             # CIF API client
├── modules/
│   └── api/
│       └── auth/
│           ├── loginCabinet.js  # Login API function
│           └── regisCabinet.js  # Register API function
└── app/
    ├── layout.js                # Root layout with AuthProvider
    └── pages/
        └── auth/
            ├── login-cabinet/
            │   └── page.jsx     # Login page
            └── regis-cabinet/
                └── page.jsx     # Register page
```

### Quick Reference

**Check if logged in:**
```jsx
const { isAuthenticated } = useAuth();
if (isAuthenticated()) {
  // User is logged in
}
```

**Get current user:**
```jsx
const { user } = useAuth();
console.log(user.username, user.email);
```

**Logout:**
```jsx
const { logout } = useAuth();
logout();
```

**Protect a page:**
```jsx
import ProtectedRoute from '@/components/ProtectedRoute';

export default function Page() {
  return <ProtectedRoute>{/* content */}</ProtectedRoute>;
}
```

---

## 📝 Changelog

**Version 1.0.0** (2026-02-11)
- ✅ Initial authentication system implementation
- ✅ Login & Register pages
- ✅ AuthContext with localStorage
- ✅ ProtectedRoute & GuestRoute components
- ✅ Auto token injection in HTTP requests
- ✅ Auto 401 handling and redirect
- ✅ Header with dynamic auth UI
- ✅ Logout functionality

---

## 👥 Support

For issues or questions:
1. Check [Troubleshooting](#troubleshooting) section
2. Review [AUTH_IMPLEMENTATION.md](AUTH_IMPLEMENTATION.md)
3. Check browser console for errors
4. Verify API responses in Network tab
5. Check localStorage values in Application tab

---

**Last Updated:** February 11, 2026  
**Version:** 1.0.0
