Typorithm · medium

Authentication and a session lifecycle

pythondjangoindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Authentication and a session lifecycle

0%

Concept and contract

Use the framework’s password and session mechanisms while distinguishing a login check from a forced test identity.

Authentication establishes who a requester is, while a session lets later requests refer to that authenticated identity. Django supplies password hashing, authentication backends and session integration; a view should not compare a stored password with raw submitted text.

This lesson uses a fictional account in the in-memory fixture. The known course password is test data, not a credential for any real user or deployed service.

Mechanism and worked example

The helper creates a user through the normal password-hashing API, calls the real test-client login path and requests a login-protected view.

The helper creates a user through the normal password-hashing API, calls the real test-client login path and requests a login-protected view. Correct credentials produce an authenticated session and success.

Incorrect credentials leave the client unauthenticated, so login_required returns its configured login redirect. The result records both whether authentication was accepted and what the later request actually observed, rather than inferring one from the other.

Complete worked example

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.test import Client
from django.urls import path

@login_required
def private(request):
    return JsonResponse({"user": request.user.username})

urlpatterns = [path("private/", private)]

def authenticate_request(password):
    User = get_user_model()
    User.objects.all().delete()
    user = User.objects.create_user(username="owner", password="course-password")
    client = Client()
    accepted = client.login(username="owner", password=password)
    response = client.get("/private/")
    return {"accepted": accepted, "status": response.status_code}
Reasoning
The helper creates a user through the normal password-hashing API, calls the real test-client login path and requests a login-protected view. Correct credentials produce an authenticated session and success.

Counterexamples and common mistakes

The counterexample uses force_login and reports success regardless of the supplied password.

The counterexample uses force_login and reports success regardless of the supplied password. force_login is useful for tests focused on later authorization behavior, but it does not test password authentication.

Do not treat a successful forced-identity test as proof that a real login works. Keep credential validation, session creation, logout and object-level authorization as separate contracts so a bypass in one cannot hide behind coverage of another.

Counterexample: a runnable framework mistake

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.test import Client
from django.urls import path

@login_required
def private(request):
    return JsonResponse({"user": request.user.username})

urlpatterns = [path("private/", private)]

def authenticate_request(password):
    User = get_user_model()
    User.objects.all().delete()
    user = User.objects.create_user(username="owner", password="course-password")
    client = Client()
    client.force_login(user)
    accepted = True
    response = client.get("/private/")
    return {"accepted": accepted, "status": response.status_code}
Reasoning
The counterexample uses force_login and reports success regardless of the supplied password. force_login is useful for tests focused on later authorization behavior, but it does not test password authentication.

Independent practice: one bounded framework change

After recording the first protected response, log out and request the same view again.

After recording the first protected response, log out and request the same view again. Add the post-logout status to the result without changing the recorded login outcome.

Begin with a correct password and then repeat the wrong-password case. This verifies a small session lifecycle rather than introducing password reset, third-party identity providers or a custom authentication backend.

Step 1: Record access again after explicit logout. Step 2: Preserve the original login outcome and first response status.

Practice starter: solve before reading the solution

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.test import Client
from django.urls import path

@login_required
def private(request):
    return JsonResponse({"user": request.user.username})

urlpatterns = [path("private/", private)]

def authenticate_request(password):
    # Remove this placeholder, then adapt the retained baseline:
    # Record access again after explicit logout.
    raise NotImplementedError
    User = get_user_model()
    User.objects.all().delete()
    user = User.objects.create_user(username="owner", password="course-password")
    client = Client()
    accepted = client.login(username="owner", password=password)
    response = client.get("/private/")
    return {"accepted": accepted, "status": response.status_code}
Reasoning
Record access again after explicit logout. Preserve the original login outcome and first response status.
  • Hint 1: Use client.logout before the second protected request.
  • Hint 2: Do not replace real authentication with force_login in this test.

Solution, tests and trade-offs

The cases check a correct password, a wrong password and an empty supplied password using the actual backend.

The cases check a correct password, a wrong password and an empty supplied password using the actual backend. Practice confirms that logout removes access for the subsequent request even after a successful login.

Tests do not inspect or compare a randomized password hash string. They also do not weaken password hashing to make execution faster or send any authentication request outside the local framework test client.

Practice solution and acceptance checks

python

from bootstrap_lab import django_setup
django_setup(__name__)

from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.test import Client
from django.urls import path

@login_required
def private(request):
    return JsonResponse({"user": request.user.username})

urlpatterns = [path("private/", private)]

def authenticate_request(password):
    User = get_user_model()
    User.objects.all().delete()
    user = User.objects.create_user(username="owner", password="course-password")
    client = Client()
    accepted = client.login(username="owner", password=password)
    response = client.get("/private/")
    client.logout()
    after = client.get("/private/")
    return {"accepted": accepted, "status": response.status_code, "after_logout": after.status_code}
Reasoning
The cases check a correct password, a wrong password and an empty supplied password using the actual backend. Practice confirms that logout removes access for the subsequent request even after a successful login.

Interview reasoning and next step

Explain why authentication success does not grant access to every object in the application.

Explain why authentication success does not grant access to every object in the application. A production session additionally needs secure transport, cookie settings, CSRF protection and an intentional account-recovery policy.

A redirect is appropriate for some browser views, while an API may use a different unauthenticated response contract. The ownership lesson next tests a valid authenticated user attempting to access somebody else’s record.

Optional stretch — after the core task works: Design a password-reset test using only the framework’s owned local mail fixture.

Computer practice: https://applydjinn.com/typorithm/python-frameworks-lab-20261105.zip. Install the pinned dependencies in an isolated environment, run verify.py --track django, then edit the retained exercise baseline and check it with --practice dj-auth. The lab uses owned in-memory databases, local framework clients and tiny CPU tensors. It never reads the working ApplyDjinn database, contacts production feeds or downloads models.

Use the framework’s password and session mechanisms while distinguishing a login check from a forced test identity.