Skip to content
RoshanzenPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

Bizora AI - AI Business Platform

A production-quality AI-powered business platform inspired by Polsia, built with Flutter Web (frontend), Django REST Framework (backend), and PostgreSQL (database).

Phase 3 Complete - Authentication & User Management

What Was Built

  1. JWT Authentication System

    • Registration endpoint with email validation
    • Login endpoint with secure password verification
    • Token refresh endpoint with blacklisting
    • Logout endpoint that invalidates refresh tokens
    • Current user endpoint (GET /api/auth/me/)
    • Profile update endpoint (PATCH /api/auth/me/)
    • Password change endpoint (POST /api/auth/change-password/)
  2. Secure Token Management

    • Short-lived access tokens (15 minutes)
    • Long-lived refresh tokens (7 days)
    • Refresh token rotation on each use
    • Blacklisting after logout or rotation
    • Tokens stored securely in Flutter using shared_preferences
  3. Company Ownership Enforcement

    • POST /api/companies/ - owner automatically set to authenticated user
    • GET /api/companies/ - returns only the current user's companies
    • GET /api/companies/{id}/ - returns 404 if company doesn't belong to user
    • PATCH /api/companies/{id}/ - only owner can update
    • DELETE /api/companies/{id}/ - only owner can delete
    • owner field removed from client input entirely
  4. Flutter Authentication UI

    • Login screen with email/password form
    • Register screen with name/email/password form
    • Password visibility toggle
    • Form validation with user-friendly error messages
    • Loading states during authentication
    • Centralized auth state management with AuthProvider
    • Token storage with TokenStorage
  5. Protected API Flow

    • All company endpoints require authentication
    • Unauthenticated requests return 401
    • Access token sent automatically in Authorization: Bearer header
    • 401 responses trigger token refresh or logout

Files Created/Changed

Backend

  • backend/config/settings.py - Added token blacklist app, adjusted JWT settings
  • backend/accounts/serializers.py - Added RegisterSerializer, LoginSerializer, ChangePasswordSerializer
  • backend/accounts/views.py - Added register, login, logout, me, change-password views
  • backend/accounts/urls.py - Added auth endpoint URLs
  • backend/companies/serializers.py - Made owner read-only
  • backend/companies/views.py - Enforced ownership, removed AllowAny permission

Frontend

  • frontend/lib/models/user.dart - User model with JSON serialization
  • frontend/lib/storage/token_storage.dart - Secure token storage using shared_preferences
  • frontend/lib/services/auth_service.dart - Authentication service (register, login, logout, refresh, change password)
  • frontend/lib/services/api_service.dart - Updated to support optional accessToken parameter
  • frontend/lib/providers/auth_provider.dart - Centralized auth state management
  • frontend/lib/screens/auth/login_screen.dart - Login UI
  • frontend/lib/screens/auth/register_screen.dart - Registration UI
  • frontend/lib/main.dart - Updated with auth flow and ChangeNotifierProvider
  • frontend/lib/screens/company_test_screen.dart - Updated to use auth tokens
  • frontend/pubspec.yaml - Added provider and shared_preferences dependencies

Authentication Endpoints

POST /api/auth/register/       - Create account
POST /api/auth/login/          - Login and get tokens
POST /api/auth/logout/         - Invalidate refresh token
POST /api/auth/token/refresh/  - Get new access token
GET  /api/auth/me/             - Get current user
PATCH /api/auth/me/            - Update profile
POST /api/auth/change-password/ - Change password

How It Works

What authentication means: Authentication is the process of verifying who you are. When you log in with email and password, Django checks if those credentials are correct. If they are, Django gives you a special "key" (JWT token) that proves you're authenticated.

What JWT is: JWT (JSON Web Token) is a compact, secure way to transmit information between parties. In our case, it's a signed token that contains the user's ID and expiration time. The frontend stores this token and sends it with every API request.

What an access token is: An access token is a short-lived key (15 minutes) that proves you're authenticated. You send it in the Authorization: Bearer <token> header with every API request. Django verifies the token and knows who you are.

What a refresh token is: A refresh token is a long-lived key (7 days) that can be used to get a new access token when the old one expires. It's stored securely and only sent to the /api/auth/token/refresh/ endpoint.

How Flutter sends the token to Django: Every API request includes an Authorization: Bearer <access_token> header. The ApiService methods accept an optional accessToken parameter. The AuthProvider provides the current token.

How Django identifies the logged-in user: When a request comes in with a JWT token, Django's JWTAuthentication class decodes the token, extracts the user ID, and sets request.user to that user. All subsequent code can access the authenticated user via request.user.

How Django protects company data: The CompanyViewSet now:

  1. Requires authentication (IsAuthenticated permission)
  2. Filters the queryset to only return companies where owner = request.user
  3. Automatically sets owner = request.user when creating a company
  4. Returns 404 if a user tries to access a company they don't own

Why users cannot simply send another user's ID: The backend ignores any owner field sent by the client. Instead, it uses request.user (extracted from the JWT token) as the owner. Even if a malicious user sends "owner": 123, Django overwrites it with the authenticated user's ID.

How password hashing works: When a user registers or changes their password, Django doesn't store the plain-text password. Instead, it uses a one-way hashing algorithm (PBKDF2 with SHA256). The password is transformed into a hash that cannot be reversed. When the user logs in, Django hashes the entered password and compares it to the stored hash.

What happens when a token expires:

  1. The access token expires after 15 minutes
  2. Django returns a 401 Unauthorized response
  3. Flutter attempts to refresh using the refresh token
  4. If refresh succeeds, the new access token is stored and the original request is retried
  5. If refresh fails (token expired/blacklisted), Flutter clears auth state and shows the login screen

