Typorithm · medium

Token parsing must lead to verified identity and revocation

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

Step 1 of 4 · intro card

Token parsing must lead to verified identity and revocation

0%

Concept and contract

Exercise DRF token authentication against owned users and the patched proxy deletion path.

Authentication verifies the credential presented by a request and establishes request.user and request.auth. A header parser alone is not a complete identity system. DRF TokenAuthentication checks a token record and its associated active user before a protected view can use that principal.

The lab creates a clearly synthetic local token for an owned alice user. The endpoint requires IsAuthenticated and returns only the resolved username. No real token, login account or external provider is contacted. These fixed fixture credentials must never be used as production authentication data.

Mechanism and worked example

The Authorization header uses the Token scheme.

The Authorization header uses the Token scheme. A missing or unknown token produces an authentication failure under the declared class order. The test also deletes the token through TokenProxy and verifies that the old credential no longer grants access.

Current DRF security patches corrected TokenProxy deletion behavior. The fixture exercises the actual database effect instead of assuming that invoking delete always revokes access. Identity resolution and the token record state remain observable through real DRF dispatch.

Complete worked example

python

from drf_lab import setup
setup()

from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token, TokenProxy
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
from drf_lab import reset_fixture

class Profile(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    def get(self, request):
        return Response({"user": request.user.username})

def inspect_example(payload):
    alice, _, _ = reset_fixture()
    token = Token.objects.create(user=alice, key="owned-fixture-token-not-a-real-credential")
    if payload.get("revoked"):
        TokenProxy.objects.get(key=token.key).delete()
    headers = {} if not payload.get("token") else {"HTTP_AUTHORIZATION": "Token " + payload["token"]}
    response = Profile.as_view()(APIRequestFactory().get("/profile/", **headers))
    body = {"error": response.data["detail"].code} if response.status_code >= 400 else dict(response.data)
    return {"status": response.status_code, "body": body}
Reasoning
The Authorization header uses the Token scheme. A missing or unknown token produces an authentication failure under the declared class order. The test also deletes the token through TokenProxy and verifies that the old credential no longer grants access. Current DRF security patches corrected TokenProxy deletion behavior. The fixture exercises the actual database effect instead of assuming that invoking delete always revokes access. Identity resolution and the token record state remain observable through real DRF dispatch.

Focused decision: context is in the complete example

python

class Profile(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    def get(self, request):
        return Response({"user": request.user.username})

TokenProxy.objects.get(key=token.key).delete()
Focused decision
Reconstruct this focused decision after the warm-up. The complete imports, model or application, and test client remain in the worked example. Typing records practice; only the downloadable computer lab executes Python.

Counterexamples and common mistakes

The counterexample leaves the token in storage when the revocation case is requested.

The counterexample leaves the token in storage when the revocation case is requested. The same credential then continues to authenticate. A response saying revoked would not be enough; a later protected request must fail with the old credential.

Built-in token authentication is a simple mechanism without an automatic expiry policy. A deployed product may need rotation, per-device tokens, expiry or an external identity provider. TLS, secure storage and permission checks remain necessary, and logging raw authorization values would create a separate exposure.

Controlled mistake: observe the actual wrong behavior

python

from drf_lab import setup
setup()

from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token, TokenProxy
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
from drf_lab import reset_fixture

class Profile(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    def get(self, request):
        return Response({"user": request.user.username})

def inspect_example(payload):
    alice, _, _ = reset_fixture()
    token = Token.objects.create(user=alice, key="owned-fixture-token-not-a-real-credential")
    if payload.get("revoked"):
        pass  # Wrong: the stored token is not revoked.
    headers = {} if not payload.get("token") else {"HTTP_AUTHORIZATION": "Token " + payload["token"]}
    response = Profile.as_view()(APIRequestFactory().get("/profile/", **headers))
    body = {"error": response.data["detail"].code} if response.status_code >= 400 else dict(response.data)
    return {"status": response.status_code, "body": body}
Reasoning
The counterexample leaves the token in storage when the revocation case is requested. The same credential then continues to authenticate. A response saying revoked would not be enough; a later protected request must fail with the old credential. Built-in token authentication is a simple mechanism without an automatic expiry policy. A deployed product may need rotation, per-device tokens, expiry or an external identity provider. TLS, secure storage and permission checks remain necessary, and logging raw authorization values would create a separate exposure.

Independent practice

Add authenticated=true to the successful public response, derived from request.user.is_authenticated.

Add authenticated=true to the successful public response, derived from request.user.is_authenticated. Preserve missing, unknown and revoked token failures. This is a small response expansion after verified identity, not permission to echo the credential.

Test a valid token, a revoked token and an absent token. The first should expose the new boolean and username only. Do not set the boolean from whether a header string exists: an arbitrary header is not a verified principal.

Step 1: Expose verified authenticated state without exposing the token or weakening revocation. Step 2: Retain the working imports and application structure. Change the stated policy, run the supplied practice cases, then explain the newly accepted or rejected boundary.

Practice starter: solve before reading the solution

python

from drf_lab import setup
setup()

from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token, TokenProxy
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
from drf_lab import reset_fixture

class Profile(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    def get(self, request):
        return Response({"user": request.user.username})

def inspect_example(payload):
    alice, _, _ = reset_fixture()
    token = Token.objects.create(user=alice, key="owned-fixture-token-not-a-real-credential")
    if payload.get("revoked"):
        TokenProxy.objects.get(key=token.key).delete()
    headers = {} if not payload.get("token") else {"HTTP_AUTHORIZATION": "Token " + payload["token"]}
    response = Profile.as_view()(APIRequestFactory().get("/profile/", **headers))
    body = {"error": response.data["detail"].code} if response.status_code >= 400 else dict(response.data)
    return {"status": response.status_code, "body": body}

# Independent task: Expose verified authenticated state without exposing the token or weakening revocation.
Reasoning
Expose verified authenticated state without exposing the token or weakening revocation.
  • Hint 1: Find the one field or branch that owns this policy.
  • Hint 2: Compare the first changed acceptance case with the retained baseline.

Solution, tests and trade-offs

The solution reads the authenticated property from the resolved user.

The solution reads the authenticated property from the resolved user. The token value remains absent from public output, and the revocation request still deletes the stored token before the protected read. The negative cases retain their failure statuses.

Authorization still decides which objects and operations this authenticated user may access. A successful identity check must not imply that every role in the database belongs to the caller. Keep credential verification and object selection as independently tested boundaries.

Practice solution and acceptance checks

python

from drf_lab import setup
setup()

from rest_framework.authentication import TokenAuthentication
from rest_framework.authtoken.models import Token, TokenProxy
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
from drf_lab import reset_fixture

class Profile(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]
    def get(self, request):
        return Response({"user": request.user.username, "authenticated": request.user.is_authenticated})

def inspect_example(payload):
    alice, _, _ = reset_fixture()
    token = Token.objects.create(user=alice, key="owned-fixture-token-not-a-real-credential")
    if payload.get("revoked"):
        TokenProxy.objects.get(key=token.key).delete()
    headers = {} if not payload.get("token") else {"HTTP_AUTHORIZATION": "Token " + payload["token"]}
    response = Profile.as_view()(APIRequestFactory().get("/profile/", **headers))
    body = {"error": response.data["detail"].code} if response.status_code >= 400 else dict(response.data)
    return {"status": response.status_code, "body": body}
Reasoning
The solution reads the authenticated property from the resolved user. The token value remains absent from public output, and the revocation request still deletes the stored token before the protected read. The negative cases retain their failure statuses. Authorization still decides which objects and operations this authenticated user may access. A successful identity check must not imply that every role in the database belongs to the caller. Keep credential verification and object selection as independently tested boundaries.

Interview reasoning and next step

Explain how a test of the next request catches failed revocation more reliably than a success message from a deletion endpoint.

Explain how a test of the next request catches failed revocation more reliably than a success message from a deletion endpoint. Then distinguish a parsed header, a token lookup and a verified user.

The next topic scopes collections and object reads. Reuse the authenticated principal at that boundary, while remembering that a test helper which forces authentication deliberately bypasses the credential verification just demonstrated.

Optional stretch — after the core task works: Add one independently reasoned boundary case and explain its expected value before running it.

Computer practice: https://applydjinn.com/typorithm/drf-lab-20261105.zip. Install pinned dependencies in an isolated Python environment. Run verify.py, then change the working exercise baseline and run --practice drf-authentication. The real DRF clients, serializers, schemas and SQLite transactions use owned fixtures only. No production database, feed, account or paid service is used. This lab executes Python; the PC typing trainer and native reading progress do not execute it.

Exercise DRF token authentication against owned users and the patched proxy deletion path.