Lesson 1 · Authentication — who are you?
The two questions & the map
Every access decision this platform makes is one of two questions — and the whole system is the sequence of gates that answers them.
Your win: name the two security questions, distinguish them cleanly, and draw the full gate sequence a request passes through — so every later lesson has a place to live on the map.
Two questions, never confused
All of access control reduces to two questions asked in order:
🔑 Authentication (authN)
"Who are you?" Proving identity. Here: a JWT presented with every request, its signature verified against a public key set. Answered once, at the door.
🚪 Authorization (authZ)
"What may you do?" Deciding what a known identity can access. Here: three tiers — a role gate, a granular permission scoped to a place, and row-level filtering. Answered repeatedly, per resource.
Keeping these apart is the first discipline. A valid token means you're authenticated — it says nothing about whether you may read a given student's record. That's a separate, later question.1
The gate sequence — the spine of this course
A request that reaches your data has passed, in order, through every gate below. Memorize this; it's the skeleton every lesson hangs on:
The three tiers of authorization
Notice authZ isn't one check — it's three, deliberately layered. This is defense in depth: each tier catches something the others can't.
| Tier | Question | Mechanism | Part |
|---|---|---|---|
| Role (RBAC) | Is your role allowed to call this method? | rbacDecider in the interceptor | 2 |
| Permission + location | Do you hold this permission on this place? | granted permissions ⋈ access_paths | 2 |
| Row-Level Security | Does this row belong to your tenant/scope? | Postgres policies on resource_path | 3 |
interceptors with the same
type names (Auth, GroupDecider): the legacy
internal/golibs/interceptors and the current
internal/usermgmt/pkg/interceptors. Every service uses the usermgmt one
for the live interceptor; the golibs one still hosts the shared token verifier, the claims struct,
and the context accessors. When you grep, check which package you're in. We'll flag it again in
Lesson 4.
internal/usermgmt/pkg/interceptors/auth.go +
internal/shamir; the role gate in each cmd/server/<svc>/auth.go
(rbacDecider); permissions/locations in migrations/bob/1182 +
migrations/auth/1001; RLS in pool_gcp.go + those same migrations. The
repo map has every anchor.
Authentication vs authorization, precisely
The clean distinction between "who you are" (ID token / OIDC) and "what you may access" (OAuth / access token) — the mental model this whole course rests on.
→ Auth0 — ID token vs access token
→ OpenID Connect Core 1.0 (OIDC = authN layer on OAuth 2.0) ·
NIST — RBAC
Check yourself (from memory)
Q1. A request arrives with a valid, unexpired JWT. What has been established?
Q2. Which is NOT one of the three authorization tiers?
Q3. Why layer three authorization tiers instead of one?
rbacDecider) → ③ service check
(ownership + granular permission on a location) → ④ repo (WHERE resource_path,
deleted_at IS NULL) → ⑤ RLS (Postgres filters rows by tenant + location). A row
survives only if the repo query and the RLS policy both allow it — defense in
depth. Part 1 = authN; Parts 2–3 = the three authZ tiers.Manabie claim that
carries your identity and your tenant. Confused about where a topic sits on the map?
Ask me — that's what I'm here for.
1. authN vs authZ: Auth0, OIDC Core. In-repo map: docs/auth/reference/repo-auth-map.md.