Skip to content

Specification — Authentication and Access in Poolia

1. Objective

Implement a simple, REST-based authentication flow for Poolia users, allowing clients to register, authenticate, and obtain a bearer token that can be used to access protected endpoints.

The current implementation is intentionally lightweight and centered on:

  • user registration;
  • email/password login;
  • JWT bearer authentication;
  • role propagation inside the token;
  • route protection through a shared dependency.

This design keeps authentication compatible with the existing FastAPI + REST architecture without introducing session stores, refresh tokens, or external identity providers.

2. Functional Approach

Authentication is modeled as a token-based flow.

Core concepts

A user registers with:

  • name
  • lastName
  • email
  • password
  • role

A successful registration creates a user record and returns a bearer token.

A user logs in with:

  • email
  • password

A successful login returns a bearer token.

Protected routes use the token to resolve the current user through a shared dependency.

Current architectural choice

The backend does not implement:

  • refresh tokens;
  • token revocation;
  • session persistence in the backend;
  • OAuth providers;
  • multi-factor authentication.

The authentication scope is intentionally limited to stateless JWT access tokens.

3. Data Design

Authentication relies mainly on the existing users collection.

3.1. User fields relevant to authentication

Relevant user fields include:

  • email: unique login identifier.
  • passwordHash: stored password hash.
  • role: one of admin, owner, technician.
  • status: one of active, blocked, pending, deleted.
  • lastLoginAt: last successful login timestamp.
  • deletedAt: logical deletion timestamp.

3.2. Token payload

The JWT contains:

  • sub: user id.
  • role: user role.
  • exp: expiration timestamp.

This is enough for the backend to identify the authenticated user and preserve role context.

4. Security Logic

Password handling

Passwords are not stored in plain text.

The flow is:

  1. the raw password is SHA-256 prehashed;
  2. the result is hashed again with bcrypt through Passlib;
  3. login verification repeats the same transformation before comparison.

This preserves compatibility with the current implementation while avoiding direct bcrypt over the plain password.

Token generation

Access tokens are signed with:

  • algorithm: HS256
  • secret key: SECRET_KEY environment variable
  • fallback secret: "super-secret" if not configured

Token duration

The current access token expiration is:

  • 60 minutes

5. Access Validation Rules

Registration

Registration fails if another user already exists with the same email.

Login

Login fails if:

  • the user does not exist;
  • the user is logically deleted;
  • the user status is not active;
  • the user has no password set;
  • the password is invalid.

Protected routes

Protected routes resolve the current user by:

  1. extracting the bearer token through OAuth2PasswordBearer;
  2. decoding the JWT;
  3. reading the sub claim;
  4. loading the user from MongoDB;
  5. failing if the token or user is invalid.

6. REST Endpoints

6.1. Register

POST /auth/register

Request body

{
  "name": "Ada",
  "lastName": "Lovelace",
  "email": "ada@example.com",
  "password": "secret123",
  "role": "owner"
}

Behavior

  • checks whether the email is already registered;
  • hashes the password;
  • creates the user with status active;
  • generates an access token;
  • returns a bearer token response.

Response shape

{
  "access_token": "jwt-token",
  "token_type": "bearer"
}

6.2. Login

POST /auth/login

Request body

{
  "email": "ada@example.com",
  "password": "secret123"
}

Behavior

  • loads the user by email;
  • validates active status;
  • validates password;
  • updates lastLoginAt;
  • returns a bearer token response.

Response shape

{
  "access_token": "jwt-token",
  "token_type": "bearer"
}

6.3. Logout

POST /auth/logout

Behavior

The current implementation returns a success message only.

It does not invalidate a token server-side.

Response shape

{
  "message": "Logout successful"
}

7. Backend Logic Summary

Registration flow

  1. validate unique email;
  2. hash password;
  3. create User;
  4. issue JWT;
  5. return token.

Login flow

  1. load user by email;
  2. validate existence;
  3. validate deletion and status rules;
  4. validate password hash;
  5. update lastLoginAt;
  6. issue JWT;
  7. return token.

Protected-route flow

  1. parse bearer token;
  2. decode JWT;
  3. extract sub;
  4. load user by id;
  5. expose current_user to the route.

8. Frontend Integration Notes

  1. submit email/password to /auth/login;
  2. store the returned bearer token;
  3. include Authorization: Bearer <token> in protected requests;
  4. load the current user using /users/me after login.
  1. submit registration form to /auth/register;
  2. store the returned token immediately;
  3. navigate to the authenticated section.

Logout behavior

Because logout is stateless, frontend logout should:

  • discard the stored token;
  • clear local auth state;
  • redirect to the unauthenticated flow.

9. Current Scope

The current implementation covers:

  • registration;
  • email/password login;
  • bearer token generation;
  • current-user resolution through dependency injection.

It does not cover:

  • refresh tokens;
  • remember-me sessions;
  • password reset;
  • email verification;
  • token blacklist;
  • multi-device session tracking.

10. Future Recommendations

A future version could add:

  • refresh token support;
  • password recovery flow;
  • email confirmation;
  • stronger secret management without fallback defaults;
  • token revocation or session tracking;
  • cookie-based auth for web clients if needed.

11. Final Summary

Authentication in Poolia is currently defined as a simple JWT-based REST flow built around the User document, email/password credentials, and a shared bearer-token dependency. The implementation is intentionally minimal, consistent with the existing backend architecture, and sufficient for current owner, technician, and admin access patterns.