AuthN vs AuthZ Under Questioning
Every security round opens with the definitional staple: "What's the difference between authentication and authorization?" The one-liner is table stakes β authentication is who are you, authorization is what are you allowed to do β but the question is a doorway, not a destination. The interviewer immediately walks you into scenarios, and that's where candidates separate.
Cookie vs JWT β answer with the architecture, not a preference
The follow-up: "Would you use cookies or JWTs here?" The strong answer starts by asking
what "here" is. For a server-rendered MVC app β which is exactly what this agency runs β
cookie authentication is the natural fit: the browser handles it, it's HttpOnly and
Secure so script can't read it, sliding expiration is built in, and sign-out actually works
because the server owns the session. JWTs earn their place for APIs consumed by other
services or SPAs β self-contained, stateless, cross-domain β but come with the costs people
often forget: you can't revoke one before expiry without building a denylist
(re-introducing the state you were avoiding), and storing them in localStorage hands them
to any XSS. The senior-sounding sentence: "Cookie for the MVC front end, JWT bearer for
service-to-service APIs β and both are just authentication; authorization is a separate
layer on top." Mention that in practice the agency likely fronts this with Entra ID via
OpenID Connect, and the app still ends up with a cookie.
Roles, policies, and the question that actually matters
"How do you handle roles?" Show the ladder. [Authorize(Roles = "Reviewer")] works but
scatters role names through the codebase. Policy-based authorization is the ASP.NET Core
model: define "CanApproveTranscripts" once in AddAuthorization, express it via role
claims, custom claims, or an IAuthorizationRequirement with a handler β controllers depend
on the capability, not the role name. When HR renames a role, you edit one policy.
Then the question that separates levels: "A reviewer can only see candidates assigned
to their region β where does that check live?" Roles can't answer per-record questions.
That's resource-based authorization: load the record, then check the user against that
resource (IAuthorizationService.AuthorizeAsync(user, candidate, policy)) β and enforce it
in the query too (Where(c => c.Region == user.Region)), or your list pages leak what your
detail pages protect. Never trust an ID posted from the browser to imply permission β that's
IDOR, and it's module 6's recurring villain.
Answers that fall flat
- Conflating the two concepts ("the JWT authorizes the user").
- JWT-in-localStorage with no XSS story; or "we check the role in the view" as access control.
- Per-record authorization done only in the UI layer β hidden buttons are not security.
Practice prompts
- Deliver the cookie-vs-JWT answer for (a) this MVC app, (b) a partner-facing API.
- Design the policy set for candidate records: reader, reviewer, approver, admin.
- Walk through where region-based record access is enforced β controller, service, query β and why one layer isn't enough.