Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A complete Django authentication system with user registration, login, logout, and secure password reset functionality using session-based authentication and email verification.

Notifications You must be signed in to change notification settings

LinusBwana/Session-Based-Authentication

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

9 Commits

Repository files navigation

Django Session-Based Authentication System

A complete Django authentication system with user registration, login, logout, and password reset functionality using session-based authentication.

Features

  • User Registration with validation
  • User Login/Logout
  • Password Reset via Email
  • Session-based authentication
  • Form validation and error handling
  • Secure password reset with expiration links

Prerequisites

  • Python 3.x
  • Django 4.x or higher
  • Email backend configuration for password reset functionality

Installation & Setup

  1. Clone the repository

    git clone <your-repository-url>
    cd <project-directory>
  2. Install dependencies

    pip install django
  3. Add the PasswordReset model to your models.py

    from django.db import models
    from django.contrib.auth.models import User
    import uuid
    class PasswordReset(models.Model):
     user = models.ForeignKey(User, on_delete=models.CASCADE)
     reset_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
     created_when = models.DateTimeField(auto_now_add=True)
     def __str__(self):
     return f"Password reset for {self.user.username} at {self.created_when}"
  4. Configure email settings in settings.py

    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = "smtp.gmail.com"
    EMAIL_PORT = 465
    EMAIL_USE_SSL = True
    EMAIL_HOST_USER = "email@gmail.com"
    EMAIL_HOST_PASSWORD = "google app password"
  5. Create and run migrations

    python manage.py makemigrations
    python manage.py migrate
  6. Start the development server

    python manage.py runserver

File Structure

your_app/
├── models.py # PasswordReset model
├── views.py # Authentication views
├── urls.py # URL patterns
└── templates/
 ├── index.html # Home page
 ├── register.html # Registration form
 ├── login.html # Login form
 ├── forgot_password.html # Forgot password form
 ├── password_reset_sent.html # Reset email sent confirmation
 └── reset_password.html # Password reset form

Models

PasswordReset Model

class PasswordReset(models.Model):
 user = models.ForeignKey(User, on_delete=models.CASCADE)
 reset_id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
 created_when = models.DateTimeField(auto_now_add=True)
  • Links to Django's built-in User model
  • Uses UUID for secure reset tokens
  • Tracks creation time for expiration validation

URL Patterns

urlpatterns = [
 path('', views.home, name='home'),
 path('register/', views.registerView, name='register'),
 path('login/', views.loginView, name='login'),
 path('logout/', views.logoutView, name='logout'),
 path('forgot-password/', views.forgotPassword, name='forgot-password'),
 path('password-reset-sent/<str:reset_id>/', views.passwordResetSent, name='password-reset-sent'),
 path('reset-password/<str:reset_id>/', views.resetPassword, name='reset-password'),
]

Views Code Overview

Home View (Protected Route)

@login_required
def home(request):
 return render(request, 'index.html')

This view requires user authentication and serves as the main dashboard after login.

1. User Registration (/register/)

Process:

  1. User fills out registration form with:

    • First name
    • Last name
    • Username
    • Email
    • Password
    • Confirm password
  2. Server-side validation:

    • Checks if username already exists
    • Checks if email already exists
    • Validates password length (minimum 8 characters)
    • Confirms password match
  3. On success:

    • Creates new user account
    • Redirects to login page with success message
  4. On error:

    • Displays appropriate error messages
    • Redirects back to registration form

Code Implementation:

def registerView(request):
 if request.method == "POST":
 first_name = request.POST.get('first_name')
 last_name = request.POST.get('last_name')
 username = request.POST.get('username')
 email = request.POST.get('email')
 password = request.POST.get('password')
 confirm_password = request.POST.get('confirm_password')
 user_data_has_error = False
 # checking whether email and username are not being used
 if User.objects.filter(username=username).exists():
 user_data_has_error = True
 messages.error(request, 'Username already exists')
 if User.objects.filter(email=email).exists():
 user_data_has_error = True
 messages.error(request, 'Email already exists')
 if len(password) < 8:
 user_data_has_error = True
 messages.error(request, 'Password must be at least 8 characters')
 if (password != confirm_password):
 user_data_has_error = True
 messages.error(request, 'Passwords do not match')
 if not user_data_has_error:
 new_user = User.objects.create_user(
 first_name = first_name,
 last_name = last_name,
 email = email,
 username = username,
 password = password
 )
 messages.success(request, 'Account created. Login now')
 return redirect('login')
 return redirect('register')
 return render(request, 'register.html')

2. User Login (/login/)

Process:

  1. User enters username and password
  2. Django authenticates credentials using authenticate()
  3. On success:
    • User session is created using login()
    • Redirects to home page
  4. On failure:
    • Displays "Invalid username or password" error
    • Redirects back to login form

Code Implementation:

def loginView(request):
 if request.method == "POST":
 # getting user inputs from frontend
 username = request.POST.get('username')
 password = request.POST.get('password')
 # authenticate credentials
 user = authenticate(request, username=username, password=password)
 if user is not None:
 login(request, user)
 return redirect('home')
 messages.error(request, 'Invalid username or password')
 return redirect('login')
 return render(request, 'login.html')

3. User Logout (/logout/)

Process:

  1. Calls Django's logout() function
  2. Destroys user session
  3. Redirects to login page

Code Implementation:

def logoutView(request):
 logout(request)
 return redirect('login')

4. Forgot Password (/forgot-password/)

Process:

  1. User enters email address
  2. System checks if email exists in database
  3. If email exists:
    • Creates new PasswordReset instance with unique UUID
    • Generates password reset URL
    • Sends email with reset link
    • Redirects to confirmation page
  4. If email doesn't exist:
    • Shows error message
    • Redirects back to forgot password form

Code Implementation:

def forgotPassword(request):
 if request.method == "POST":
 email = request.POST.get('email')
 # verify if email exists
 try:
 user = User.objects.get(email=email)
 # create a new reset id
 new_password_reset = PasswordReset(user=user)
 new_password_reset.save()
 # creating password reset url;
 password_reset_url = reverse('reset-password', kwargs={'reset_id': new_password_reset.reset_id})
 full_password_reset_url = f'{request.scheme}://{request.get_host()}{password_reset_url}'
 # email content
 email_body = f'Reset your password using the link below:\n\n\n{full_password_reset_url}'
 
 email_message = EmailMessage(
 'Reset your password', # email subject
 email_body,
 settings.EMAIL_HOST_USER, # email sender
 [email] # email receiver 
 )
 email_message.fail_silently = True
 email_message.send()
 return redirect('password-reset-sent', reset_id=new_password_reset.reset_id)
 except User.DoesNotExist:
 messages.error(request, f"No user with email '{email}' found")
 return redirect('forgot-password')
 return render(request, 'forgot_password.html')

5. Password Reset Confirmation (/password-reset-sent/<reset_id>/)

Process:

  1. Validates that reset ID exists in database
  2. If valid: Shows confirmation page
  3. If invalid: Redirects to forgot password with error

Code Implementation:

def passwordResetSent(request, reset_id):
 if PasswordReset.objects.filter(reset_id=reset_id).exists():
 return render(request, 'password_reset_sent.html')
 else:
 # redirect to forgot password page if code does not exist
 messages.error(request, 'Invalid reset id')
 return redirect('forgot-password')

6. Password Reset (/reset-password/<reset_id>/)

Process:

  1. Validates reset ID exists
  2. User enters new password and confirmation
  3. Validation checks:
    • Passwords match
    • Password minimum length (8 characters)
    • Reset link hasn't expired (10-minute window)
  4. On success:
    • Updates user password using set_password()
    • Deletes used reset token
    • Redirects to login with success message
  5. On error:
    • Shows appropriate error messages
    • For expired links: deletes token and redirects to forgot password

