363 lines
12 KiB
Markdown
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)
|