# we-mp-rss API Authentication Debugging

## Auth Header Format
```
Authorization: AK-SK {access_key}:{secret_key}
```
Example: `Authorization: AK-SK WKn4p...:SKuv1...`

## Secret Key Hashing: SHA256 (NOT bcrypt)

Wrong (will produce broken hashes):
```python
import bcrypt
hashed = bcrypt.hashpw(SK.encode(), bcrypt.gensalt()).decode()
```

Correct:
```python
import hashlib
hashed = hashlib.sha256(SK.encode()).hexdigest()  # 64-char hex string
```

The `secret` column in `access_keys` table is `VARCHAR(64)` — SHA256 hex digest fits perfectly.

## Database Setup (Fresh Install)

The `access_keys` table is empty by default. To insert a key:

```sql
INSERT INTO access_keys (id, user_id, key, secret, name, description, permissions, is_active, created_at, updated_at, expires_at)
VALUES (
    '<uuid>',
    '<existing_user_id>',   -- MUST match a user.id from users table!
    '<access_key>',
    '<sha256_of_secret_key>',
    'app-name',
    'Description',
    'full',
    1,
    '<iso_timestamp>',
    '<iso_timestamp>',
    '<expiry_timestamp>'
);
```

## Critical: user_id Must Exist

`authenticate_ak()` calls `get_user_by_id(ak.user_id)` — if the user doesn't exist, auth fails with "Could not validate credentials" even though the AK/SK is correct.

The default admin user is typically `id=0, username=admin, role=admin`.

## Debugging Steps

1. Check if access key exists: `SELECT key, user_id, is_active FROM access_keys;`
2. Check if user exists: `SELECT id, username, role FROM users;`
3. Verify the key matches: compare SHA256 of the SK against stored `secret` column
4. Test API: `curl -H "Authorization: AK-SK <ak>:<sk>" http://localhost:8001/api/v1/wx/articles?page=1&page_size=1`

## Common Errors

| Symptom | Cause |
|---------|-------|
| `Could not validate credentials` | user_id doesn't exist, or SK hash mismatch |
| `Could not validate credentials` (database had bcrypt hash) | Used bcrypt instead of SHA256 |
| API returns 401 even with correct AK/SK | user_id points to nonexistent user |
