Authentication¶
Login flow and session management for the PWA.
Overview¶
The PWA uses session-based authentication against Odoo's authentication system. Users log in with their Odoo credentials, and the session is maintained in Flask with a 24-hour lifetime.
Login Flow¶
sequenceDiagram
participant User
participant PWA as PWA (Flask)
participant Odoo
User->>PWA: GET /login
PWA-->>User: Login page
User->>PWA: POST /login (username, password)
PWA->>Odoo: POST /web/session/authenticate
Note over Odoo: Validates credentials
alt Valid credentials
Odoo-->>PWA: {uid, username, name, session_id}
PWA->>Odoo: GET user partner_id
Odoo-->>PWA: {partner_id}
PWA->>PWA: Store in session
PWA-->>User: Redirect to /jobs/active
else Invalid credentials
Odoo-->>PWA: {uid: false}
PWA-->>User: "Invalid username or password"
end
Routes¶
Login¶
GET /login
Displays the login form. Redirects to /jobs/active if already logged in.
POST /login
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | string | Yes | Odoo username/email |
| password | string | Yes | Odoo password |
| remember | checkbox | No | Keep session for 24 hours |
Logout¶
GET /logout
Clears the session and redirects to login page.
Session Data¶
After successful login, the following data is stored in the Flask session:
| Key | Type | Description |
|---|---|---|
user_id |
int | Odoo user ID (res.users.id) |
username |
string | Login username |
user_name |
string | User's display name |
partner_id |
int | Associated partner ID for activity attribution |
Session Configuration¶
class Config:
# Session lifetime (24 hours with "Remember me")
PERMANENT_SESSION_LIFETIME = timedelta(hours=24)
# Security settings
SESSION_COOKIE_SECURE = True # HTTPS only in production
SESSION_COOKIE_HTTPONLY = True # Not accessible via JavaScript
SESSION_COOKIE_SAMESITE = 'Lax' # CSRF protection
Login Required Decorator¶
Protected routes use the @login_required decorator:
from functools import wraps
from flask import session, redirect, url_for, flash
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'user_id' not in session:
flash('Please log in to access this page.', 'warning')
return redirect(url_for('auth.login'))
return f(*args, **kwargs)
return decorated_function
Usage:
Odoo Authentication API¶
The PWA authenticates against Odoo's session endpoint:
def authenticate_user(self, username: str, password: str) -> dict:
url = f"{self.base_url}/web/session/authenticate"
payload = {
"jsonrpc": "2.0",
"method": "call",
"params": {
"db": self.db,
"login": username,
"password": password
},
"id": 1
}
response = requests.post(url, json=payload, timeout=10)
result = response.json()
if result.get('error') or not result.get('result', {}).get('uid'):
raise Exception('Invalid username or password')
return {
'uid': result['result']['uid'],
'username': result['result'].get('username', username),
'name': result['result'].get('name', username),
'session_id': result['result'].get('session_id')
}
Partner ID for Activity Attribution¶
After login, the PWA fetches the user's partner_id to properly attribute activities:
def get_user_partner_id(self, user_id: int) -> int:
result = self._jsonrpc_call('res.users', 'search_read',
[[('id', '=', user_id)]],
{'fields': ['partner_id'], 'limit': 1}
)
if result and result[0].get('partner_id'):
return result[0]['partner_id'][0]
return None
This partner_id is used when:
- Posting comments to activity logs
- Changing stages (FSM, CRM)
- Recording who performed actions
Security Considerations¶
CSRF Protection¶
All forms include CSRF tokens via Flask-WTF:
Password Handling¶
- Passwords are never stored in the PWA
- Passwords are transmitted over HTTPS only
- Session tokens are HTTP-only cookies
Session Security¶
- Sessions expire after 24 hours (with "Remember me")
- Sessions are cleared on logout
- Cookie is marked
Securein production
Troubleshooting¶
"Please log in to access this page"¶
Session has expired or was cleared. Log in again.
"Invalid username or password"¶
- Verify credentials work in Odoo directly
- Check
ODOO_BASE_URLandODOO_DBin.env - Ensure user account is active in Odoo
Session Not Persisting¶
- Check
SECRET_KEYis set and stable - Verify cookies are enabled in browser
- Check for HTTPS issues (Secure cookie flag)