Validation, Authentication, Authorization: mangling tokens for your dark purposes
Flying back from S.Diego, after attending a great edition of Catalyst. I should probably write down my impressions before they fade, like it happened with the IIW, but there’s in fact something (only mildly related) that bugged me for quite some time and I just want to flush it out of my system before going in vacation (somehow I feel that my old time Italian friends would not appreciate me blabbering about tokens, especially if I do it with my mouth full of focaccia al formaggio :-)).
Ok, the story is somewhat similar to the “credentials are not identities” and returning user woes discussed in the Tao of authentication: it’s a matter of agreeing on the semantic of terms that in the pre-token era had a simpler meaning, but that today need a richer/more rigorous definition. In summary: in practice, what RPs and STSes are supposed to do with incoming tokens?
The answer lies in asking ourselves why we asked for a token in the first place. Perhaps the RP wants to see if the subject is allowed to sign in and start a session; an STS wants to know if the subject is worthy of being issued with the token he is requesting; and again, the RP may want to verify the the user has the necessary rights for performing a certain action (one may argue that this is a generalization of the signin case; I sort of agree, but later I’ll make things more complicated). Even if we’d live in a world fueled only by shared secrets, there would be different cases to handle. If the RP is a simple password-protected file, verifying that the subject knows the password would suffice; no user store to look up, no identity (hence the term blind credentials). Would you call that “authenticating the user”? I wouldn’t, because in that case there’s no user to speak of; or perhaps I would, since in fact all possible users are divided in 2 big categories: the ones who know THE password (singular), and the ones who don’t. If you want, it’s like with earthworms: there are many of them, but they’re all identical down to the cellular level hence you could say that there is only one earthworm (I suspect I am getting confused with some other species, but you get the idea). And so much for my promise of being more concrete.
If the RP is something slightly more complicated, like pretty much any website that grants some degree of customization or resources that are associated to specific users (think mailbox), all of the sudden we have to handle a list of username-password couples; that entails FIRST to look up if the incoming username exists in the list, THEN if the provided password happen to match with the corresponding one the list (hey kids, don’t store passwords in clear 🙂 this is just pour parler). As I argued in one Tao, the lookup & password check are TWO distinct actions and in this case they just happen to be conflated in a single movement given the nature of the credential mechanism (shared secret). I won’t bore you with a detailed historical analysis of how things went that way; let’s just say that overloading the username (mnemonic moniker often used for human interactions, such as chat nickname) with the function of index for the user database happened to be the path of least resistance, but it could have gone in a different way. For example, the fact that the username must be unique is a consequence of that conflation but should not be assumed as the only possible practice. Just imagine if in real life we would be forced to have unique names: I would *really* not be thrilled to be called Vittorio_12345, and neither would you. When institutions needed to associate a record with me, they just created an index for the purpose; codice fiscale, social security number, costco membership number… all stuff that can be used as part of the credential mechanism, and that should not circulate beyond that purpose (just think of the horrible mess of having a number of institutions all deciding to use the SSN as the key for locating your record; welcome to unintendedconsequencesland).
Now that we see that there’s no spoon, we can move to consider serious tokens (the ones with decent crypto capabilities). Tokens have this interesting <claims list-credentials> dual nature, which makes them handy for rewriting a better physics of identity but also offers more opportunities for confusion. Let’s consider a website RP that requires for signin a token as follows: SAML 1.1 format, issued by http://myissuer, containing the claims http://…/age and http://…/PPID (for the sake of argument, let’s say that the RP accepts only users who signed up at a certain moment in the past: for signing in, you must be a returning user. This makes our scenario closer to the familiar case, but later we’ll relax this assumption and venture in uncharted territory).
The incoming token is the material component of our credential verification mechanism: what do we need to do for ensuring that we should let the user in? Let’s try a (incomplete) list:
- check that it is a valid (well formed) SAML 1.1 token
- check that the signature is still OK (nobody tampered with it)
- check that it contains the 2 claims we asked for (http://…/age and http://…/PPID)
- check that the issuer is http://myissuer
- lookup in the DB the value in the http://…/PPID claim
If all checks work OK, we can let the user in. As I mentioned, this is really incomplete (where is AudienceRestriction?) but it is enough to make a couple of observation. For example:
- 1. and 2. are operations that we can perform regardless of the context (or better, even before getting to know that there is a context). It’s a bit like asking a jeweler to estimate if the stone you have is a diamond: he can do that even if he doesn’t know what you want to do with the diamond. In fact he really does not care if that’s an appropriate gift for a 20 years anniversary, all you can expect from his estimate is “this is a fine stone, worth X” or “sorry, this is no diamond”.
- 3. and 4. are associated with a context, those are requirements we are imposing; nonetheless, they still seem to have to do with well-formedness. If 1 and 2 are the moral equivalent of verifying that an XML doc is valid XML, 3 and 4 are the moral equivalent of verifying that it matches a schema; still something we can expect the infrastructure to lend a hand, but the responsibility of providing the requirements is on us.
- 5 is something that is really dependent on our infrastructure. Here we have chosen the PPID; we may have chosen the email as well. Furthermore: this operation can be independent from the token structure, or even from the fact that the value we lookup has been received in form of claim (provided that you keep claims separated from credentials).
How to tie the sequence above to the title of the post? I think we can have a lot of arguing here (trust me been there, done that :-), so I’ll go straight to my take:
- I would call 1 and 2 validation. Those are the steps that just verify that the caller is respecting the game rules of the specific credentials technology we are using. Is this a well formed, non tampered SAML? Is this X509 token a projection of a cert that was not revoked?
- I would call 3, 4 and 5 authentication. Why? Because those are the info I need for determining if the subject belongs to the category I am interested into. In this case, the category I am talking about is users that are able to obtain from http://myissuer tokens containing http://…age and http://..PPID, and that used such a token in the past to sign up with me
I should be able to expect the validation to be performed entirely by the infrastructure. I should expect significant help from the infrastructure for the authentication operations, too, but i have to be prepared to do my part and at a minimum describe the category I am interested into.
Now: let’s say that I want to relax the condition that imposes the subject to be a returning user; as long as you can present a token with the right features & from the right issuer, I’ll do business with you even if I never saw you before. That models much more closely what happens in meatspace, I don’t see bartenders searching for my name in a huge phonebook-like tome when I ask for a gintonic: who cares if I showed up before, or if I’ll never go back there? Anyway, the above sequence still works beautifully: we just get rid of step 5. And finally this allows me to close the circle. When you use passwords, looking up the moniker-password couple in the database seems like a validation because of the nature of the credential mechanism: but if we’d extend that view to other token types, we’d lose the separation of concern that we achieved by having the validation as a context free operation and the authentication as something driven by our requirements. And doing that would be equivalent to build a geometry model of triangles that’s biased toward the case of segments as degenerate triangles: we should have a theory that correctly predicts the behavior of triangles even in the degenerate case in which they are a segment, but IMHO it is a mistake to assume that every triangle is a segment and then struggle for predicting its behavior. OK, that was really abstract, but I hope you see what I mean; i understand the need of forcing username/password credentials in the tokens system, despite their lame single claim (username; which IMHO is not even a valid claim, since it is part of the cred mechanism and non-descriptive, but ignore this last parenthesis), but I am always worried when its special characteristic are generalized beyond their boundaries.
I started writing this on the flight from S.Diego to Seattle, and I am finishing it from the NW lounge in Seattle waiting for my flight to Paris (and the Genova: vacation!!!). In 20 mins I have to board, so I have to wrap up. I purposefully left out authorization, because it deserves a post (actually, many) by itself: anyway, let me add one small thing about it. Once could say that the value of the claim age is something that influences the ability of a subject to sign in and start a session, hence thta would belong to the authentication realm; OTOH you could also think that starting a session is an operation by itself, and as such it needs to be authorized. For that reason I would advocate that the validation-authentication sequence above is unchanged, and the check of values of claims would be performed at a later stage of the pipeline that takes care of authorization. That would allow you to reuse exactly the same pipeline even when you are asking for a token for authorization reasons, as opposed to starting a session (think home banking application, which asks for a certain token for starting a session and prompts for another token with higher assurance levels just for authorizing a certain operation beyond a given threshold). However for this last part I am more malleable and happy to discuss, that’s a complicated space and there’s still a lot to be figured out.
Alright, vacation time! I’ll probably still write something on the plane, but in general I won’t be too active in the next 2 weeks: be patient if your comments don’t show up immediately or I won’t respond to comments quickly. 😉
2 Comments