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.
| Property | Value |
|---|---|
| Algorithm | HS256 |
| Expiry | Configurable via JWT_EXPIRE_MINUTES (default: 60 minutes) |
| Secret | From JWT_SECRET_KEY env variable |
Security rules:
JWT_SECRET_KEYmust be a strong, randomly generated value. Minimum 32 bytes recommended.- The algorithm is hardcoded in the verification logic. The
nonealgorithm is not accepted. - The
expclaim is validated on every request. - Never hardcode a fallback secret in code.
Token storage:
- Web app: stored as an
HttpOnly,Secure,SameSite=Laxcookie. - 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
- Open
apps/api/.env. - Add the university email to
LAB_TECHNICIANS:LAB_TECHNICIANS=existing@ua.pt,new.tech@ua.pt - Rebuild and restart the API container:
docker compose -f infra/docker/docker-compose.yml up -d --build api - 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
- Remove the email from
LAB_TECHNICIANS. - Rebuild and restart the API container.
- On the user's next login, their role reverts to
studentorprofessor. - Snipe-IT access is revoked automatically (the auth_request gate will return 403).
Secrets management
| Secret | Location | Notes |
|---|---|---|
JWT_SECRET_KEY | apps/api/.env | Must be strong and unique per deployment |
SNIPEIT_API_TOKEN | apps/api/.env | Generated by bootstrap script; treat as a password |
DML_AUTH_KEY / DML_AUTH_SECRET | apps/api/.env | University SSO OAuth1 client credentials |
POSTGRES_PASSWORD | infra/db/.env.postgres | Database password |
MYSQL_PASSWORD / MYSQL_ROOT_PASSWORD | infra/snipeit/.env.snipeit | MariaDB passwords |
| TLS private key | infra/nginx/certs/selfsigned.key | Replace with real cert in production |
Rules:
- Never commit
.envfiles 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
backendDocker 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
.envfiles. - Enable HSTS in Nginx.
See Future Work.