add docs part 1
This commit is contained in:
362
docs/login-flow.md
Normal file
362
docs/login-flow.md
Normal file
@@ -0,0 +1,362 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user