How logout works with JWT: Since JWT is stateless, we can't "delete" the access token. Instead, we:

  1. Blacklist the refresh token in the database
  2. Clear tokens from Flutter's local storage
  3. The access token will naturally expire within 15 minutes
  4. The refresh token is permanently invalid

How to Run

Step 1: Start PostgreSQL

Start-Service postgresql-x64-16

Step 2: Start Django Backend

$env:PATH = "C:\Users\acer\AppData\Local\Programs\Python\Python312;C:\Users\acer\AppData\Local\Programs\Python\Python312\Scripts;" + $env:PATH
cd C:\Users\acer\Downloads\bizorai\backend
python manage.py runserver 0.0.0.0:8000

Step 3: Start Flutter Frontend

$env:PATH = "C:\Users\acer\AppData\Local\Programs\Python\Python312;C:\Users\acer\AppData\Local\Programs\Python\Python312\Scripts;" + $env:PATH
cd C:\Users\acer\Downloads\bizorai\frontend
flutter run -d chrome --web-port 8080

Visit http://localhost:8080 in Chrome.

Testing the Authentication Flow

1. Register a new account

$body = @{
    name = "Test User"
    email = "testuser@example.com"
    password = "SecurePassword123"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:8000/api/auth/register/" -Method Post -ContentType "application/json" -Body $body

2. Login

$body = @{
    email = "testuser@example.com"
    password = "SecurePassword123"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:8000/api/auth/login/" -Method Post -ContentType "application/json" -Body $body

3. Create a company (using the access token)

$token = "YOUR_ACCESS_TOKEN"
$headers = @{Authorization = "Bearer $token"; "Content-Type" = "application/json"}

$body = @{
    name = "My Bookstore"
    description = "An online bookstore"
    industry = "Education"
    target_customer = "Students"
    business_model = "E-commerce"
    goals = "Provide affordable books"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:8000/api/companies/" -Method Post -Headers $headers -Body $body

4. List companies (only your own)

$headers = @{Authorization = "Bearer $token"}
Invoke-RestMethod -Uri "http://localhost:8000/api/companies/" -Method Get -Headers $headers

5. Try to access another user's company (should return 404)

$headers = @{Authorization = "Bearer $token"}
Invoke-RestMethod -Uri "http://localhost:8000/api/companies/ANOTHER_USERS_COMPANY_ID/" -Method Get -Headers $headers

6. Change password

$body = @{
    current_password = "SecurePassword123"
    new_password = "NewPassword456"
} | ConvertTo-Json

Invoke-RestMethod -Uri "http://localhost:8000/api/auth/change-password/" -Method Post -Headers $headers -Body $body

7. Logout

$body = @{refresh = "YOUR_REFRESH_TOKEN"} | ConvertTo-Json
Invoke-RestMethod -Uri "http://localhost:8000/api/auth/logout/" -Method Post -Headers $headers -Body $body

Common Errors and Fixes

  1. "User with this email address already exists."

    • The email is already registered. Use a different email or login instead.
  2. "Invalid email or password."

    • Check that the email and password are correct. This message is generic for security.
  3. "Token is invalid" or 401 Unauthorized

    • The access token has expired. The app should automatically refresh it.
    • If refresh also fails, you need to login again.
  4. "No Company matches the given query."

    • The company either doesn't exist or doesn't belong to the authenticated user.
  5. CORS errors in Flutter

    • Make sure the Flutter dev server port (8080) is in Django's CORS_ALLOWED_ORIGINS.

Security Notes

  • Passwords are hashed using Django's PBKDF2 algorithm - never stored in plain text
  • JWT tokens are short-lived (15 min access, 7 day refresh)
  • Refresh tokens are rotated and blacklisted on logout
  • Owner field is never trusted from the client - always uses request.user
  • CORS is configured for specific local origins only
  • No sensitive data is exposed in API responses (no passwords, no hashes)
  • Generic error messages are used for login failures to prevent user enumeration

Beginner Explanations

  1. What authentication means: Verifying a user's identity (who they claim to be) using credentials like email and password.

  2. What JWT is: A secure, compact token that contains user information and is signed so it can't be tampered with.

  3. What an access token is: A short-lived key that proves you're logged in and allows you to access protected APIs.

  4. What a refresh token is: A long-lived key used to get new access tokens without requiring the user to log in again.

  5. How Flutter sends the token to Django: By including Authorization: Bearer <token> in the HTTP request headers.

  6. How Django identifies the logged-in user: By decoding the JWT token and extracting the user ID, then setting request.user.

  7. How Django protects company data: By filtering the queryset to only include companies owned by the authenticated user.

  8. Why users cannot simply send another user's ID: Because the backend ignores the owner field from the client and uses request.user instead.

  9. How password hashing works: Django transforms passwords into irreversible hashes using PBKDF2, so even if the database is compromised, passwords can't be recovered.

  10. What happens when a token expires: Django returns 401, Flutter tries to refresh with the refresh token, or redirects to login if refresh fails.

  11. How logout works with JWT: The refresh token is blacklisted in the database, and local tokens are cleared from the device.

Phase 3 Checklist

  • Registration endpoint with validation
  • Login endpoint with JWT tokens
  • Token refresh endpoint
  • Logout with token blacklisting
  • Current user endpoint
  • Profile update endpoint
  • Password change endpoint
  • Company ownership enforcement
  • Owner field removed from client input
  • Flutter auth screens (login/register)
  • Flutter token storage
  • Flutter auth state management
  • End-to-end testing verified

Phase 3 Status: COMPLETE

  • JWT authentication fully functional
  • Company ownership enforced server-side
  • Flutter auth flow working
  • Data persists in PostgreSQL

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages