Life Cost authenticates users exclusively through Google OAuth 2.0 via Flask-Dance. After a successful OAuth exchange, Flask-Login writes a server-side session and sets a signed session cookie in the browser. Every subsequent request to a protected endpoint carries that cookie automatically — no manual token management is required in a normal browser context.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/akevalion/life_cost/llms.txt
Use this file to discover all available pages before exploring further.
How It Works
When a user visits the application without an active session, they are sent through the Google OAuth consent screen. Once consent is granted, Google calls back to the application, which looks up (or creates) the matching user record by email, then callslogin_user(). From that point on, Flask-Login reads the session cookie on every request to determine current_user.
All wallet-scoped data (transactions, analytics, etc.) is automatically filtered by current_user.last_visited_wallet_id, so the session context controls not just authentication but also which wallet’s data is returned.
Auth Flow Step-by-Step
Visit the home page
The browser requests
GET /. If current_user.is_authenticated is False, the view immediately issues a redirect to /google_login.Entry point — /google_login
GET /google_login checks whether Flask-Dance has a stored Google token (google.authorized). If not, it redirects the browser to the Google OAuth consent screen via Flask-Dance’s internal url_for("google.login") helper.Google OAuth consent screen
The browser is sent to Google with the scopes:
https://www.googleapis.com/auth/userinfo.emailhttps://www.googleapis.com/auth/userinfo.profileopenid
OAuth callback — /login/google/authorized
Google redirects the browser back to the Flask-Dance callback URL:Flask-Dance exchanges the authorisation code for an access token and stores it in the session, then redirects to the
redirect_to target — which is configured as auth.google_login (the same /google_login route).User lookup or creation
Back in
/google_login, google.authorized is now True. The handler calls the Google userinfo API to retrieve name, email, and picture.- If a
Userrow with that email already exists, the existing record is used as-is without modification. - If no row exists, a new
Useris created, all existing wallets are associated with the account, andlast_visited_wallet_idis set to the first available wallet.
Session cookie set — redirected home
login_user(user) writes the user’s ID into the Flask session. Flask serialises and signs the session as a cookie (session) and sends it back to the browser.current_user automatically.Session Persistence
The session cookie is tied to the browser that completed the OAuth flow. It persists until one of the following occurs:- The user explicitly logs out via
GET /logout. - The browser storage is cleared (cookies deleted).
- The server is restarted with a new
SECRET_KEY(which invalidates all existing signed cookies — note that the current implementation generates a random key on every startup withos.urandom(24), so sessions do not survive restarts by default).
Logging Out
Sending a browser request toGET /logout calls logout_user(), which clears the session, and then redirects to /.
@login_required — unauthenticated requests are redirected to /google_login before the logout logic runs.
Unauthenticated Requests
Endpoints decorated with
@login_required do not return a JSON 401 Unauthorized response when the session is absent. Instead, Flask-Login issues an HTTP 302 redirect to /google_login. Clients that do not follow redirects will receive a 302 with a Location: /google_login header and an empty body — not an error payload.302 redirects, verify that:
- A valid session cookie obtained from a completed OAuth flow is present in the request.
- The cookie domain and path match the request URL.
- The server has not been restarted since the cookie was issued (which would have rotated the
SECRET_KEY).
Configuration Reference
The following environment variables control the OAuth integration and must be set before starting the application:| Variable | Description |
|---|---|
GOOGLE_CLIENT_ID | OAuth 2.0 client ID from the Google Cloud Console |
GOOGLE_CLIENT_SECRET | OAuth 2.0 client secret from the Google Cloud Console |
DATABASE_URL | SQLAlchemy-compatible database connection string |