How TeslaMate Handles User Sessions and Authentication in Its Web Interface

TeslaMate uses a signed HTTP cookie session managed by Phoenix LiveView combined with encrypted OAuth tokens stored in the database to maintain secure user access and authenticate API calls to Tesla.

TeslaMate's web interface is built on the Phoenix framework and follows a conventional session-plus-token strategy to balance security with usability. The application separates transient browser session state from sensitive authentication credentials, ensuring that user sessions and authentication remain persistent across page loads while keeping OAuth tokens encrypted at rest. This architecture enables seamless interaction with the Tesla API without exposing tokens to the client-side browser.

HTTP Session Configuration

The foundation of TeslaMate's session handling lies in lib/teslamate_web/endpoint.ex, where the application configures a signed cookie store for all browser connections. The @session_options module attribute defines a strict same-site cookie policy to prevent cross-site request forgery.


# lib/teslamate_web/endpoint.ex

@session_options [
  store: :cookie,
  key: "_teslamate_key",
  signing_salt: "yt5O3CAQ",
  same_site: "Strict"
]

plug Plug.Session, @session_options

This configuration creates a signed cookie named _teslamate_key that persists the user's session ID and locale preferences. The same_site: "Strict" setting ensures the cookie is never sent in cross-origin requests, mitigating CSRF attacks.

Router Pipeline and Session Loading

Every HTTP request passes through the :browser pipeline defined in lib/teslamate_web/router.ex, which loads the session data and makes it available to LiveViews. The pipeline combines standard Phoenix plugs with custom locale handling.


# lib/teslamate_web/router.ex

pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session          # <-- loads the cookie into conn.session

  plug :fetch_live_flash
  plug Cldr.Plug.AcceptLanguage, cldr_backend: TeslaMateWeb.Cldr, no_match_log_level: :debug
  plug Cldr.Plug.PutLocale, apps: [:cldr, :gettext], from: [:query, :session, :accept_language], gettext: TeslaMateWeb.Gettext, cldr: TeslaMateWeb.Cldr
  plug TeslaMateWeb.Plugs.PutSession   # stores locale values in the session

  plug :protect_from_forgery
  plug :put_secure_browser_headers
  plug :fetch_settings                # puts global settings into conn.assigns and session

end

The fetch_session plug decodes the signed cookie, while TeslaMateWeb.Plugs.PutSession persists CLDR and Gettext locale selections back into the session for subsequent requests. The custom fetch_settings plug additionally loads global configuration from the database into both connection assigns and the session, ensuring settings remain available across LiveView reconnections.

OAuth Token Storage and Encryption

Unlike the transient session cookie, Tesla OAuth tokens receive persistent encrypted storage in the database. The TeslaMate.Auth context in lib/teslamate/auth.ex handles all create, read, update, and delete operations for authentication tokens.


# lib/teslamate/auth.ex

def save(%{token: access, refresh_token: refresh}) do
  attrs = %{access: access, refresh: refresh}

  maybe_created_or_updated =
    case get_tokens() do
      nil -> create_tokens(attrs)
      tokens -> update_tokens(tokens, attrs)
    end

  with {:ok, _tokens} <- maybe_created_or_updated, do: :ok
end

The actual token schema in lib/teslamate/auth/tokens.ex utilizes the Vault library to encrypt the access and refresh tokens at rest. This ensures that even with database access, an attacker cannot use the stored credentials without the encryption key.

Sign-In LiveView Process

User authentication occurs through TeslaMateWeb.SignInLive.Index, a LiveView module that renders the sign-in form and handles the OAuth flow. On mount, the view initializes a changeset for token fields and checks for environment-based configuration.


# lib/teslamate_web/live/signin_live/index.ex

def mount(_params, _session, socket) do
  assigns = %{
    api: get_api(socket),
    page_title: gettext("Sign in"),
    error: nil,
    task: nil,
    changeset: Auth.change_tokens(),
    token: System.get_env("TOKEN", ""),
    provider: System.get_env("TESLA_AUTH_HOST", "https://auth.tesla.com")
  }

  {:ok, assign(socket, assigns)}
end

When a user submits credentials, the handle_event("sign_in") function spawns a background Task that calls the Tesla API. Upon successful authentication, the returned token pair passes to Auth.save/1, which encrypts and persists them to the database. The user then redirects to the main car view while the browser retains the original session cookie, preserving locale and UI state.

API Request Authentication

All outbound requests to Tesla's API include the stored access token via middleware. The TeslaApi.Middleware.TokenAuth module in lib/tesla_api/middleware/token_auth.ex intercepts every request and injects the bearer token into the authorization header.


# lib/tesla_api/middleware/token_auth.ex

def call(%Tesla.Env{} = env, next, _opts) do
  env =
    case env.opts[:access_token] do
      nil -> env
      token -> Tesla.put_header(env, "Authorization", "Bearer " <> token)
    end

  Tesla.run(env, next)
end

This middleware retrieves the decrypted access token from the database through the API module, ensuring that no token data ever reaches the client-side JavaScript or browser storage.

End-to-End Session Lifecycle

The complete session and authentication flow follows these steps:

  1. Initial Request: The browser hits TeslaMateWeb.Endpoint, which creates the signed _teslamate_key cookie.
  2. Pipeline Processing: Plug.Session loads the cookie into conn.session, and PutSession persists locale data.
  3. Authentication: The user visits /sign_in and submits credentials through SignInLive.Index.
  4. Token Persistence: On successful API validation, Auth.save/1 encrypts and stores tokens via the Tokens schema.
  5. API Usage: Subsequent background syncs use TokenAuth middleware to attach the bearer token to Tesla API requests.
  6. Session Continuity: Page reloads or LiveView reconnections restore state from the signed cookie without requiring re-authentication.

Summary

  • Signed cookies handle browser session state via Plug.Session configured in endpoint.ex with strict same-site policies.
  • Encrypted database storage protects OAuth tokens using the Vault library in the Tokens schema, accessed through the Auth context.
  • Phoenix LiveView manages the sign-in flow through SignInLive.Index, spawning background tasks for API calls to prevent UI blocking.
  • Middleware injection automatically adds bearer tokens to outbound requests via TeslaApi.Middleware.TokenAuth, keeping credentials server-side only.
  • Locale persistence survives page reloads through the custom PutSession plug, storing CLDR and Gettext settings in the same signed cookie.

Frequently Asked Questions

How does TeslaMate secure OAuth tokens from unauthorized access?

TeslaMate stores OAuth tokens in a PostgreSQL database using the Vault library for encryption at rest. The TeslaMate.Auth.Tokens schema encrypts both the access and refresh tokens before persistence, ensuring that database access alone does not compromise account credentials.

What maintains the user session during page reloads or browser restarts?

A signed HTTP cookie named _teslamate_key maintains the session, configured in lib/teslamate_web/endpoint.ex with same_site: "Strict" protection. This cookie persists the session ID and locale preferences, allowing LiveViews to restore state without requiring repeated authentication.

Does the Tesla API token ever reach the user's browser?

No, the Tesla API access token never leaves the server. The TeslaApi.Middleware.TokenAuth module injects the bearer token into API requests on the backend only. The browser receives only the signed session cookie, which contains no OAuth credentials.

How does the application handle the initial sign-in process?

The TeslaMateWeb.SignInLive.Index LiveView renders a form backed by Auth.change_tokens/0. Upon submission, it spawns a background Task to call the Tesla API, then persists the returned tokens using Auth.save/1 before redirecting the user to the dashboard.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →