Day 051: Authentication, Authorization, and API Trust
API security gets much clearer when you separate three questions: who is calling, what are they allowed to do, and why should this system trust the proof they presented.
Today's "Aha!" Moment
Many backend teams say “auth” as if it were one feature. That shortcut causes a lot of confusion. A valid token, a logged-in session, an OAuth flow, and a role check all feel related, but they solve different problems. If you collapse them together, the system may successfully prove identity and still grant the wrong access, or carry a token correctly and still have no trustworthy authorization model behind it.
The more useful mental model is a trust chain. First, the API needs a believable identity for the caller. Second, it needs a policy decision about whether that identity may perform this action on this resource. Third, it needs a safe way to carry that trust across requests, clients, and sometimes across organizational boundaries. Authentication, authorization, and token/session mechanics are different links in that chain.
Imagine the learning platform. A student should read only their own progress. An instructor may edit courses they own. An admin may access system-wide controls, but those operations need stronger audit and privilege handling. A valid identity token can help the API know who the caller is. It does not answer whether that caller may edit course 42 or read another learner’s data. That second question is authorization, and it is where many real API bugs live.
The key shift is this: tokens and login flows are not the center of the model. Trust boundaries and permission rules are. Once those are explicit, sessions, JWTs, OAuth, and OIDC become implementation choices that support the model instead of pretending to define it.
Why This Matters
The problem: Security work often starts with token libraries or authentication middleware instead of starting with a clear trust model and permission design.
Before:
- Authentication and authorization are treated as interchangeable.
- A valid token is mistaken for permission.
- JWT versus session debates dominate while ownership and policy rules remain vague.
After:
- Identity proof and permission checks are designed separately.
- Access is tied to domain rules such as role, ownership, tenant, or scope.
- Token or session mechanisms are chosen to support the trust model rather than to replace it.
Real-world impact: Fewer authorization bugs, better auditability, clearer service-to-service trust, and APIs whose security behavior can actually be explained during review or incident response.
Learning Objectives
By the end of this session, you will be able to:
- Separate identity from permission - Explain authentication and authorization as different stages in API trust.
- Understand what sessions, JWTs, OAuth, and OIDC really solve - See them as trust-carrying or delegation mechanisms rather than as whole security architectures.
- Evaluate API access rules more sharply - Identify where role checks, ownership checks, scopes, and service trust should actually live.
Core Concepts Explained
Concept 1: Authentication Establishes a Principal, Not an Outcome
Suppose the API receives a request with a bearer token and validates it successfully. What has the system learned? Ideally, it has learned who the caller is or which principal the request represents: learner u-17, instructor u-42, service grading-worker, or admin u-1.
That identity step is authentication. It answers “who is this request acting as?” It may involve credentials, cookies, signed tokens, client certificates, or delegated identity providers. But the result should be conceptually simple: the request now has a principal attached to it.
One clean picture is:
request
-> verify credential / session / token
-> establish principal
-> pass principal to policy checks
This is powerful because later parts of the backend can stop guessing who the caller is. But authentication alone does not grant action rights. It only establishes the subject for later checks.
The trade-off is convenience versus assurance. Lightweight authentication flows improve usability, but stronger trust often requires better credential handling, expiration, revocation, and audit discipline.
Concept 2: Authorization Decides Whether This Principal May Perform This Action on This Resource
Once the principal is known, the real security question begins. May this user perform this action here? That decision often depends on more than a role string. It may depend on ownership, tenancy, relationship to the resource, sensitivity level, or contextual rules such as “only instructors assigned to this course may edit it.”
For the learning platform, these are very different decisions:
- a student reading their own progress
- an instructor editing a course they own
- an admin rotating system-wide settings
All three callers may authenticate successfully. The API still needs explicit policy for each resource/action pair.
def can_edit_course(user, course):
return user["role"] == "admin" or course["owner_id"] == user["id"]
The code is intentionally small because the important lesson is conceptual: authorization always combines principal + action + target resource. If your security model does not mention the resource explicitly, it is often already too weak.
This is also why UI hiding is never enough. Hiding the “Edit Course” button does not protect the underlying endpoint. The backend must enforce the same rule.
The trade-off is simplicity versus precision. Broad role checks are easy to implement, but domain-specific ownership and scope rules are often what the business actually needs to stay safe.
Concept 3: Sessions, JWTs, OAuth, and OIDC Move or Delegate Trust; They Do Not Replace Policy
Teams often argue about sessions versus JWTs as if that alone decides API security. It does not. These mechanisms are mostly about how trust information is carried or delegated.
- Session cookies: the server stores session state and the client presents a session handle
- JWTs: the client carries signed claims that the server can validate
- OAuth 2.0: a framework for delegated authorization
- OpenID Connect: an identity layer on top of OAuth 2.0
They solve different transport and trust-boundary problems. Browser-based apps often fit cookies and server-managed sessions well. Mobile or API ecosystems may use tokens more naturally. Third-party login and delegated access often call for OAuth/OIDC flows. But none of these choices answer the core permission question automatically.
One useful trust-chain diagram is:
identity provider / login flow
-> credential or token issued
-> API validates and establishes principal
-> authorization policy checks resource/action
-> request allowed or denied
This is why “we use JWTs” is not a security model. It says something about how claims move, not about whether those claims are fresh enough, revocable enough, least-privileged enough, or mapped correctly to domain permissions.
The trade-off is distribution versus control. Self-contained tokens reduce repeated server lookups, but server-managed sessions can make revocation and central control simpler. Delegated identity improves integration, but also expands the trust boundary that must be understood.
Troubleshooting
Issue: A valid token is treated as proof the request is authorized.
Why it happens / is confusing: Token validation is a visible security step, so it can feel like the hard part is already over.
Clarification / Fix: Treat token or session validation as the identity stage only. Every sensitive endpoint still needs a domain-aware authorization decision over the requested resource.
Issue: Security design collapses into JWT versus session debate.
Why it happens / is confusing: Transporting trust is concrete and library-driven, while modeling permissions is more domain-specific and less productized.
Clarification / Fix: Decide the trust boundary first: who the principals are, how permissions work, how revocation should behave, and what delegation is needed. Then choose the mechanism that carries that trust appropriately.
Advanced Connections
Connection 1: API Trust ↔ Domain Modeling
The parallel: Authorization gets much easier when ownership, tenancy, and administrative boundaries are explicit in the domain model itself.
Real-world case: Course editing becomes easier to secure once the data model clearly states which instructor owns or manages which course.
Connection 2: Authentication ↔ Distributed Systems Trust
The parallel: Service-to-service identity, user identity, and delegated identity all revolve around the same problem: how to carry trustworthy principals across boundaries without letting trust become ambiguous.
Real-world case: Internal workers and public clients should rarely share exactly the same trust assumptions, even if they hit related APIs.
Resources
Optional Deepening Resources
- These resources are optional and are not required for the core 30-minute path.
- [RFC] The OAuth 2.0 Authorization Framework (RFC 6749)
- Link: https://www.rfc-editor.org/rfc/rfc6749
- Focus: Read OAuth as a delegation framework rather than as “the JWT standard.”
- [SPEC] OpenID Connect Core 1.0
- Link: https://openid.net/specs/openid-connect-core-1_0.html
- Focus: See how identity layers on top of delegated authorization flows.
- [DOC] OWASP API Security
- Link: https://owasp.org/API-Security/
- Focus: Review common authorization and trust-boundary mistakes that appear in real APIs.
Key Insights
- Authentication and authorization are different decisions - Identity proof answers who the caller is; policy answers what that caller may do.
- Authorization is where API trust becomes domain-specific - Role, ownership, scope, and tenancy checks are the real gatekeepers.
- Tokens and sessions carry trust, they do not define it - JWTs, cookies, OAuth, and OIDC are mechanisms for transport and delegation, not substitutes for a coherent permission model.
Knowledge Check (Test Questions)
-
What does authentication establish in an API request?
- A) Which principal the request is acting as.
- B) Everything that principal may do.
- C) Whether the requested resource should be editable.
-
Why is authorization a separate problem from authentication?
- A) Because even a valid identity still needs resource- and action-specific permission checks.
- B) Because authenticated users never need access limits.
- C) Because tokens cannot represent user identity.
-
What is the best way to think about sessions, JWTs, OAuth, and OIDC?
- A) As mechanisms for carrying or delegating trust information under different assumptions.
- B) As replacements for permission checks.
- C) As proof that security is complete once implemented.
Answers
1. A: Authentication establishes the principal behind the request, such as a user or service identity.
2. A: Knowing who is calling is necessary, but the system still has to decide whether that principal may perform this action on this resource.
3. A: These mechanisms determine how identity and access information move across boundaries; they do not by themselves define the authorization model.