Code Implementation:

def resetPassword(request, reset_id):
 try:
 password_reset_id = PasswordReset.objects.get(reset_id=reset_id)
 if request.method == 'POST':
 password = request.POST.get('password')
 confirm_password = request.POST.get('confirm_password')
 passwords_have_error = False
 if password != confirm_password:
 passwords_have_error = True
 messages.error(request, 'Passwords do not match')
 if len(password) < 8:
 passwords_have_error = True
 messages.error(request, 'Password must be at least 8 characters long')
 # check to make sure link has not expired
 expiration_time = password_reset_id.created_when + timezone.timedelta(minutes=10)
 if timezone.now() > expiration_time:
 passwords_have_error = True
 messages.error(request, 'Reset link has expired')
 # delete reset id since it has expired
 password_reset_id.delete()
 # reset password
 if not passwords_have_error:
 user = password_reset_id.user
 user.set_password(password)
 user.save()
 
 # delete reset id after use
 password_reset_id.delete()
 # redirect to login
 messages.success(request, 'Password reset. Proceed to login')
 return redirect('login')
 else:
 # redirect back to password reset page and display errors
 return redirect('reset-password', reset_id=reset_id)
 
 except PasswordReset.DoesNotExist:
 # redirect to forgot password page if code does not exist
 messages.error(request, 'Invalid reset id')
 return redirect('forgot-password')
 return render(request, 'reset_password.html')

Security Features

Password Reset Security

  • Unique UUID tokens: Each reset request generates a unique, non-guessable token
  • Time-based expiration: Reset links expire after 10 minutes
  • One-time use: Tokens are automatically deleted after successful password reset or when expired
  • Email validation: Only registered email addresses can request resets

Form Validation

  • Username uniqueness: Prevents duplicate usernames
  • Email uniqueness: Prevents duplicate email addresses
  • Password strength: Minimum 8-character requirement
  • Password confirmation: Ensures passwords match

Session Security

  • Uses Django's built-in session framework
  • Login required decorator protects authenticated routes
  • Proper logout destroys sessions

Template Requirements

Your templates should include the following forms:

Registration Form (register.html)

<form method="POST">
 {% csrf_token %}
 <input type="text" name="first_name" required>
 <input type="text" name="last_name" required>
 <input type="text" name="username" required>
 <input type="email" name="email" required>
 <input type="password" name="password" required>
 <input type="password" name="confirm_password" required>
 <button type="submit">Register</button>
</form>

Login Form (login.html)

<form method="POST">
 {% csrf_token %}
 <input type="text" name="username" required>
 <input type="password" name="password" required>
 <button type="submit">Login</button>
</form>

Forgot Password Form (forgot_password.html)

<form method="POST">
 {% csrf_token %}
 <input type="email" name="email" required>
 <button type="submit">Send Reset Link</button>
</form>

Reset Password Form (reset_password.html)

<form method="POST">
 {% csrf_token %}
 <input type="password" name="password" required>
 <input type="password" name="confirm_password" required>
 <button type="submit">Reset Password</button>
</form>

Error Handling

The system includes comprehensive error handling:

  • Form validation errors are displayed using Django messages framework
  • Invalid reset tokens redirect to appropriate error pages
  • Expired reset links are automatically cleaned up
  • User-friendly error messages for all failure scenarios

Usage Examples

Protecting Views

from django.contrib.auth.decorators import login_required
@login_required
def protected_view(request):
 return render(request, 'protected.html')

Displaying Messages in Templates

{% if messages %}
 {% for message in messages %}
 <div class="alert alert-{{ message.tags }}">{{ message }}</div>
 {% endfor %}
{% endif %}

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Support

If you encounter any issues or have questions, please open an issue on GitHub.

About

A complete Django authentication system with user registration, login, logout, and secure password reset functionality using session-based authentication and email verification.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

AltStyle によって変換されたページ (->オリジナル) /