# Authentication Dependencies Guide

## Overview

FastAPI routes use different authentication dependencies based on whether they serve **HTML pages** or **API endpoints**.

## Available Dependencies

### Admin Authentication

| Dependency | Use Case | Accepts | Description |
|------------|----------|---------|-------------|
| `get_current_admin_from_cookie_or_header` | HTML pages | Cookie OR Header | For admin HTML routes like `/admin/dashboard` |
| `get_current_admin_api` | API endpoints | Header ONLY | For admin API routes like `/api/v1/admin/stores` |
| `get_current_admin_optional` | Login pages | Cookie OR Header | Returns `None` instead of raising exception |

### Store Authentication

| Dependency | Use Case | Accepts | Description |
|------------|----------|---------|-------------|
| `get_current_store_from_cookie_or_header` | HTML pages | Cookie OR Header | For store HTML routes like `/store/{code}/dashboard` |
| `get_current_store_api` | API endpoints | Header ONLY | For store API routes like `/api/v1/store/{code}/products` |
| `get_current_store_optional` | Login pages | Cookie OR Header | Returns `None` instead of raising exception |

### Customer Authentication

| Dependency | Use Case | Accepts | Description |
|------------|----------|---------|-------------|
| `get_current_customer_from_cookie_or_header` | HTML pages | Cookie OR Header | For shop account pages like `/shop/account/dashboard` |
| `get_current_customer_api` | API endpoints | Header ONLY | For shop API routes like `/api/v1/shop/cart` |
| `get_current_customer_optional` | Login pages | Cookie OR Header | Returns `None` instead of raising exception |

## When to Use Which?

### Use `_from_cookie_or_header` for HTML Pages

HTML pages that render templates and are accessed by browsers:

```python
# app/routes/admin_pages.py
from app.api.deps import get_current_admin_from_cookie_or_header

@router.get("/admin/dashboard", response_class=HTMLResponse)
async def admin_dashboard(
    request: Request,
    current_user: User = Depends(get_current_admin_from_cookie_or_header)
):
    return templates.TemplateResponse("admin/dashboard.html", {...})
```

**Why?** Browsers automatically send cookies, making this seamless for page navigation.

### Use `_api` for API Endpoints

JSON API endpoints that are called by JavaScript:

```python
# app/api/v1/admin/stores.py
from app.api.deps import get_current_admin_api

@router.get("/api/v1/admin/stores")
async def list_stores(
    current_user: User = Depends(get_current_admin_api),
    db: Session = Depends(get_db)
):
    return {"stores": [...]}
```

**Why?**
- **Security**: API endpoints should NOT accept cookies (prevents CSRF attacks)
- **Explicit**: JavaScript must explicitly set Authorization header
- **Stateless**: API calls are stateless and don't rely on browser cookies

### Use `_optional` for Login Pages

Login pages that redirect if already authenticated:

```python
# app/routes/admin_pages.py
from app.api.deps import get_current_admin_optional

@router.get("/admin/login", response_class=HTMLResponse)
async def admin_login_page(
    request: Request,
    current_user: Optional[User] = Depends(get_current_admin_optional)
):
    if current_user:
        return RedirectResponse("/admin/dashboard")
    return templates.TemplateResponse("admin/login.html", {...})
```

**Why?** Avoids showing login page to already-authenticated users.

## Migration Guide

### Old vs New Names

The authentication dependencies were renamed for clarity:

| ❌ Old Name (REMOVED) | ✅ New Name | Type |
|----------------------|-------------|------|
| `get_current_admin_user` | `get_current_admin_from_cookie_or_header` | HTML pages |
| `get_current_admin_user` | `get_current_admin_api` | API endpoints |
| `get_current_store_user` | `get_current_store_from_cookie_or_header` | HTML pages |
| `get_current_store_user` | `get_current_store_api` | API endpoints |

### How to Update Your Code

1. **Identify route type**: Is it an HTML page or API endpoint?
2. **Choose correct dependency**:
   - HTML page → `_from_cookie_or_header`
   - API endpoint → `_api`
3. **Update import and usage**

#### Example 1: HTML Page Route

**Before:**
```python
from app.api.deps import get_current_admin_user  # ❌ Doesn't exist

@router.get("/admin/settings")
def settings_page(current_user: User = Depends(get_current_admin_user)):
    ...
```

**After:**
```python
from app.api.deps import get_current_admin_from_cookie_or_header  # ✅

@router.get("/admin/settings")
def settings_page(
    current_user: User = Depends(get_current_admin_from_cookie_or_header)
):
    ...
```

#### Example 2: API Endpoint

**Before:**
```python
from app.api.deps import get_current_admin_user  # ❌ Doesn't exist

@router.post("/api/v1/admin/stores")
def create_store(current_user: User = Depends(get_current_admin_user)):
    ...
```

**After:**
```python
from app.api.deps import get_current_admin_api  # ✅

@router.post("/api/v1/admin/stores")
def create_store(current_user: User = Depends(get_current_admin_api)):
    ...
```

## Quick Reference

```python
# All available in app.api.deps

# ADMIN
from app.api.deps import (
    get_current_admin_from_cookie_or_header,  # HTML pages
    get_current_admin_api,                     # API endpoints
    get_current_admin_optional,                # Login pages
)

# STORE
from app.api.deps import (
    get_current_store_from_cookie_or_header,  # HTML pages
    get_current_store_api,                     # API endpoints
    get_current_store_optional,                # Login pages
)

# CUSTOMER
from app.api.deps import (
    get_current_customer_from_cookie_or_header,  # HTML pages
    get_current_customer_api,                     # API endpoints
    get_current_customer_optional,                # Login pages
)

# GENERIC (any authenticated user)
from app.api.deps import get_current_user  # Header-only, any role
```

## See Also

- [Authentication Documentation](../api/authentication.md) - Complete auth system docs
- [Authentication Flow Diagrams](../api/authentication-flow-diagrams.md) - Visual flows
- Source code: `app/api/deps.py` - Authentication dependency implementations
