Stage 7 · L32
Treat CORS as a browser-origin policy
Core · original Session 7
Download starter · Download solution
Use the starter for this stage's focused examples. The cumulative transfer and solution belong at the stage-end capstone. Baseline checks pass; transfer checks initially fail. Downloads contain the matching native starter and solution for this stage.
CORS is a browser response-access rule, not authentication. A browser may send an OPTIONS preflight before a request with Authorization or JSON. CORSMiddleware answers whether the requesting Origin, method and headers are allowed. The route still requires a current actor and permitted action.
The snapshot permits exactly http://localhost:5173, the methods used by these routes and Authorization/Content-Type headers. It does not allow arbitrary origins or credentials by wildcard. The baseline checks an allowed preflight200, a denied origin400 and an actual unauthenticated POST that still returns401 even from the allowed origin.
Origin consists of scheme, host and port. http://localhost:5173 differs from http://127.0.0.1:5173 and from an https origin. A server-to-server script is not subject to browser CORS enforcement and can send a request regardless; the API's authentication/authorization must therefore protect it independently.
Same-origin cookies introduce additional browser/session considerations such as CSRF and secure cookie settings. This teaching API uses an explicit bearer header rather than a cookie login. It does not certify the website's production browser security by answering one preflight. The website already has its own Django/session boundary.
Keep CORS configuration as narrow as the intended local client requires. A successful preflight is permission to attempt the browser request, not proof of identity, row ownership or a successful business write. Test all of those boundaries separately.
Follow the running code
Focused lesson example; see the end-of-stage capstone for the cumulative app · stage 07
OPTIONS /rentals
Origin: http://localhost:5173
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Allowed preflight → browser may attempt request
Actual request → still authenticate and authorize.Predict and observe this focused example using the concepts explained above. Its boundary is stated in the focused answer.
Guided lab
- Read the explanation and predict the focused example’s outcome.
- Predict allowed-origin preflight, a different host/port and an unauthenticated actual POST from the allowed origin.
- Compare the observed outcome with the focused answer and state its boundary.
Expected: The configured origin's preflight is200; the unconfigured origin is400. An actual POST without bearer identity remains401. Scheme/host/port together define Origin. CORS controls browser response access; it grants neither identity nor business permission. Complete owner-page implementation in the stage capstone after these boundaries are taught.
- CORS alone cannot stop a nonbrowser caller; allowed origin does not grant a role or record.
Focused exercise and answer
Complete this focused exercise before reading its answer. The full native transfer is introduced only at the end of the stage.
Your transfer task: Predict allowed-origin preflight, a different host/port and an unauthenticated actual POST from the allowed origin.
- Predict allowed-origin preflight, a different host/port and an unauthenticated actual POST from the allowed origin.
Inspect the matching answer
This answer addresses the focused exercise above; the cumulative implementation is shown only after the stage prerequisites.
The configured origin's preflight is200; the unconfigured origin is400. An actual POST without bearer identity remains401. Scheme/host/port together define Origin. CORS controls browser response access; it grants neither identity nor business permission. Complete owner-page implementation in the stage capstone after these boundaries are taught.Stage 07 capstone — after these prerequisites
Implement current owner scope before filter/order/pagination; preserve masked read and action no-effect denials.
Use the downloaded starter after completing this stage's focused exercises. The cumulative implementation below is a stage transfer answer, not an answer to an earlier lesson.
python run_checks.py --stage 07 --role starter --prepare
python run_checks.py --stage 07 --role starter
python run_checks.py --stage 07 --role starter --transfer
From this extracted starter: preparation and baseline pass; transfer initially fails only at the named unfinished target. After implementing it, rerun the same starter --transfer command and expect success.
Optional comparison in a separate solution directory
Optional comparison: download and extract this stage’s solution ZIP into a separate directory. Change your terminal into that extracted solution root (beside checkpoint.json and run_checks.py) before running the following commands. Your starter remains a starter even after you implement its task.
python run_checks.py --stage 07 --role solution --transfer
Inspect the cumulative capstone implementation
def list_rentals(session, status, limit, offset, actor):
authorize(actor, "rental", "read")
statement = select(Rental).options(joinedload(Rental.equipment))
if actor.role != "admin":
statement = statement.where(Rental.owner_id == actor.id)
if status is not None:
statement = statement.where(Rental.status == status)
statement = statement.order_by(Rental.created_at, Rental.id).limit(limit).offset(offset)
return [RentalDetail.model_validate(row) for row in session.scalars(statement).all()]
Check your reasoning
Does an allowed preflight authorize a rental?
Show the explanation
No. Current identity, permitted action and business invariants still apply to the actual request.
Reading progress
54 lessons remain open to guests. Marking a lesson read records reading only; it does not award assessment credit or a certificate.
Device reading marks require browser storage. Reading is always available.
Sign in or create an account to save separate account progress. Your current page is kept.
Your earlier place on this device suggests these lessons. No new lesson is marked read.