Files
immish/docs/login-flow.md

363 lines
12 KiB
Markdown

# Authentication & Login
This document describes the authentication flow, login process, and session management.
## Overview
The app supports two authentication methods:
1. **Email/Password Login** - Traditional credentials
2. **OAuth Login** - External identity provider (SSO)
## Login Flow Diagram
```
┌─────────────────────────────────────────────────────────────────┐
│ Splash Screen │
│ - Check for existing session │
│ - Initialize databases │
└─────────────────────────────────────────────────────────────────┘
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Has Valid Token │ │ No Token/ │
│ │ │ Token Expired │
└─────────────────┘ └─────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Main App │ │ Login Page │
│ (Timeline) │ │ │
└─────────────────┘ └─────────────────┘
```
## Login Page UI
### Screen Layout
```
┌─────────────────────────────────────┐
│ │
│ [Immich Logo] │
│ (animated) │
│ │
│ "immich" text │
│ │
├─────────────────────────────────────┤
│ Server URL │
│ ┌─────────────────────────────┐ │
│ │ https://your-server.com │ │
│ └─────────────────────────────┘ │
│ │
│ [Next Button] │
│ │
│ [Settings] │
│ │
├─────────────────────────────────────┤
│ v1.2.3 Logs │
└─────────────────────────────────────┘
```
After server validation:
```
┌─────────────────────────────────────┐
│ │
│ [Immich Logo] │
│ │
│ server-url.com │
│ │
├─────────────────────────────────────┤
│ Email │
│ ┌─────────────────────────────┐ │
│ │ user@example.com │ │
│ └─────────────────────────────┘ │
│ │
│ Password │
│ ┌─────────────────────────────┐ │
│ │ •••••••• │ │
│ └─────────────────────────────┘ │
│ │
│ [Login Button] │
│ ───────────── │
│ [OAuth Button] │
│ │
│ [Back] │
└─────────────────────────────────────┘
```
## Server URL Validation
### Process
1. User enters server URL
2. App sanitizes URL (adds https:// if missing, removes trailing slash)
3. Attempts to resolve endpoint via `/.well-known/immich`
4. Falls back to `{url}/api` if well-known not found
5. Pings server to verify reachability
6. Stores validated URL locally
### Well-Known Discovery
```
GET {server_url}/.well-known/immich
Response:
{
"api": {
"endpoint": "/api" // or absolute URL
}
}
```
### Server Info Fetch
After URL validation, fetch server configuration:
```
GET /server/config
GET /server/features
```
This determines:
- Whether OAuth is enabled
- Whether password login is enabled
- OAuth button text
- Server version (for compatibility check)
## Email/Password Login
### API Request
```
POST /auth/login
Headers:
deviceModel: "iPhone 14 Pro" | "Pixel 7"
deviceType: "iOS" | "Android"
Body:
{
"email": "user@example.com",
"password": "secret123"
}
Response:
{
"accessToken": "eyJhbG...",
"userId": "uuid-here",
"userEmail": "user@example.com",
"name": "John Doe",
"isAdmin": false,
"shouldChangePassword": false,
"profileImagePath": "/path/to/image"
}
```
### Post-Login Actions
1. Store access token securely
2. Store user info locally
3. Generate/retrieve device ID
4. Connect WebSocket for real-time updates
5. Request gallery permissions
6. Start initial sync
7. Navigate to main app
## OAuth Login (PKCE Flow)
### Flow Diagram
```
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ App │ │ Server │ │ OAuth │ │ App │
│ │ │ │ │ Provider │ │ │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ 1. Request │ │ │
│ OAuth URL │ │ │
│───────────────►│ │ │
│ │ │ │
│ 2. Return URL │ │ │
│ + state │ │ │
│◄───────────────│ │ │
│ │ │ │
│ 3. Open Browser with code_challenge │
│────────────────────────────────►│ │
│ │ │ │
│ 4. User authenticates │ │
│ │ │ │
│ 5. Redirect with auth code │ │
│◄────────────────────────────────│ │
│ │ │ │
│ 6. Exchange code for token (with code_verifier) │
│───────────────►│ │ │
│ │ │ │
│ 7. Return access token │ │
│◄───────────────│ │ │
```
### PKCE Parameters
- **code_verifier**: Random 43-128 character string
- **code_challenge**: SHA256 hash of verifier, base64url encoded
- **state**: Random 32 character string for CSRF protection
### OAuth Request
```
GET /oauth/authorize?
code_challenge={code_challenge}&
code_challenge_method=S256&
state={state}
Response:
{
"url": "https://oauth-provider.com/auth?client_id=..."
}
```
### OAuth Callback
```
POST /oauth/callback
Body:
{
"url": "immich://oauth-callback?code=xxx&state=yyy",
"codeVerifier": "original_code_verifier"
}
Response:
{
"accessToken": "eyJhbG...",
"userId": "uuid-here",
...
}
```
## Session Management
### Access Token Storage
- Stored in secure/encrypted storage
- Token included in all API requests via header
- Automatically loaded on app start
### Request Authentication
All authenticated requests include:
```
Headers:
Authorization: Bearer {access_token}
x-immich-user-token: {access_token} // alternative
```
### Token Validation
On app start:
1. Load stored token
2. Call `GET /users/me` to validate
3. If valid, proceed to app
4. If invalid (401), redirect to login
## Logout
### Process
1. Call server logout endpoint
2. Clear local access token
3. Clear user data from database
4. Disable background backup
5. Cancel ongoing sync operations
6. Navigate to login screen
### API Request
```
POST /auth/logout
```
### Data Cleared on Logout
- Access token
- Current user info
- Asset ETag (sync marker)
- Auto endpoint switching settings
- Preferred WiFi name
- Local/external endpoint list
## Password Change
If `shouldChangePassword` is true after login:
1. Redirect to Change Password screen
2. User enters new password
3. Submit password change
```
PUT /auth/change-password
Body:
{
"password": "newSecurePassword123"
}
```
## Multi-Server Support
### Automatic Endpoint Switching
The app can automatically switch between local and external server URLs based on WiFi network:
1. Configure local endpoint (e.g., `http://192.168.1.100:2283`)
2. Configure external endpoint (e.g., `https://photos.example.com`)
3. Set preferred WiFi network name
4. When on preferred WiFi, use local endpoint
5. Otherwise, use external endpoint
### Auxiliary Endpoint Validation
Before switching, validate the new endpoint is reachable:
```
GET {endpoint}/users/me
Response: 200 OK = valid endpoint
```
## PIN Code / Local Auth
For the locked folder feature:
- User can set up a PIN code
- PIN is stored securely on device
- Biometric authentication can be used as alternative
### PIN Setup
```
PUT /auth/pin-code
Body:
{
"pinCode": "1234"
}
```
### PIN Verification
```
POST /auth/pin-code/verify
Body:
{
"pinCode": "1234"
}
```
## Error Handling
### Common Login Errors
| Error | User Message | Cause |
|-------|--------------|-------|
| Invalid URL | "Invalid server URL" | Malformed URL entered |
| Server unreachable | "Server is not reachable" | Network issue or wrong URL |
| SSL Error | "SSL certificate error" | Self-signed cert not trusted |
| Invalid credentials | "Login failed" | Wrong email/password |
| OAuth failed | "OAuth login failed" | OAuth flow interrupted |
| API exception | Error message from server | Server-side error |
### Validation Rules
- **URL**: Must be valid URL with http/https scheme
- **Email**: Must contain @, no leading/trailing spaces
- **Password**: No specific validation (server handles it)
## Version Compatibility
After connecting to server, check version compatibility:
1. Get app version
2. Get server version from `/server/version`
3. Compare major/minor versions
4. Show warning if mismatch detected
---
[Previous: Project Structure](./structure.md) | [Next: Main Navigation](./main-screens.md)