Skip to content

Identity and Authentication

This document describes the current frontend authentication and identity flow.

Overview

  • Authentication is session-based. A valid sessionid cookie indicates an authenticated session.
  • Login is handled via POST /account/login/ and sets the session cookie.
  • User identity, groups, and permissions are hydrated from GET /account/me/.
  • The app uses a user Pinia store for identity and permission checks.
  • The app uses app.loginRequired to toggle the login overlay.

Backend endpoints

  • POST /account/login/
    • Response includes:
      • user (string)
      • user_detail (object with basic user fields)
      • groups (array of Django groups)
      • permissions (array of permission strings)
  • GET /account/me/
    • Requires authentication.
    • Response includes:
      • user (user id)
      • user_detail (object with basic user fields)
      • groups (array of Django groups)
      • permissions (array of permission strings)
  • POST /account/logout/
    • Logs out the current session.

Frontend flow

Login

  • The login overlay is shown when app.loginRequired is true.
  • Login.vue posts credentials to /account/login/.
  • On success, it populates the user store from the response and reloads the page.

Session detection

  • Default.vue watches the sessionid cookie.
  • If the cookie is missing:
    • app.loginRequired is set to true
    • userStore.clear() is called
  • If the cookie is present:
    • app.loginRequired is set to false
    • userStore.hydrate() calls /account/me/ to refresh identity data

Request handling

  • useHttp.sendRequest sets app.loginRequired = true when a request returns 403 with "Authentication credentials were not provided.".

Stores

user store (src/store/user.js)

State:

  • user: user detail object from user_detail
  • groups: group list
  • permissions: permission list
  • loading: request state for hydration

Actions:

  • hydrate(): loads user data from /account/me/
  • setFromResponse(payload): sets user, groups, permissions from the login/me response
  • clear(): resets identity data

Getters:

  • isAuthenticated: true when user.id exists
  • hasPermission(permission): checks permission string
  • hasRole(roleName): checks group name

Examples

js
import { computed, onMounted } from 'vue'
import { useUserStore } from '@/store/user'

const userStore = useUserStore()
const userData = computed(() => userStore.user)

const isAuthed = computed(() => userStore.isAuthenticated)
const canViewInvoices = computed(() => userStore.hasPermission('project.view_invoice'))
const isAdmin = computed(() => userStore.hasRole('Admin'))


onMounted(() => {
  userStore.hydrate()
})

app store (src/store/app.js)

State:

  • loginRequired: controls login overlay visibility

Router guard behavior

  • A global beforeEach checks for a sessionid cookie.
  • If missing, it marks loginRequired and clears user data.
  • Navigation is not blocked; the login overlay is used instead.

Notes

  • The login flow is session-cookie based and does not use tokens.