# Authentication

**Author**: Josh S. Sakweli, Backend Lead Team  
**Last Updated**: 2025-01-05  
**Version**: v1.0

**Base URL**: `https://api.fursahub.com/api/v1`

**Short Description**: Authentication endpoints for Fursa Hub platform. Handles user registration/login via Firebase, token management, and session control. All new users start the onboarding flow after successful authentication.

**Hints**: 
- Firebase handles the actual sign-in (Google, Apple, Email) - your app gets a Firebase ID token
- Send that Firebase token to our backend to get Fursa Hub access tokens
- Access tokens expire in 1 hour, use refresh token to get new ones
- Pass `preferredLanguage` and `theme` during first authentication to set user preferences

---

## Authentication Flow

```
┌─────────────────────────────────────────────────────────────────────────┐
│                        AUTHENTICATION FLOW                               │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  1. USER OPENS APP                                                       │
│     └── App shows language selector (calls GET /languages)              │
│     └── User picks language (e.g., "sw" for Swahili)                    │
│     └── App stores language + theme preference locally                   │
│                                                                          │
│  2. USER SIGNS IN VIA FIREBASE                                          │
│     └── Google Sign-In / Apple Sign-In / Email+Password                 │
│     └── Firebase returns ID Token                                        │
│                                                                          │
│  3. APP SENDS TO FURSA HUB BACKEND                                      │
│     └── POST /auth/firebase/authenticate                                 │
│     └── Include: firebaseToken, preferredLanguage, theme                │
│                                                                          │
│  4. BACKEND RESPONSE                                                     │
│     ├── NEW USER: Creates account, returns tokens + onboarding status   │
│     └── EXISTING USER: Returns tokens + current onboarding status       │
│                                                                          │
│  5. CHECK ONBOARDING STATUS                                              │
│     └── onboarding.isComplete = false → Navigate to onboarding flow     │
│     └── onboarding.isComplete = true → Navigate to home screen          │
│                                                                          │
│  6. TOKEN MANAGEMENT                                                     │
│     └── Store accessToken (for API calls)                               │
│     └── Store refreshToken (for renewing accessToken)                   │
│     └── When accessToken expires → POST /auth/refresh                   │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘
```

---

## Standard Response Format

### Success Response Structure
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-01-05T10:30:45",
  "data": { }
}
```

### Error Response Structure
```json
{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-01-05T10:30:45",
  "data": "Error description"
}
```

---

## Endpoints

---

## 1. Authenticate with Firebase
**Purpose**: Exchange Firebase ID token for Fursa Hub access tokens. Creates new user if first time.

**Endpoint**: <span style="background-color: #007bff; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">POST</span> `{base_url}/auth/firebase/authenticate`

**Access Level**: 🌐 Public

**Authentication**: None (Firebase token in body)

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Content-Type | string | Yes | `application/json` |

**Request JSON Sample**:
```json
{
  "firebaseToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "preferredLanguage": "sw",
  "theme": "DARK",
  "deviceInfo": "Android 14, Samsung Galaxy S24"
}
```

**Request Body Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| firebaseToken | string | Yes | Firebase ID token from client SDK | Must be valid Firebase token |
| preferredLanguage | string | No | User's language preference | 2-5 chars (e.g., "en", "sw", "fr") |
| theme | string | No | UI theme preference | enum: `LIGHT`, `DARK`, `SYSTEM` |
| deviceInfo | string | No | Device information for session tracking | Max 255 chars |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Authentication successful",
  "action_time": "2025-01-05T10:30:45",
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "tokenType": "Bearer",
    "expiresIn": 3600,
    "user": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "email": "user@example.com",
      "username": "johndoe",
      "phoneNumber": null,
      "fullName": "John Doe",
      "profilePhotoUrl": "https://lh3.googleusercontent.com/...",
      "isPhoneVerified": false,
      "isEmailVerified": true,
      "preferredLanguage": "sw",
      "theme": "DARK",
      "authProvider": "GOOGLE",
      "role": "ROLE_USER",
      "createdAt": "2025-01-05T10:30:45"
    },
    "onboarding": {
      "isComplete": false,
      "currentStep": "PENDING_PHONE_VERIFICATION"
    }
  }
}
```

**Success Response Fields**:
| Field | Description |
|-------|-------------|
| accessToken | JWT token for API requests (expires in 1 hour) |
| refreshToken | Token to get new accessToken (expires in 30 days) |
| tokenType | Always "Bearer" |
| expiresIn | Access token lifetime in seconds |
| user | User profile information |
| user.theme | User's theme preference: LIGHT, DARK, or SYSTEM |
| onboarding.isComplete | `false` = must complete onboarding, `true` = can access app |
| onboarding.currentStep | Current onboarding step (see Onboarding docs) |

---

## 2. Refresh Access Token
**Purpose**: Get a new access token using refresh token when current one expires.

**Endpoint**: <span style="background-color: #007bff; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">POST</span> `{base_url}/auth/refresh`

**Access Level**: 🌐 Public

**Authentication**: None (refresh token in body)

**Request JSON Sample**:
```json
{
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

**Request Body Parameters**:
| Parameter | Type | Required | Description | Validation |
|-----------|------|----------|-------------|------------|
| refreshToken | string | Yes | Refresh token from authentication | Must be valid, non-expired |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Token refreshed successfully",
  "action_time": "2025-01-05T11:30:45",
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "tokenType": "Bearer",
    "expiresIn": 3600,
    "user": { ... },
    "onboarding": { ... }
  }
}
```

**Error Responses**:

*Invalid Refresh Token (401):*
```json
{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Invalid refresh token",
  "action_time": "2025-01-05T11:30:45",
  "data": "Invalid refresh token"
}
```

*Expired Refresh Token (401):*
```json
{
  "success": false,
  "httpStatus": "UNAUTHORIZED",
  "message": "Refresh token expired",
  "action_time": "2025-01-05T11:30:45",
  "data": "Refresh token expired"
}
```

---

## 3. Logout
**Purpose**: Invalidate all refresh tokens for the user, ending all sessions.

**Endpoint**: <span style="background-color: #007bff; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">POST</span> `{base_url}/auth/logout`

**Access Level**: 🔒 Protected

**Authentication**: Bearer Token

**Request Headers**:
| Header | Type | Required | Description |
|--------|------|----------|-------------|
| Authorization | string | Yes | `Bearer {accessToken}` |

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Logged out successfully",
  "action_time": "2025-01-05T12:00:00",
  "data": null
}
```

---

## 4. Get Supported Languages
**Purpose**: Get list of supported languages for language selector screen.

**Endpoint**: <span style="background-color: #28a745; color: white; padding: 4px 8px; border-radius: 4px; font-family: monospace; font-size: 12px; font-weight: bold;">GET</span> `{base_url}/languages`

**Access Level**: 🌐 Public

**Authentication**: None

**Success Response JSON Sample**:
```json
{
  "success": true,
  "httpStatus": "OK",
  "message": "Languages retrieved successfully",
  "action_time": "2025-01-05T10:00:00",
  "data": [
    {
      "code": "en",
      "name": "English",
      "nativeName": "English"
    },
    {
      "code": "sw",
      "name": "Swahili",
      "nativeName": "Kiswahili"
    },
    {
      "code": "fr",
      "name": "French",
      "nativeName": "Français"
    },
    {
      "code": "zh",
      "name": "Chinese",
      "nativeName": "中文"
    }
  ]
}
```

---

## Frontend Implementation Guide

### Step 1: First App Launch
```
Show language selector screen
├── Call GET /languages to get options
├── User selects language
├── Store locally: selectedLanguage, theme (default: SYSTEM)
└── Navigate to sign-in screen
```

### Step 2: Sign In
```
Firebase Sign-In
├── Use Firebase SDK (Google/Apple/Email)
├── On success, get Firebase ID token
└── Call POST /auth/firebase/authenticate with:
    - firebaseToken
    - preferredLanguage (from step 1)
    - theme (from step 1)
    - deviceInfo (optional)
```

### Step 3: Handle Response
```
Check response.data.onboarding.isComplete
├── false → Navigate to onboarding flow
│   └── Start at response.data.onboarding.currentStep
└── true → Navigate to home screen
```

### Step 4: Store Tokens
```
Save securely:
├── accessToken → For Authorization header
├── refreshToken → For token renewal
└── user data → For UI display
```

### Step 5: API Calls
```
All protected endpoints:
├── Add header: Authorization: Bearer {accessToken}
├── On 401 error → Try refresh token
│   ├── Success → Retry original request
│   └── Fail → Force re-login
└── Continue normal flow
```