Skip to main content

Security

Authentication (SSO)

All user authentication is delegated to the University of Aveiro SSO (identity.ua.pt). The system does not manage passwords.

  • The SSO flow uses OAuth 1.0.
  • No user credentials are stored in the MakerLab database.
  • The SSO callback URL must match exactly what is registered with the identity provider.

JWT tokens

After SSO authentication, the API issues a JWT signed with JWT_SECRET_KEY.

PropertyValue
AlgorithmHS256
ExpiryConfigurable via JWT_EXPIRE_MINUTES (default: 60 minutes)
SecretFrom JWT_SECRET_KEY env variable

Security rules:

  • JWT_SECRET_KEY must be a strong, randomly generated value. Minimum 32 bytes recommended.
  • The algorithm is hardcoded in the verification logic. The none algorithm is not accepted.
  • The exp claim is validated on every request.
  • Never hardcode a fallback secret in code.

Token storage:

  • Web app: stored as an HttpOnly, Secure, SameSite=Lax cookie.
  • Mobile app: stored in Expo SecureStore (Android Keystore / iOS Keychain).

Role-based access control

Three roles exist: student, professor, lab_technician. Role is assigned at login and re-evaluated on every SSO authentication.

  • Role changes take effect on next login after restarting the API.
  • Technician-only endpoints check current_user.role == "lab_technician" in route handlers.
  • The Nginx auth_request gate enforces technician-only access to Snipe-IT at the proxy level.

Managing lab technicians

Technicians are identified by their university email in the LAB_TECHNICIANS environment variable.

Adding a technician

  1. Open apps/api/.env.
  2. Add the university email to LAB_TECHNICIANS:
    LAB_TECHNICIANS=existing@ua.pt,new.tech@ua.pt
  3. Rebuild and restart the API container:
    docker compose -f infra/docker/docker-compose.yml up -d --build api
  4. The next time the user logs in via SSO, their role is set to lab_technician.
    • They are automatically provisioned as a Snipe-IT admin user.
    • Snipe-IT access is granted immediately upon their next login.

Removing a technician

  1. Remove the email from LAB_TECHNICIANS.
  2. Rebuild and restart the API container.
  3. On the user's next login, their role reverts to student or professor.
  4. Snipe-IT access is revoked automatically (the auth_request gate will return 403).

Secrets management

SecretLocationNotes
JWT_SECRET_KEYapps/api/.envMust be strong and unique per deployment
SNIPEIT_API_TOKENapps/api/.envGenerated by bootstrap script; treat as a password
DML_AUTH_KEY / DML_AUTH_SECRETapps/api/.envUniversity SSO OAuth1 client credentials
POSTGRES_PASSWORDinfra/db/.env.postgresDatabase password
MYSQL_PASSWORD / MYSQL_ROOT_PASSWORDinfra/snipeit/.env.snipeitMariaDB passwords
TLS private keyinfra/nginx/certs/selfsigned.keyReplace with real cert in production

Rules:

  • Never commit .env files to version control (all are in .gitignore).
  • In production, use a secrets management system (e.g., HashiCorp Vault, AWS Secrets Manager) rather than files on disk.
  • Rotate secrets regularly, especially after any suspected compromise.

Snipe-IT API token

The Snipe-IT API token is a long-lived personal access token generated from the Snipe-IT admin interface. It grants full API access to Snipe-IT.

  • Treat this token with the same security level as a password.
  • Store it only in apps/api/.env, not in code or logs.
  • Rotate it if compromised by generating a new token in Snipe-IT and updating apps/api/.env.

Network security

  • All external traffic terminates at Nginx on ports 80 and 443.
  • Port 80 is redirected to 443 (HTTPS only).
  • Internal services communicate on the private backend Docker network.
  • In production, close direct access to ports 8000 (API), 5432 (PostgreSQL), and 8080 (Snipe-IT) using firewall rules.

CORS

CORS is configured in the FastAPI app to allow requests only from the configured FRONTEND_URL and known development origins:

origins = [
"http://localhost:8081", # Expo mobile dev
"http://localhost:3000", # Next.js local dev
settings.FRONTEND_URL, # Production frontend URL
]

Wildcard origins are not used.


Future security improvements

  • Use a dedicated least-privilege database user for the application (separate from the PostgreSQL superuser).
  • Add rate limiting to authentication endpoints.
  • Add monitoring and alerting for suspicious login activity.
  • Use a production-grade secrets manager instead of .env files.
  • Enable HSTS in Nginx.

See Future Work.