182 lines
4.8 KiB
Markdown
182 lines
4.8 KiB
Markdown
|
|
# Token Persistence Guide
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The Kosmi bridge now caches JWT authentication tokens to avoid repeated browser automation on every startup. The token is stored in a local directory that persists across Docker container rebuilds and restarts.
|
||
|
|
|
||
|
|
## How It Works
|
||
|
|
|
||
|
|
### Token Cache Location
|
||
|
|
|
||
|
|
The token cache is stored in a file called `kosmi_token_cache.json` in the following locations:
|
||
|
|
|
||
|
|
- **Docker (Production)**: `./data/kosmi_token_cache.json` (mounted from your host machine)
|
||
|
|
- **Local Development**: `~/.matterbridge/kosmi_token_cache.json`
|
||
|
|
|
||
|
|
### Token Cache Structure
|
||
|
|
|
||
|
|
The cache file contains:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||
|
|
"email": "your-email@example.com",
|
||
|
|
"expires_at": "2026-11-02T15:56:23Z",
|
||
|
|
"saved_at": "2025-11-02T15:56:23Z"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Token Lifecycle
|
||
|
|
|
||
|
|
1. **On Startup**: The bridge checks for a cached token
|
||
|
|
- If found and valid, it uses the cached token (no browser automation needed)
|
||
|
|
- If expired or expiring within 7 days, it performs fresh authentication
|
||
|
|
- If not found, it performs fresh authentication
|
||
|
|
|
||
|
|
2. **Token Expiry**: Kosmi JWT tokens expire after 1 year
|
||
|
|
- The bridge automatically refreshes tokens that expire within 7 days
|
||
|
|
- You'll see a log message indicating how long until the token expires
|
||
|
|
|
||
|
|
3. **Token Storage**: After successful authentication, the token is saved to the cache file
|
||
|
|
- File permissions are set to `0600` (read/write for owner only)
|
||
|
|
- The cache directory is created automatically if it doesn't exist
|
||
|
|
|
||
|
|
## Docker Configuration
|
||
|
|
|
||
|
|
### Volume Mount
|
||
|
|
|
||
|
|
The `docker-compose.yml` includes a volume mount for persistent storage:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
volumes:
|
||
|
|
- ./data:/app/data:z
|
||
|
|
```
|
||
|
|
|
||
|
|
This mounts the `./data` directory from your host machine into the container at `/app/data`.
|
||
|
|
|
||
|
|
### Environment Variable
|
||
|
|
|
||
|
|
The container sets the `MATTERBRIDGE_DATA_DIR` environment variable:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
environment:
|
||
|
|
- MATTERBRIDGE_DATA_DIR=/app/data
|
||
|
|
```
|
||
|
|
|
||
|
|
This tells the bridge where to store persistent data like the token cache.
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### First Run
|
||
|
|
|
||
|
|
On the first run with email/password configured:
|
||
|
|
|
||
|
|
1. The bridge will launch a headless browser
|
||
|
|
2. Authenticate with Kosmi using your credentials
|
||
|
|
3. Extract and cache the JWT token
|
||
|
|
4. Save it to `./data/kosmi_token_cache.json`
|
||
|
|
|
||
|
|
You'll see logs like:
|
||
|
|
|
||
|
|
```
|
||
|
|
level=info msg="No cached token found, performing authentication..."
|
||
|
|
level=info msg="Starting browser automation for authentication..."
|
||
|
|
level=info msg="💾 Token cached (expires in 8760h)"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Subsequent Runs
|
||
|
|
|
||
|
|
On subsequent runs (container restarts, rebuilds, etc.):
|
||
|
|
|
||
|
|
1. The bridge checks the cached token
|
||
|
|
2. If valid, uses it immediately (no browser needed)
|
||
|
|
3. Connects to Kosmi in seconds
|
||
|
|
|
||
|
|
You'll see logs like:
|
||
|
|
|
||
|
|
```
|
||
|
|
level=info msg="✅ Using cached token (expires in 8736h)"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Token Refresh
|
||
|
|
|
||
|
|
When the token is close to expiring (within 7 days):
|
||
|
|
|
||
|
|
1. The bridge automatically performs fresh authentication
|
||
|
|
2. Updates the cached token
|
||
|
|
3. Continues normal operation
|
||
|
|
|
||
|
|
You'll see logs like:
|
||
|
|
|
||
|
|
```
|
||
|
|
level=info msg="Cached token expires soon (2025-11-09T15:56:23Z), will refresh"
|
||
|
|
level=info msg="Starting browser automation for authentication..."
|
||
|
|
level=info msg="💾 Token cached (expires in 8760h)"
|
||
|
|
```
|
||
|
|
|
||
|
|
## File Structure
|
||
|
|
|
||
|
|
After running with authentication, your directory structure will look like:
|
||
|
|
|
||
|
|
```
|
||
|
|
irc-kosmi-relay/
|
||
|
|
├── data/ # Persistent data directory
|
||
|
|
│ └── kosmi_token_cache.json # Cached JWT token
|
||
|
|
├── docker-compose.yml
|
||
|
|
├── matterbridge.toml
|
||
|
|
└── ...
|
||
|
|
```
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Token Cache Not Persisting
|
||
|
|
|
||
|
|
If the token cache doesn't persist across container restarts:
|
||
|
|
|
||
|
|
1. Check that the `./data` directory exists and is writable
|
||
|
|
2. Verify the volume mount in `docker-compose.yml` is correct
|
||
|
|
3. Check container logs for permission errors
|
||
|
|
|
||
|
|
### Force Token Refresh
|
||
|
|
|
||
|
|
To force a fresh authentication (e.g., if credentials changed):
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Stop the container
|
||
|
|
docker-compose down
|
||
|
|
|
||
|
|
# Remove the cached token
|
||
|
|
rm ./data/kosmi_token_cache.json
|
||
|
|
|
||
|
|
# Start the container
|
||
|
|
docker-compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
### Check Token Status
|
||
|
|
|
||
|
|
To view the current cached token:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cat ./data/kosmi_token_cache.json | jq .
|
||
|
|
```
|
||
|
|
|
||
|
|
This will show you:
|
||
|
|
- When the token was saved
|
||
|
|
- When it expires
|
||
|
|
- Which email it's associated with
|
||
|
|
|
||
|
|
## Security Notes
|
||
|
|
|
||
|
|
- The token cache file has restricted permissions (`0600`) for security
|
||
|
|
- The token is a JWT that expires after 1 year
|
||
|
|
- The cache file is stored locally and never transmitted
|
||
|
|
- If you commit your code to version control, add `data/` to `.gitignore`
|
||
|
|
|
||
|
|
## Benefits
|
||
|
|
|
||
|
|
1. **Faster Startup**: No browser automation on every restart (saves 10-15 seconds)
|
||
|
|
2. **Reduced Resource Usage**: No need to launch Chromium on every startup
|
||
|
|
3. **Persistence**: Token survives container rebuilds, restarts, and host reboots
|
||
|
|
4. **Automatic Refresh**: Token is automatically refreshed before expiry
|
||
|
|
5. **Local Storage**: Token is stored on your host machine, not in the container
|