Identification, Authentication, Authorisation
3.0 What this chapter gives you#
- You will be able to take any sentence containing the word “auth” and say which of three completely different operations the speaker meant.
- You will be able to explain why identification is a search through a list and authentication is a comparison of two things, and why that difference decides which one can fail silently.
- You will be able to describe an authorization decision as a function of a subject, an action, a resource and a context, and name the four inputs without looking them up.
- You will be able to design a system that grants access without ever learning who the person is, and say when that is the right answer.
- You will be able to choose correctly between HTTP 401 and HTTP 403 in any situation, quote the specification text that settles it, and spot the three common ways production code gets it backwards.
- You will be able to write an audit record that contains the six elements a regulator will ask for, and explain why the outcome field is the one everybody forgets.
- You will be able to read a RADIUS packet capture and say which attributes are answering “who is this” and which are answering “what may they do”.
- You will be able to walk a colleague through an airport departure and point at the exact moment each of the three questions is asked, using the real sixty-character boarding pass format.
- You will be able to recognize a confused deputy in your own architecture, and name the two authorities the deputy is holding.
There are three verbs at the centre of this subject and they are almost never used correctly. Identification is the claim: I am Anita Rao. Authentication is the proof: here is something only Anita Rao has. Authorization is the permission: given that you really are Anita Rao, you may read this file and you may not delete it. Three verbs, three questions, three answers of completely different shapes.
Engineers run them together constantly. A codebase will have a package
called auth that does all three and a comment that explains none of
them. A ticket will say “the user is not authorized” when the password
was wrong. An API will return the status code for one when it means the
other. None of this is pedantry. Each of the three fails in its own way,
each failure has a different cause and a different fix, and a system
that cannot tell you which of the three refused a request cannot be
debugged, cannot be audited, and cannot be made safe.
This chapter separates them and keeps them separate. We will take one traveller through one airport, ask the three questions in order, and watch each succeed and fail on its own terms. Then we will do it again in exact professional language, with the real field layout of a boarding pass barcode, the real status codes of the web, and the real packet formats of the protocols that carry these questions across networks. Along the way we pick up a fourth verb, auditing, which is not optional, and meet a forty-year-old bug called the confused deputy that is currently being reinvented by everybody building software agents.
Two neighbours to mark and leave alone. The nouns these verbs operate on — the identifier, the attribute and the claim — are the business of chapter 2, which pulls them apart properly. The database underneath, the table with one row per human being, belongs to chapter 4. This chapter is about the verbs.
The plain version#
Three different questions at the same airport#
Anita Rao is flying from Bengaluru to London on the seventeenth of August, 2026. She has a booking, a passport and a small suitcase. Over the next two hours she will be asked three questions by three different people, and although all three feel like the same question — “who are you and can you get on this plane” — they are not. They are as different from each other as weighing, measuring and pricing.
The first question happens at the check-in desk. Anita says her name. The clerk types it into a screen, and the screen holds everybody booked on flight ZZ 118 that day: two hundred and fourteen people. The computer looks through all two hundred and fourteen names and finds the one that matches. That is the first question, and here is its exact shape:
Which one of all these people are you?
Notice what the computer just did. It started with one piece of information — a name — and searched a whole list to find the row that fits. It compared one thing against many things. It could have found nothing. It could have found two. If there are two women called Anita Rao on the same flight, and there sometimes are, the screen shows two rows and the clerk has to ask something else to tell them apart.
The second question happens about four seconds later, and it feels so natural that most travellers never notice it is a separate question at all. The clerk asks for the passport. She opens it, looks at the photograph, and looks at Anita’s face. Then she looks at the name in the passport and the name on the screen.
Are you really the person you just said you were?
This is a completely different operation. There is no searching. There is no list. There are exactly two things — the face in front of the clerk and the photograph in the book — and one comparison between them. The answer is yes or no. Nothing is being looked up; something is being checked.
The third question happens at the gate, forty minutes later, and it is asked by a machine rather than a person. Anita holds her boarding pass under a scanner. The scanner reads the barcode, a light goes green, and she walks down the jetway.
Are you allowed to do this particular thing?
The thing, in this case, is walking through this particular door at this particular time to sit in seat 14C of this particular aircraft. And here is the part that surprises people when it is pointed out: the machine at the gate did not ask who she was. It did not look at her face. It did not open her passport. It read a piece of paper. If Anita had handed the boarding pass to a stranger in the departure lounge, the stranger would have got a green light too, because the gate is not checking a person. It is checking a permission.
The three questions have three different shapes#
It is worth slowing down here, because the difference between the three questions is the whole chapter.
The first question searches. You give it one clue and it hunts through a list, which might hold two hundred names or two hundred million. The bigger the list, the more chances of finding the wrong row, and the answer is not “yes” or “no” but “here is the row I think you meant”.
The second question compares. You give it two things and it says whether they match. It does not care how big any list is. It is looking at exactly one photograph and exactly one face, or exactly one password and exactly one stored value.
The third question decides. It does not search and it does not compare faces. It takes a fact — this pass is valid for this flight — and applies a rule: passengers holding a valid pass for this flight may board. The rule was written long before Anita arrived, by somebody who never met her.
Here they are together.
| Question | What it does | Answer looks like |
|---|---|---|
| Which one are you? | Searches a list | A row, or none, or many |
| Really you? | Compares two things | Yes or no |
| May you do this? | Applies a rule | Allow or deny |
Read that table twice. Almost every muddle in this subject comes from treating one of those three rows as though it were another.
The three questions fail in three different ways#
Because they are different operations, they break differently, and this is the practical reason to keep them apart.
The first question can fail by finding the wrong person. There are two Anita Raos, and the clerk clicks the first one. Now the wrong booking is checked in, the wrong bag is tagged, and nothing looks broken until somebody’s suitcase goes to the wrong city. It can also fail by finding nobody: the booking was made as “Anita R Rao” and she said “Anita Rao”, and a person who has paid for a seat is told she does not exist.
The second question can fail by accepting a lie. Somebody presents a good forgery, the photograph looks close enough, and the clerk waves them through. Or it fails the other way: Anita has cut her hair since the photograph was taken, the clerk is not convinced, and a real passenger is refused.
The third question can fail by permitting too much, letting somebody into a seat they never paid for, or too little: Anita paid for extra legroom, the rule in the machine was never updated, and she is sent to the wrong seat.
Notice that all six of these failures would be described by a frustrated traveller in exactly the same words: “they would not let me on the plane”. Six different causes, six different fixes, one sentence. That is why the vocabulary matters.
The fourth thing, which nobody notices#
While all of this is happening, something else is going on quietly. A computer somewhere is writing it down.
At 09:14 the check-in system recorded that a booking reference was retrieved. At 09:15 it recorded that a passport number was entered against that booking. At 09:52 the gate reader recorded that a boarding pass was scanned and accepted, at gate 22, by reader number 4. If, three weeks later, somebody asks how a person with no ticket got onto flight ZZ 118, these recordings are the only way anyone will find out.
This is the fourth verb, and it has no glamour at all: auditing, which means keeping an honest record of what was asked and what was answered. It is not part of letting people through doors. It is what lets you find out afterwards what happened, and it is the first thing dropped when a deadline is close.
An honest record has to answer six small questions: what happened, when it happened, where it happened, who or what caused it, who or what it was done to, and — the one everybody forgets — whether it worked. A log line that says “Anita Rao attempted to board” and does not say whether she boarded is close to useless, because the interesting events are exactly the ones that failed.
Where the boarding pass comes from, and what it really is#
Go back to the moment at the gate, because there is something odd buried in it.
The boarding pass is a piece of paper, or a rectangle on a phone screen, with a barcode. Inside the barcode is a short line of text: the passenger’s name, the booking reference, where the flight starts, where it ends, which airline, which flight number, which day, which seat. That is all. There is no photograph in it. There is no fingerprint. There is usually no signature or seal of any kind.
So the boarding pass is not a proof of who you are. It is a proof of what you may do. It says: the holder of this may sit in seat 14C on this flight. The holder. Not Anita Rao — whoever is holding it.
We meet this pattern everywhere once we start looking. A cinema ticket does not know your name. A hotel key card knows a door and a date range. A cloakroom token knows a peg, and if you lose it the coat is gone. All of these are permissions that travel on their own, separated from any person, and they work because you hold them. Systems built this way are giving up on knowing who you are, on purpose, in exchange for something simpler and often more private.
The whole plain story in one place#
Here is Anita’s journey with the three questions marked.
| Moment | Question asked | How it is answered |
|---|---|---|
| Says her name at desk | Which one are you? | Search 214 bookings |
| Hands over passport | Really you? | Face against photo |
| Barcode at the gate | May you do this? | Rule about the pass |
| Every step above | (recorded) | Written to a log |
Three questions, in that order, at that airport. A search, then a comparison, then a rule. And a fourth thing, running underneath, writing it all down.
Those three questions have professional names, and you have now earned them. The search is called identification. The comparison is called authentication. The rule is called authorization. The writing down is called auditing. Everything else in this chapter is those four words done carefully.
Where the plain version stops being true#
The three questions do not always come in that order#
The airport told the story neatly: identify, then authenticate, then authorize. Real systems shuffle it constantly, and some of them skip steps entirely.
When you unlock a phone with your face, no name is claimed first. The phone does not ask who you are and then check. It looks at a face and searches the small set of faces enrolled on that device. Identification and authentication have collapsed into one operation.
When you use a hotel key card, there is no identification and no authentication in any meaningful sense. The lock does not know you, and the card does not prove anything about you. It carries a permission and the lock reads it.
When a bank calls you back on a number it already holds, the order reverses: the channel is authenticated first and you are identified second.
The honest version: the three verbs are three questions, not three steps. They can be asked in any order, some can be skipped, and two of them can be answered by a single act. What must never happen is that a system believes it has answered one when it has only answered another.
The gate scanner really does not care who you are#
This bears repeating because it is the piece readers refuse to believe. The green light at the gate is a decision about a token, not a person. The name printed on the boarding pass is data inside the token. Nothing at that moment reads it against a face.
Airports patch around this. The passport check at security, and at many airports a second check at the gate, is where a person is bound to a pass. The barcode itself is a bearer instrument, in the plain sense that whoever bears it gets the benefit.
The honest version: a permission that travels on its own is not a weaker version of identity, it is a different thing. Chapter 38 deals with the token as an object in its own right; the point here is only that authorization can and often does happen with no identification at all.
“Prove it” is never really yes or no#
The plain version said the second question has a yes-or-no answer. It does not. A clerk looking at a photograph is making a judgement under time pressure, and so is a face-matching algorithm.
Every check of this kind has two ways to be wrong, and they trade against each other. Make the check stricter and you refuse more genuine travellers. Make it looser and you admit more impostors. There is no setting that removes both errors, only settings that choose the ratio. This is not a defect of any particular product. It is a property of comparing two noisy measurements of the same thing.
The honest version: authentication produces a confidence, and the yes-or-no you see is that confidence compared against a threshold that somebody chose. Chapter 19 covers the measurement of that trade for biometrics, and chapter 48 covers what “how sure are you” means as an engineering quantity.
The search does not return one answer#
The plain version said the check-in screen finds the row that matches. Sometimes it finds several, and sometimes the several are not obvious.
In March 2004 Senator Edward Kennedy of Massachusetts was stopped at airports on the east coast of the United States and refused a ticket by airline staff. The Washington Post reported it on the twentieth of August, 2004, under the headline “Sen. Kennedy Flagged by No-Fly List”. The story was repeated for a decade. The Transportation Security Administration corrected it in a “myth buster” post in July 2008: he was not on the no-fly list and not on the selectee list either. He had been misidentified as somebody on the selectee list, because he shared a surname and a first initial with them. The name being matched against was “T. Kennedy”.
Kennedy described it himself at a Senate hearing on the nineteenth of August, 2004. He was told he could not buy a ticket, could not get information about why, and the problem recurred several times. He said it took weeks to fix, after the Secretary of Homeland Security personally apologized, and he asked the obvious question: if it takes that to fix it for a senator, what happens to everyone else.
The honest version: a one-to-many search over human names returns candidates, not answers, and the bigger the list the more candidates it returns. This is the deduplication problem, and chapter 8 is entirely about it. Here it is enough to see that identification alone is not a decision and must never be treated as one.
One document can answer all three questions, and that hides the seams#
A passport is doing three jobs at once. Its number is a label that picks one record out of a national register. Its photograph and chip are proof that the holder is the person in that record. And, quite separately, the visa page is a permission: this holder may enter that country for that purpose until that date. Because the three jobs arrive stapled together in one book, travellers experience them as one thing, and software copies the confusion: a session cookie, a signed token or a directory entry routinely carries all three at once, and then somebody changes one of them and is surprised when another breaks.
The honest version: whenever one artefact answers more than one of the three questions, write down which parts answer which. The seams are still there; they are just hidden, and hidden seams are where the incidents come from.
The answers are frozen in time, and the world is not#
The clerk checked the passport at 09:15. The gate scanned the pass at 09:52. Between those two moments the world could have changed. The passport could have been reported stolen at 09:30. The passenger could have been added to a watch list at 09:40. Nothing at the gate goes back and asks again.
Every real system does this. It answers the three questions once, writes the answer somewhere, and then trusts the written answer for minutes or hours. That written answer is a session, and it is the subject of chapter 36; the way it gets revoked when the world changes is chapter 30. Both exist because of the gap we have just described.
The honest version: authentication is an event at a moment, not a continuing state, and every system that behaves as though it were a continuing state is making a bet about how much can go wrong before the next check.
The plain version’s tidiest lie#
The tidiest lie in the plain version is the word “the” in “the list”.
At the check-in desk we said the computer searches the list of two hundred and fourteen passengers. In fact there are several lists, owned by several organizations, updated on different schedules: the airline’s departure control system, the reservation system that may belong to a different company, the government’s advance passenger information feed, and the watch lists matched against it. They disagree routinely, and reconciling them is somebody’s full-time job.
The honest version: identification is a search over one particular list belonging to one particular organization, and the belief that different organizations’ lists describe the same set of people is an assumption, not a fact. Chapter 4 takes the assumption apart.
The technical version#
Identification is a one-to-many search over a namespace#
Identification is the operation of selecting, from a set of enrolled entities, the one that a presented clue refers to. Formally it is a search: input one identifier or one set of attributes, output zero, one or many candidate records.
Three properties follow from that shape, and all three cause trouble in production.
It is one-to-many. The cost and the error rate both scale with the size of the enrolled population. A face-matching system that performs well against a gallery of five thousand employees is a different system, with different error behaviour, when pointed at a national register of a billion people, even with identical software. The biometrics vocabulary standard, ISO/IEC 2382-37:2022, makes this the defining distinction between a one-to-many search and a one-to-one comparison.
It can return more than one answer, and it can return none. Any code path that assumes exactly one result is a bug waiting for a common surname.
It is not a decision. Identification narrows a population. It does not establish anything. NIST Special Publication 800-63-4, the revision of the United States digital identity guidelines published on 1 August 2025, is careful about this: it defines identity proofing as “the processes used to collect, validate, and verify information about a subject to establish assurance in the subject’s claimed identity”, and that is enrolment, a separate exercise from either the search or the later proof. Chapter 7 covers enrolment properly.
In software, identification is usually invisible because it has been reduced to a primary-key lookup. A user types an email address, the server runs a query with a unique index behind it, gets one row, and the search feels like a certainty. It is still a one-to-many search; the namespace has simply been engineered so that collisions cannot happen. That engineering is chapter 2’s subject, and it is exactly what fails when the namespace is human names.
Authentication is a one-to-one check against a bound authenticator#
Authentication is the operation of testing a claim of identity against evidence bound to that identity in advance. It is one-to-one: one claimant, one stored reference.
SP 800-63-4 gives the definition in the tightest form anyone has managed: authentication is “the process by which a claimant proves possession and control of one or more authenticators bound to a subscriber account to demonstrate that they are the subscriber associated with that account”. Every word in that sentence is load-bearing. A claimant is defined as “a subject whose identity is to be verified using one or more authentication protocols” — that is, somebody who has made a claim and has not yet proved it. A subscriber is “an individual enrolled in the CSP identity service”, where CSP is the credential service provider. The proof is of possession and control of an authenticator. The authenticator is bound to an account. The binding happened earlier.
Three consequences.
Authentication is meaningless without a prior binding. If nothing was registered in advance, there is nothing to compare against, and whatever the system is doing, it is not authentication. Enrolment is therefore the root of trust for every later login, which is why attacks move there. Chapter 24, on recovery, is about what happens when the binding has to be re-established after it is lost, and it is the weakest point in most designs.
Authentication is a comparison of two things, so it inherits all the properties of comparisons: it can be made stricter or looser, it has two error types, and a threshold sits somewhere in the middle. For a password the comparison is exact and the error rate is zero for the comparison itself, which is why passwords feel binary; all their failure lies elsewhere, in guessing and theft, which is chapters 13 through 16.
Authentication says nothing about permission. Proving that you are Anita Rao establishes nothing about what Anita Rao may do. That is the next verb, and conflating the two is the single most common error in application code.
Authorization is a policy decision about a proven subject#
Authorization is the operation of deciding whether a given subject may perform a given action on a given resource in a given context. SP 800-63-4 defines it in one line: “a decision to grant access, typically automated by evaluating a subject’s attributes”. RFC 6733, the Diameter base protocol of October 2012, gives the older and equally serviceable network definition: “the act of determining whether a requesting entity (subject) will be allowed access to a resource (object)”.
The four inputs are worth memorizing, because a system that cannot name all four is a system whose policy is scattered through its code.
| Input | Airport example |
|---|---|
| Subject | Passenger Anita Rao |
| Action | Board |
| Resource | Flight ZZ 118, seat 14C |
| Context | 09:52, gate 22, that date |
The context input is the one that gets omitted and then bolted on badly. Time of day, source network, device posture, how recently the subject authenticated: all of these are context, and all of them turn up later as special cases if there is no place to put them at the start.
How the decision is actually expressed — roles, attributes, relationships, policy languages — is a large subject with its own chapter, and chapter 46 is it. What matters here is the boundary: an authorization decision takes a subject as an input. It does not establish the subject. If your authorization code is also deciding whether the caller is who they say they are, the two verbs have merged, and the merge is where the confused deputy lives.
Authorization without identification: capability tokens#
There is a whole family of systems in which the third verb runs and the first one never does. They work, they are old, and they are enjoying a revival.
The idea is a capability: an unforgeable reference that both names a resource and confers the right to use it. The word in this technical sense comes from Jack Dennis and Earl Van Horn, “Programming Semantics for Multiprogrammed Computations”, published in Communications of the ACM, volume 9, number 3, March 1966, pages 143 to 155. The contrast is with an access control list, which names the resource in one place and the permitted subjects in another, and requires the system to identify the caller before it can consult the list.
Butler Lampson formalized the difference in “Protection”, presented at the fifth Princeton Conference on Information Sciences and Systems in March 1971 and reprinted in ACM Operating Systems Review, volume 8, number 1, January 1974, pages 18 to 24. His access matrix has subjects down the side and objects across the top. Read it by row and you have a capability list: what this subject may do. Read it by column and you have an access control list: who may touch this object. Two ways of storing one matrix, and the choice decides whether identification is on the critical path.
Capabilities in modern practice look like this.
The boarding pass barcode, which we have already met. The hotel key card. The cloakroom token.
The OAuth 2.0 bearer token, defined in RFC 6750 of October 2012, whose definition is admirably blunt: a bearer token is “a security token with the property that any party in possession of the token (a ‘bearer’) can use the token in any way that any other party in possession of it can”, and “using a bearer token does not require a bearer to prove possession of cryptographic key material”. Chapter 40 covers the protocol that issues them.
The pre-signed URL. An Amazon S3 pre-signed URL embeds a signature authorizing one operation on one object until an expiry time, and the holder needs no account at all. So does a document link shared with “anyone with the link”.
The macaroon, described by Arnar Birgisson, Joe Gibbs Politz, Ulfar Erlingsson, Ankur Taly, Michael Vrable and Mark Lentczner in “Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud”, at the Network and Distributed System Security Symposium in the year 2014. A macaroon is a bearer credential built from chained message authentication codes, so that any holder can attenuate it — add a caveat narrowing where, when or for what it may be used — without talking to the issuer, and cannot broaden it.
The advantages are real. There is nothing to look up, so the decision is fast and works offline. There is no account, so there is nothing to correlate, which is a genuine privacy gain rather than a marketing one. Delegation is trivial: hand over the token.
The disadvantages are equally real. Whoever holds it, holds the right. Revocation is hard, because there is no subject to disable, only a token to blacklist. Auditing degrades, because the log records which token was used but not who used it. And a token that leaks into a referrer header, a browser history or a proxy log has leaked the access with it, which is why RFC 6750 permits sending a bearer token in a URI query parameter and then spends a section explaining that you should not.
The honest version: capability tokens do not remove the need for the first two verbs, they move them earlier. Somebody identified and authenticated a person at the moment the token was minted. The token is a cached authorization decision with a shelf life.
The 401 and 403 distinction in HTTP, and why it is routinely wrong#
The web has carried the identification and authorization confusion in its status codes since the beginning, partly because one of them is misnamed.
The status codes 401 and 403 both appeared in RFC 1945, the HTTP/1.0 specification of May 1996 by Tim Berners-Lee, Roy Fielding and Henrik Frystyk. Their current definitions are in RFC 9110, “HTTP Semantics”, published in June 2022 by Roy Fielding, Mark Nottingham and Julian Reschke, which obsoleted the older split across RFCs 7230 to 7235.
RFC 9110 section 15.5.2 defines 401: “The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field (Section 11.6.1) containing at least one challenge applicable to the target resource.”
RFC 9110 section 15.5.4 defines 403: “The 403 (Forbidden) status code indicates that the server understood the request but refuses to fulfill it.” It continues: “If authentication credentials were provided in the request, the server considers them insufficient to grant access. The client SHOULD NOT automatically repeat the request with the same credentials.” And it closes with the escape hatch: an origin server that wishes to hide the existence of a forbidden resource may respond 404 instead.
So the rule, stated once and correctly:
401 -> "I do not know who you are."
Authentication failed or was absent.
MUST include a WWW-Authenticate challenge.
Retrying with better credentials may work.
403 -> "I know who you are. You may not."
Authorization failed.
No challenge, because a challenge is pointless.
Retrying with the same credentials will not work.
The name of 401 is the problem. Its registered reason phrase is
“Unauthorized”, but its meaning is unauthenticated, and the request
header that carries the credentials is called Authorization, a name in
place since RFC 1945 section 10.2. Two of this chapter’s three words are
used backwards in the specification’s own labels, and thirty years of
developers have learned the wrong association from them. The prose in
RFC 9110 is unambiguous even where the labels are not.
Three failure patterns turn up again and again in production.
The first is returning 403 when there are no credentials at all. The
caller cannot tell whether to log in or give up, because there is no
challenge to respond to. This is common enough that a major framework
documents it as intended behaviour: Django REST Framework returns 401
only when the first authentication class on the view uses a
WWW-Authenticate header, and 403 otherwise, stating plainly that HTTP
403 responses do not include that header. The framework is internally
consistent; the client still cannot tell whether authenticating would
have helped.
The second is returning 401 for an authorization failure. A valid token belonging to a real user who is not an administrator gets 401, the client’s retry logic throws away a perfectly good token, re-authenticates, and gets 401 again. Refresh loops built this way have taken down services under their own retry traffic.
The third is the deliberate one, and it is correct: returning 404 to
hide the existence of a resource. RFC 9110 explicitly allows it, and
serious systems use it. Amazon S3 documents the behaviour exactly: if
the object you request does not exist, S3 returns 404 if you hold the
s3:ListBucket permission on the bucket and 403 if you do not. The
status code is chosen to avoid telling an unauthorized caller whether
the key exists. Anyone debugging S3 permissions has been confused by
this; it is not a bug.
Done properly, the mapping is available in a standard. RFC 6750 section
3.1 fixes it for OAuth 2.0 bearer tokens: invalid_request maps to 400,
invalid_token maps to 401, and insufficient_scope maps to 403. Those
three codes are precisely our three verbs — malformed request, unproven
subject, proven subject without permission.
Here is the exchange in full, with both outcomes.
GET /accounts/8814/statements HTTP/1.1
Host: api.example.com
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api",
error="invalid_token",
error_description="token expired"
GET /accounts/8814/statements HTTP/1.1
Host: api.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
HTTP/1.1 403 Forbidden
Content-Type: application/json
{"error":"insufficient_scope",
"scope":"statements:read"}
Read the two responses. The first says: I have no idea who is calling, here is how to tell me. The second says: I know who is calling, and this token lacks the scope this endpoint needs. A client can act correctly on both, and can only guess if it gets 403 for both.
| Code | Means | Send when |
|---|---|---|
| 400 | Malformed request | Syntax or params wrong |
| 401 | Not authenticated | No or bad credentials |
| 403 | Not authorized | Good credentials, no right |
| 404 | Hidden or absent | Existence is a secret |
Auditing, the fourth verb#
The three verbs decide. The fourth verb records. In network engineering the fourth letter is usually accounting, which is auditing plus measurement for billing; RFC 6733 defines accounting as “the act of collecting information on resource usage for the purpose of capacity planning, auditing, billing, or cost allocation”.
An audit record has a specification, and it is short. NIST SP 800-53 Revision 5, control AU-3, “Content of Audit Records”, requires that audit records contain information establishing six things: what type of event occurred; when the event occurred; where the event occurred; the source of the event; the outcome of the event; and the identity of any individuals, subjects, or objects and entities associated with the event.
The payment card industry asks for the same six with different wording. PCI DSS requirement 10.2.2 requires audit logs to record, for each auditable event: user identification; type of event; date and time; success and failure indication; origination of event; and identity or name of affected data, system component, resource, or service.
Both lists contain the element that application logging habitually omits: the outcome. A log that records only successes cannot answer the question anybody actually asks after an incident, which is what was tried and refused.
Written out for our airport, one gate event looks like this.
{
"event": "boarding.scan",
"ts": "2026-08-17T09:52:41.318Z",
"where": {"site": "BLR", "gate": "22",
"reader": "R4"},
"source": {"actor": "device:reader-R4",
"op_id": "OP-4471"},
"target": {"pnr": "QK4T2P",
"flight": "ZZ0118",
"seat": "14C"},
"decision": "allow",
"reason": "valid_pass_for_flight",
"verb": "authorization"
}
Two design rules earn their place here.
Record the decision, not the conclusion. Fields that say which of the three verbs refused, and why, turn an incident investigation from archaeology into a query. A log line saying “access denied” and nothing else has thrown away the only information that mattered.
Protect the log at least as well as the thing it describes. SP 800-53 control AU-9 exists because an attacker who can edit the audit trail has removed the only evidence. Append-only storage, a separate trust boundary, and shipping records off the machine that generated them are the usual answers.
There is a genuine tension here, and it is not resolved. AU-3 tells you to record the identity of the individuals associated with the event; the same control’s supplemental guidance warns that audit records can reveal personal information and create privacy risk. Recording everything forever is the safe answer for forensics and the wrong answer for privacy law. Chapter 55 takes that argument up properly.
AAA on the wire: RADIUS#
The letters AAA — authentication, authorization, accounting — became standard vocabulary through network access control, because of one protocol.
RADIUS, the Remote Authentication Dial In User Service, was written at Livingston Enterprises for the Merit Network’s dial-in service and first published by the IETF as RFC 2058 in January 1997. The current base specification is RFC 2865, June 2000, by Carl Rigney, Steve Willens, Allan Rubens and William Simpson. Its companion, RFC 2866, “RADIUS Accounting”, carries the third A.
RFC 2865 describes itself as a protocol “for carrying authentication, authorization, and configuration information between a Network Access Server which desires to authenticate its links and a shared Authentication Server”. Read that again: authentication and authorization travel in the same message. That is the design decision that matters.
The mechanics are small enough to state completely. RADIUS runs over UDP; the assigned ports are 1812 for authentication and 1813 for accounting, and older equipment used 1645 and 1646, which collided with another registered service. A packet is between 20 and 4096 octets: a one-octet Code, a one-octet Identifier, a two-octet Length and a sixteen-octet Authenticator, then attributes in type-length-value form.
| Code | Name | Sent by |
|---|---|---|
| 1 | Access-Request | Access server |
| 2 | Access-Accept | RADIUS server |
| 3 | Access-Reject | RADIUS server |
| 4 | Accounting-Request | Access server |
| 5 | Accounting-Response | RADIUS server |
| 11 | Access-Challenge | RADIUS server |
The three verbs map onto those codes cleanly, which is why RADIUS is such a good teaching example.
Identification is the User-Name attribute, type 1. Authentication is User-Password, type 2, which is not sent in clear: RFC 2865 section 5.2 hides it by taking the MD5 hash of the shared secret concatenated with the Request Authenticator and exclusive-ORing the result with the password, sixteen octets at a time, chaining forward through longer passwords. Authorization is everything that comes back inside the Access-Accept: Service-Type (type 6), Framed-IP-Address (type 8), Session-Timeout (type 27), Class (type 25), Vendor-Specific (type 26). Accounting is RFC 2866: Acct-Status-Type (type 40) with values Start (1), Stop (2), Interim-Update (3), Accounting-On (7) and Accounting-Off (8), carrying Acct-Session-Id (44), Acct-Session-Time (46), Acct-Input-Octets (42), Acct-Output-Octets (43) and Acct-Terminate-Cause (49).
A single successful login looks like this.
NAS -> server Access-Request
User-Name = "anita"
User-Password= (hidden, 16-octet blocks)
NAS-IP-Address = 10.4.0.7
NAS-Port = 22
server -> NAS Access-Accept
Service-Type = Framed-User
Framed-IP-Address = 10.9.3.44
Session-Timeout = 3600
Class = (opaque handle)
NAS -> server Accounting-Request
Acct-Status-Type = Start
Acct-Session-Id = "0000A1F4"
Notice what the Access-Accept contains. It does not say “yes, this is Anita”. It says “yes, and give her address 10.9.3.44 for one hour”. The answers to the second and third verbs are in the same packet, and the access server cannot have one without the other. That is convenient, and it is why RADIUS cannot express “genuine user, no service today” except as a flat Access-Reject.
RADIUS has an important dated caveat. Its integrity protection is built on MD5, and in July 2024 that came due. CVE-2024-3596, published on 9 July 2024 with a CVSS version 3.1 base score of 9.0, described as critical, states that RADIUS under RFC 2865 “is susceptible to forgery attacks by a local attacker who can modify any valid Response (Access-Accept, Access-Reject, or Access-Challenge) to any other response using a chosen-prefix collision attack against MD5 Response Authenticator signature”. The attack is known as BlastRADIUS. In plain terms: an attacker positioned on the path can turn a reject into an accept.
The mitigations are the Message-Authenticator attribute, type 80, defined in RFC 2869 of June 2000, which is an HMAC-MD5 over the whole packet keyed with the shared secret, and moving RADIUS onto TLS. Standards work is live rather than finished: as of August 2026 the IETF document “Deprecating Insecure Practices in RADIUS”, which mandates support for TLS-based transports, is still an Internet-Draft, at version 10 dated 3 July 2026, and has not been published as an RFC. Treat plain-UDP RADIUS across any untrusted path as broken.
Diameter, and result codes that get it right#
Diameter was designed to replace RADIUS. The name is the industry’s joke about its predecessor, twice the radius, and the specification never explains it. The base protocol is RFC 6733, October 2012, by Victor Fajardo, Jari Arkko, John Loughney and Glen Zorn, which obsoleted RFC 3588 and RFC 5719. It runs over TCP or SCTP on port 3868, and unlike RADIUS it does not treat transport security as optional.
Diameter is where the terminology of this chapter is written down most crisply. Its terminology section defines authentication as “the act of verifying the identity of an entity (subject)”; authorization as “the act of determining whether a requesting entity (subject) will be allowed access to a resource (object)”; and accounting as “the act of collecting information on resource usage for the purpose of capacity planning, auditing, billing, or cost allocation”. Three sentences, three verbs, no overlap.
Messages carry a command code and a set of attribute-value pairs. An AVP has a four-octet AVP Code, an eight-bit flags field including V for vendor-specific and M for mandatory, and a three-octet length.
| Code | Abbreviation | Meaning |
|---|---|---|
| 257 | CER/CEA | Capabilities exchange |
| 258 | RAR/RAA | Re-authorize |
| 271 | ACR/ACA | Accounting |
| 274 | ASR/ASA | Abort session |
| 275 | STR/STA | Session termination |
| 280 | DWR/DWA | Device watchdog |
| 282 | DPR/DPA | Disconnect peer |
The detail worth carrying away is the Result-Code AVP, code 268. Diameter distinguishes the two failures that HTTP muddles, and it puts them in different error classes.
| Value | Name | Class |
|---|---|---|
| 2001 | DIAMETER_SUCCESS | Success |
| 4001 | AUTHENTICATION_REJECTED | Transient |
| 5003 | AUTHORIZATION_REJECTED | Permanent |
| 5012 | UNABLE_TO_COMPLY | Permanent |
Value 4001 is authentication rejected and sits in the 4xxx transient failure range, meaning try again with something better. Value 5003 is authorization rejected and sits in the 5xxx permanent failure range, meaning do not bother. That is exactly the 401 and 403 distinction, with the retry semantics built into the numbering. If you ever need to convince a colleague that the distinction is real engineering rather than vocabulary policing, show them these two numbers.
Diameter did not replace RADIUS in general practice. Its deployment is concentrated in mobile core networks, where it carries the signalling for subscriber authentication and charging, while RADIUS remains the protocol of enterprise wireless and wired network access. Both are current as of August 2026.
TACACS+, and the protocol that really does separate them#
There is one widely deployed protocol that treats the three verbs as three independent exchanges, and it is worth knowing because it shows both the benefit and the trap.
TACACS+ is documented in RFC 8907, September 2020, an Informational publication by Thorsten Dahm, Andrej Ota, Douglas Medway Gash, David Carrel and Lol Grant, describing a protocol Cisco had been shipping for decades. It runs over TCP port 49. The specification says it plainly: “The separation of authentication, authorization, and accounting is a key element of the design of TACACS+ protocol. Essentially, it makes TACACS+ a suite of three protocols.”
This is why network engineers use it for device administration. Because
authorization is a separate exchange, a TACACS+ server can be asked
about each individual command a technician types, and can allow show interface while refusing configure terminal, with a separate
accounting record for each. RADIUS cannot express that, because its
authorization arrives once, glued to the login.
Now the trap, in the specification’s own words: “Note that there is no provision made at the protocol level to associate authentication requests with authorization requests.”
Read that carefully. The protocol separates the verbs so thoroughly that it does not bind them back together. An authorization request arrives carrying a username; nothing in the protocol proves that this username was ever authenticated in this session. The binding is left to the implementation and the network. RFC 8907 is also candid that its packet protection “would be best referred to as ‘obfuscation’ and not ‘encryption’, since they provide no meaningful integrity, privacy, or replay protection”, and recommends running it inside a secured transport.
The lesson generalizes well beyond TACACS+. Separating the three verbs is necessary and it is not sufficient. Something must carry the result of the second verb into the third, and if that something is a username in a field, you have built a confused deputy.
The worked example: one passenger, three questions, real fields#
Let us take Anita Rao through the airport again, in exact terms.
The flight is invented so that nothing here can be mistaken for a real timetable: carrier designator ZZ, flight number 0118, Bengaluru (BLR) to London Heathrow (LHR), on 17 August 2026. The airport codes are real, the airline is not.
Question one, identification. At check-in Anita gives her booking reference, QK4T2P. This is the operating carrier’s passenger name record locator, a six-character alphanumeric string. It is an identifier in the sense of chapter 2: it points at exactly one booking inside one airline’s reservation system for a limited period. The search is one-to-many over that day’s departures, but because the locator is machine-assigned and unique, it returns exactly one row. Had she given only her name, the same search would have been one-to-many over human names, with the properties we described earlier.
Question two, authentication. The agent inspects her passport, checking its physical security features and, at many airports, reading its chip according to ICAO Document 9303, the machine-readable travel document specification. The face is compared with the stored image: one live face, one reference image, a one-to-one comparison. Chapter 6 covers what a document proves and chapter 20 covers face matching.
Question three, authorization. She is issued a boarding pass. The barcode encodes the IATA Bar Coded Boarding Pass format, standardized in 2004 as Resolution 792 by the IATA Passenger Services Conference. The mandatory section is exactly sixty characters. Paper passes use the PDF417 symbology; mobile passes use Aztec, Data Matrix or QR.
Here is her pass, first as encoded, then with the field boundaries marked and wrapped across two lines to fit this page.
M1RAO/ANITA EQK4T2P BLRLHRZZ 0118 229Y014C0043 100
M|1|RAO/ANITA |E|QK4T2P |BLR|LHR|ZZ |0118 |229|
Y|014C|0043 |1|00
| Field | Size | Anita’s value |
|---|---|---|
| Format code | 1 | M |
| Number of legs | 1 | 1 |
| Passenger name | 20 | RAO/ANITA |
| E-ticket indicator | 1 | E |
| Carrier PNR code | 7 | QK4T2P |
| From airport | 3 | BLR |
| To airport | 3 | LHR |
| Carrier designator | 3 | ZZ |
| Flight number | 5 | 0118 |
| Date of flight (Julian) | 3 | 229 |
| Compartment code | 1 | Y |
| Seat number | 4 | 014C |
| Check-in sequence | 5 | 0043 |
| Passenger status | 1 | 1 |
| Variable field size | 2 | 00 |
Those sizes add to sixty. The date is the Julian day of the year: the seventeenth of August, 2026 is day 229, since 2026 is not a leap year. Field lengths are fixed, so short values are padded with spaces.
Now the three observations that make this example worth the space.
First, the sixty mandatory characters contain no proof of anything. No photograph, no biometric, no key. The passenger name is a text string that anybody could type. This is a pure authorization token: it asserts a permission and nothing else.
Second, a digital signature is possible and optional. The BCBP standard provides security items — a type-of-security-data field and a signature field — in the conditional section following the mandatory sixty characters. They are not required, and a pass issued without them is text that happens to be printed as a barcode. Anyone can generate a plausible one; the control is that the gate reader checks the pass against the departure control system, not that the barcode is unforgeable.
Third, the audit record generated at the gate references the PNR, the reader and the outcome, and never mentions the passport. The system can prove that a pass for seat 14C was scanned and accepted. It cannot prove, from that record alone, that the person holding it was Anita Rao. If that binding matters, it must be captured where it happens, at question two, and carried forward. Systems that do not carry it forward discover the gap during an investigation, which is the worst time.
| Verb | Answered by | Failure at the airport |
|---|---|---|
| Identification | PNR QK4T2P | Wrong booking retrieved |
| Authentication | Passport check | Impostor or false refusal |
| Authorization | BCBP barcode | Boards a seat not paid for |
| Auditing | Gate scan log | Cannot reconstruct events |
The confused deputy#
In October 1988 Norm Hardy, then senior architect at Key Logic, published a three-page paper in ACM SIGOPS Operating Systems Review, volume 22, issue 4, pages 36 to 38. It is called “The Confused Deputy (or why capabilities might have been invented)” and it is the best short paper in this subject. Hardy opens by saying it is “a nearly true story (inessential details have been changed)” and that the events happened about eleven years earlier at Tymshare, a commercial timesharing company, which places them around 1977.
Here is what happened, in Hardy’s own terms.
A FORTRAN compiler lived in a directory called SYSX. Users ran it by
typing RUN (SYSX)FORT, and they could supply the name of a file to
receive optional debugging output. The operators had instrumented the
compiler to collect statistics about which language features were being
used, and those statistics were written to a file called (SYSX)STAT. So
that the compiler could write that file, they marked the compiler itself
with home files license, a privilege that let a program write files
in its own home directory.
Also in SYSX was the billing file, (SYSX)BILL.
A user learned the name (SYSX)BILL and supplied it as the debugging output filename. The compiler passed the name to the operating system. The operating system saw that the compiler held home files license, allowed the write, and the billing information was destroyed.
Hardy then works through the fixes that do not work, and the sequence is worth following because engineers propose these in the same order. Refuse to write outside the user’s directory? Writing elsewhere is legitimate. Check for the directory name SYSX? That name did not exist when the code was written, and there are legitimate reasons to write into SYSX. Check for the name (SYSX)BILL? It is not the only sensitive file, and the compiler would need changing every time a file was added. He records that the rules for opening a file eventually required fourteen boolean operators.
Then the diagnosis, which is the sentence to memorize: “The fundamental problem is that the compiler runs with authority stemming from two sources. (That’s why the compiler is a confused deputy.)” The invoker lends authority when they type the command. The home files license grants separate authority. The compiler “serves two masters and carries some authority from each to perform its respective duties. It has no way to keep them apart.” When writing statistics it means to use its own authority; when writing debug output it means to use the caller’s. And, in Hardy’s words, “the compiler had no way of expressing these intents”.
Tymshare’s first fix was a system call to switch hats, selecting one of the two authorities explicitly. Hardy notes the increase in complexity, and that it broke down as soon as more than two authorities were needed.
The capability answer removes the ambiguity at the root. Instead of receiving a filename, the compiler receives a capability to the output file from its invoker, and holds a separate capability to the statistics file. In Hardy’s phrasing, “the capability both identifies the file and authorizes the compiler to write there”. There is no name to be misinterpreted, because designation and permission arrive as one object. A caller who cannot open the billing file cannot hand over a capability to it.
The general shape, stripped of its 1970s detail:
caller ------ names a resource -------> deputy
(no right to the billing file) |
| acts with
| its OWN right
v
resource
Two authorities, one request, no way to say
which one is meant. That is a confused deputy.
The name is the problem. When a request carries a name for a resource, the permission does not travel with it, and the receiving system silently substitutes the deputy’s permission for the caller’s. When a request carries a capability, permission and designation cannot be separated.
The confused deputy today, in four costumes#
Hardy’s bug did not stay in the 1970s. It is in the everyday failure modes of modern systems, and recognizing the shape matters more than memorizing any single instance.
Cross-site request forgery. A browser is a deputy. It holds your
session cookie for a bank, and it will attach that cookie to any request
to the bank, including one triggered by a page on an attacker’s site.
The attacker supplies the request; the browser supplies the authority.
The web application security literature has listed “confused deputy”
among the aliases of cross-site request forgery for years, and the term
CSRF is generally traced to a 2001 Bugtraq post by Peter Watkins. The
fix is to make the request carry something the attacker cannot supply —
an anti-forgery token, or the SameSite cookie attribute — which is a
capability bolted onto an ambient-authority design.
Server-side request forgery. A server that fetches an address supplied by a user is a deputy holding network authority the user lacks, including reach into internal addresses and cloud metadata endpoints. The user names the resource; the server supplies the right to reach it.
Cloud cross-account access. A monitoring vendor assumes a role in
your account to read your data, so it is a deputy holding authority in
many customers’ accounts. If another customer can name your account, the
vendor may act on your resources while believing it acts for them.
Amazon Web Services documents this as “the confused deputy problem” and
gives the answer: an sts:ExternalId condition in the role’s trust
policy, a value unique to each customer that the vendor must present,
and, for service-to-service cases, the aws:SourceArn,
aws:SourceAccount and aws:SourceOrgID condition keys. Each narrows
the deputy’s authority to the caller it is meant to be serving.
Tool-using software agents. An agent given tools and credentials is a deputy with a large standing authority, taking instructions from a channel — a document, a web page, a message — that somebody else may control. The shape is identical to Hardy’s, and so are the remedies: attenuate the authority per task, make the caller supply the right along with the request, and never infer the author of an instruction from the fact that the agent holds a credential. This is active engineering practice as of August 2026, not a settled discipline.
The underlying property has a name the capability literature settled on later: ambient authority. Authority is ambient when a program exercises it merely by being itself, without naming which right it invokes. Ambient authority is convenient, which is why every mainstream operating system and web framework has it, and it is precisely the ingredient that makes confused deputies possible.
A checklist you can run against your own system#
The three verbs are easy to state and hard to keep apart under delivery pressure. This review catches most of it.
- Name the three. For one endpoint, write one sentence each: how the subject is identified, how that claim is proved, and what rule decides the outcome. If a sentence is hard to write, that verb is implicit somewhere and is not being tested.
- Check the codes. Find every place your code returns 403 and ask
whether the caller was authenticated. If not, it should be 401 with a
WWW-Authenticatechallenge, or a deliberate 404. - Find the deputies. List every component that acts with more authority than its caller: background workers, service accounts, admin tools, integration credentials. Ask what stops each from applying its own authority to a resource its caller named.
- Follow the binding. When authentication happens in one place and authorization in another, find the object that carries the result between them, and ask what an attacker who could write it would gain.
- Read one audit record. Take a real log line for a denied request and check it against the six AU-3 elements. If you cannot tell which verb refused and why, it is not yet an audit record.
- Test the refusals. Most suites test that authorized users succeed. Assert the specific status code and reason for each way of being refused, because those paths regress silently.
3.98 Common wrong ideas#
Wrong: Authentication and authorization are two names for the same
thing, so auth is a fine name for the module. Right: They are
different operations with different inputs and different failure modes.
Authentication takes a claimant and an authenticator and returns a
subject; NIST SP 800-63-4 defines it as the process by which a claimant
proves possession and control of authenticators bound to a subscriber
account. Authorization takes a subject, an action, a resource and a
context, and returns allow or deny; the same document defines it as a
decision to grant access by evaluating a subject’s attributes. Code that
cannot say which one refused cannot be debugged.
Wrong: HTTP 401 means the user lacks permission. Right: It means
the request lacks valid authentication credentials for the target
resource, and RFC 9110 section 15.5.2 requires the server to send a
WWW-Authenticate header with at least one challenge. Lacking
permission with valid credentials is 403, defined in section 15.5.4,
where the specification states the client should not automatically
repeat the request with the same credentials. The status code’s
registered reason phrase, “Unauthorized”, is a naming accident that
dates to RFC 1945 in May 1996.
Wrong: Returning 404 instead of 403 is a hack. Right: It is
explicitly permitted. RFC 9110 section 15.5.4 allows an origin server
that wishes to hide the existence of a forbidden resource to respond
with 404 instead, and production systems rely on it. Amazon S3 documents
that a request for a missing object returns 404 if the caller holds
s3:ListBucket on the bucket and 403 if it does not, precisely so that
an unauthorized caller learns nothing about which keys exist.
Wrong: You must know who somebody is before you can let them do anything. Right: Capability-based authorization has worked since Dennis and Van Horn described it in Communications of the ACM in March 1966, and it is what a cinema ticket, a hotel key card, an S3 pre-signed URL and an OAuth bearer token all are. RFC 6750 states that any party in possession of a bearer token can use it in any way any other holder can, without proving possession of a key. The trade is real: you gain speed, offline operation and privacy, and you lose easy revocation and useful audit.
Wrong: Identification is a lookup that returns the right person. Right: It is a one-to-many search that returns candidates, and the error rate grows with the population. Senator Edward Kennedy was refused tickets repeatedly in 2004 because he shared a surname and first initial with a listed person; the Transportation Security Administration confirmed in July 2008 that he was on neither the no-fly nor the selectee list and had been misidentified. Treating a search result as a decision is how that happens.
Wrong: A confused deputy is a kind of privilege escalation bug in
old operating systems. Right: It is a structural property of any
program that holds authority from two sources and cannot say which one
it is using. Norm Hardy’s 1988 paper diagnosed it exactly that way, and
the same shape appears today as cross-site request forgery, server-side
request forgery, cloud cross-account access — which Amazon Web Services
names “the confused deputy problem” and answers with the
sts:ExternalId condition — and tool-using software agents.
Wrong: Separating authentication from authorization is enough to avoid the problem. Right: Separating them creates a new obligation: something must carry the proven subject from one to the other, and that carrier becomes the target. RFC 8907 makes this concrete, stating that in TACACS+ “there is no provision made at the protocol level to associate authentication requests with authorization requests”. The separation is correct and the binding is your responsibility.
Wrong: Logging is a non-functional requirement you add later. Right: Auditing is the fourth verb and it has a specification. NIST SP 800-53 control AU-3 requires six elements in every audit record: type of event, when, where, source, outcome, and the identity of the individuals or objects involved. PCI DSS requirement 10.2.2 asks for the same six in different words. The element applications habitually omit is the outcome, which makes the records useless for the only question anyone asks afterwards.
Wrong: RADIUS handles authentication and something else handles authorization. Right: RADIUS carries both in one exchange by design. RFC 2865 describes itself as carrying authentication, authorization and configuration information together, and an Access-Accept delivers the authorization attributes — Service-Type, Framed-IP-Address, Session-Timeout, Class — in the same packet that says the password was right. That is why it cannot express “genuine user, no service today” except as a flat reject, and why TACACS+, documented in RFC 8907, exists for per-command device administration.
Wrong: Once a user is authenticated, they are authenticated. Right: Authentication is an event at an instant, not a state. Every system that behaves otherwise is trusting a cached result — a session, a cookie, a token — for a chosen period, and is betting that nothing important changes inside it. The passport was checked at 09:15 and the gate scanned the pass at 09:52, and nothing re-asked in between. Chapters 36 and 30 are about that gap and how it is closed.
3.99 Chapter summary in 20 lines#
- Identification, authentication and authorization are three different operations, and running them together is the most common structural error in identity software.
- Identification is a one-to-many search over an enrolled population, and it returns candidates rather than a decision.
- Authentication is a one-to-one comparison between a claim and evidence bound to that claim in advance, so it is meaningless without a prior enrolment.
- NIST SP 800-63-4, published on 1 August 2025, defines authentication as a claimant proving possession and control of authenticators bound to a subscriber account.
- Authorization is a policy decision with four inputs: subject, action, resource and context, and the context input is the one systems forget and then bolt on.
- Authorization can run without identification, using capabilities, which Dennis and Van Horn described in Communications of the ACM in March 1966.
- Butler Lampson’s access matrix of 1971 shows why: read by row it is a capability list, read by column it is an access control list, and only the second needs to know who is calling.
- A boarding pass, a hotel key card, an S3 pre-signed URL and an OAuth bearer token are all capabilities, and RFC 6750 says plainly that any holder of a bearer token can use it as any other holder could.
- Capabilities buy speed, offline operation and privacy, and cost revocation and audit quality, because there is a token to trace and no subject.
- RFC 9110 section 15.5.2 says 401 means the request lacks valid
authentication credentials and requires a
WWW-Authenticatechallenge in the response. - RFC 9110 section 15.5.4 says 403 means the server understood and refuses, that provided credentials are considered insufficient, and that the client should not retry with the same credentials.
- The reason phrase “Unauthorized” on 401 and the request header named
Authorizationare naming accidents dating to RFC 1945 of May 1996, and they have taught three decades of developers the wrong pairing. - RFC 6750 section 3.1 gets the mapping right for OAuth: invalid request is 400, invalid token is 401, insufficient scope is 403.
- Auditing is the fourth verb, and NIST SP 800-53 control AU-3 requires six elements — type, when, where, source, outcome, and the identities involved — with PCI DSS 10.2.2 asking for the same six.
- RADIUS, first published as RFC 2058 in January 1997 and current as RFC 2865 of June 2000, deliberately carries authentication and authorization in one exchange, with the authorization attributes inside the Access-Accept.
- RADIUS integrity rests on MD5, and CVE-2024-3596, published on 9 July 2024 with a CVSS 3.1 base score of 9.0, showed a response can be forged from reject to accept.
- Diameter, RFC 6733 of October 2012, defines the three verbs separately and encodes the distinction in its result codes: 4001 is authentication rejected and transient, 5003 is authorization rejected and permanent.
- TACACS+, documented in RFC 8907 of September 2020, genuinely separates the three, and warns that nothing at the protocol level associates an authorization request with an authentication request.
- Norm Hardy’s “The Confused Deputy”, ACM SIGOPS Operating Systems Review volume 22 issue 4, October 1988, diagnosed the failure that occurs when a program holds authority from two sources and cannot say which it is using.
- The confused deputy is alive in cross-site request forgery, server-side request forgery, cloud cross-account roles and tool-using software agents, and the 1988 answer still works: make the request carry the right, not just the name.
Chapter sources: RFC 9110, “HTTP Semantics”, June 2022, Fielding, Nottingham and Reschke, sections 15.5.2 for 401 Unauthorized, 15.5.4 for 403 Forbidden, 15.5.5 for 404 Not Found and 11.6.1 and 11.6.2 for the WWW-Authenticate and Authorization header fields; RFC 1945, “Hypertext Transfer Protocol -- HTTP/1.0”, May 1996, Berners-Lee, Fielding and Frystyk, for the original 401 and 403 definitions and the Authorization header in section 10.2. RFC 2865, “Remote Authentication Dial In User Service (RADIUS)”, June 2000, for packet codes, the 1812 port assignment, the 20 to 4096 octet length range and the section 5.2 password hiding construction; RFC 2866, “RADIUS Accounting”, June 2000, for Acct-Status-Type 40 and the accounting attributes; RFC 2869, “RADIUS Extensions”, June 2000, for the Message-Authenticator attribute type 80; RFC 2058, January 1997, as the first RADIUS publication; CVE-2024-3596 as published by the United States National Vulnerability Database on 9 July 2024, CVSS version 3.1 base score 9.0, for the BlastRADIUS chosen-prefix MD5 collision attack; and the IETF document “Deprecating Insecure Practices in RADIUS”, draft version 10 dated 3 July 2026, which remained an Internet-Draft as of August 2026. RFC 6733, “Diameter Base Protocol”, October 2012, obsoleting RFC 3588 and RFC 5719, for the terminology definitions of authentication, authorization and accounting, the command codes, and Result-Code values 2001, 4001, 5003 and 5012; RFC 2904, “AAA Authorization Framework”, August 2000, for the IETF’s AAA architecture work. RFC 8907, “The TACACS+ Protocol”, September 2020, for the separation of the three functions, TCP port 49, and the statements that no protocol-level provision associates authentication with authorization and that its packet protection is obfuscation rather than encryption. RFC 6750, “The OAuth 2.0 Authorization Framework: Bearer Token Usage”, October 2012, for the bearer token definition and the section 3.1 mapping of invalid_request, invalid_token and insufficient_scope to 400, 401 and 403. Norm Hardy, “The Confused Deputy (or why capabilities might have been invented)”, ACM SIGOPS Operating Systems Review, volume 22, issue 4, October 1988, pages 36 to 38, for the Tymshare compiler, the SYSX directory, home files license and the two-authorities diagnosis; Jack B. Dennis and Earl C. Van Horn, “Programming Semantics for Multiprogrammed Computations”, Communications of the ACM, volume 9, number 3, March 1966, pages 143 to 155, for the capability; Butler W. Lampson, “Protection”, Proceedings of the Fifth Princeton Conference on Information Sciences and Systems, March 1971, pages 437 to 443, reprinted in ACM Operating Systems Review, volume 8, number 1, January 1974, pages 18 to 24, for the access matrix; Birgisson, Politz, Erlingsson, Taly, Vrable and Lentczner, “Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud”, Network and Distributed System Security Symposium, 2014. NIST Special Publication 800-63-4, “Digital Identity Guidelines”, published 1 August 2025, for the definitions of authentication, authorization, identity proofing, claimant and subscriber; NIST Special Publication 800-53 Revision 5, control AU-3 “Content of Audit Records” and its supplemental guidance, and control AU-9 on protection of audit information; PCI DSS requirement 10.2.2 as stated in the Payment Card Industry Security Standards Council’s self-assessment questionnaire documentation; ISO/IEC 2382-37:2022, the biometrics vocabulary, for the one-to-one and one-to-many distinction. IATA Resolution 792, the Bar Coded Boarding Pass standard approved by the Passenger Services Conference in 2004, and the IATA BCBP Implementation Guide, for the sixty-character mandatory section, the field sizes, the PDF417 symbology and the optional security items; ICAO Document 9303 for machine-readable travel documents. Amazon Web Services IAM User Guide, “The confused deputy problem”, for sts:ExternalId, aws:SourceArn, aws:SourceAccount and aws:SourceOrgID, and the Amazon S3 API Reference entry for GetObject for the 404 and 403 behaviour that depends on the s3:ListBucket permission, both as of August 2026; Django REST Framework documentation on unauthorized and forbidden responses. Washington Post, “Sen. Kennedy Flagged by No-Fly List”, 20 August 2004; Senator Edward Kennedy’s account at a Senate hearing on 19 August 2004; and the Transportation Security Administration’s “myth buster” post of July 2008 correcting the record and describing the Traveler Redress Inquiry Program. The attribution of the term cross-site request forgery to a 2001 Bugtraq post by Peter Watkins follows the Web Application Security Consortium’s threat classification.