2 weeks ago Donovan and I were at RSA, manning the Geneva booth: the interest about this technology is overwhelming, as well as the enthusiasm for the claims based approach.
Now that there’s actually something to toy with, as opposed to hand-weave how beautiful a claims-flavoured world would be, I distinctly felt a change in the kind of questions I get: more pragmatic, aimed at understanding how to solve specific *practical* (as opposed to hypothetical) problems or how to integrate with existing assets. One thing that really surprised me is how difficult it could be for people to understand what to put in claims, or who is supposed to add what/where, and so on. There is surprisingly little in literature about this: or rather, this should not surprise at all since the tools that would enable the industry to even pose the question are emerging just now.
So, after so many practical/basic posts lately here there’s some scatter consideration about what should go into claims. I meant to write this post since really long, and I don’t actually have enough time to do a thorough job today… however tomorrow there’s the 2nd day of the EIC and I don’t want to risk hearing something like this from somebody else, it would not be the first time that I just waited too long 🙂 PLEASE NOTE: that’s mainly meant to stimulate thought and discussion, remember that I not in the product unit team hence whatever i write here may have nothing to do with the product whatsoever. You can hear the Voice of the product group here.
What is a claim (again?!)
A claim is a statement made by one entity about another entity. I guess you heard this ad nauseam, did you (if you didn’t have enough of that already, try this, this , this this this this and this. Am I obsessed with claims or what? 🙂 they’re awesome).
You can derive practically all the good claim’s properties from this simple definition, which is amazingly elegant per se, however it may not prove especially helpful in deciding WHAT you should put (or expect) in the claims, WHO should worry about it, WHERE in the architecture you should plan to emit, transform or consume claims; and so on. As I like to say, moving to a claims-based approach is a bit like moving from Roman numbers to Arabic ones with zero: now that we got the point about the notation and we are even getting calculators, it’s time to actually do some applied math.
Let’s think for a moment about the WHAT. Without getting in philosophy like in the coarse claim taxonomy post, can you list the type of info you can put in a claim? “Personal” attributes like name or birthdate, “contextual” attributes like group or role membership (which is in the context of the user’s home realm, for example), permissions/privileges like Read or Invoke, an so on. This is by no mean an exhaustive taxonomy, it is meant as well to stimulate somebody smarter than me to actually come out with a good one; anyway if the interest for this keep raising at the current pace we’ll soon have even too many classifications. OK, fine. A claim can be all of those things, and more.
User or Resource?
If an entity (A) needs to make a statement about another entity (S), one would hope that (A) knows what it is talking about! If the claim is a user attribute, PII for example, one would assume that in general the issuing authority knows more or less directly about the user: that’s something you’d observe in the most classic examples of identity providers. If the claim is instead a permission on a specific resources, write access to a file for example, it’s clear that whoever issued that claim 1) knows about the existence of the resource 2) knows about which kind of permissions apply to that resource (“invoke” applies to a webmethod, but makes no sense for a DB table) 3) is authoritative about how such permissions are assigned to which resources, or it is a very good friend with somebody who is. Doesn’t that look like some kind of range to you? Let’s put it in picture:
Well, not especially illuminating but that’s the base form where we’ll do our next step.
When a user tries to gain access to a resource, his/her call will traverse one or more boundaries and the call may be enriched by one or more authorities, which will add claims on the way. The simple picture above gives you a heuristic about the kind of claims you can expect from such authorities depending on how close they live to the two extremes of the spectrum. Let’s make a more detailed sketch.
Waaay more detailed! Let’s start from the user and move outward:
- Account. That’s the very first thing: the bare minimum we can know is that a user is indeed one of ours. This does not even need to be an explicit claim, just being able to exhibit a token from a certain auth should be enough to assert this. Whoever controls the account authentication can source this.
- “personal” attributes. Let’s say that you have an application that associates a profile of some sort to its accounts: it could be a website, sure, but it could also be a packaged product which live in a domain but is really not very well integrated in the directory. Anyway, that’s the right place from where we can obtain claim values which represent user attributes
- Attributes at the user’s org level. If the user does not live in isolation in an application credentials store, but is in fact belonging to a domain, then he/she will probably have attributes that are associated to other artifacts in such domain: it can belong to a group, be assigned a role and so on. All the user attributes which make sense in the context of his/her org can be sourced here. The tricky part here is – what is “the user’s org”? It is tempting to think of it as the entire directory, and many many times it will be accurate: however you can imagine scenarios in which departments have their own roles (ie Finance may have an Auditor and HR may have a Generalist, and the two do not make sense outside of their original divisions) hence here you’d have 2 concentric rings instead of one; and so on.
- Federation settings. This is the layer which is aware of federated partners: at the extreme boundary of the org there are the settings that describe which info can leave the organization, under which name, and toward whom. In the end, whatever info has been bubbling up through the inner levels will or will not go through according to the settings here, and with the format (including claim’s name) imposed here. The boundary line is dashed here, because this is one level that is somewhat visible & approachable from the outside (via metadata exchange, for example) whereas the internal layers are not (or SHOULD NOT) directly accessible to the outside without violating some good architecture rule (duplicating data or giving out of band access)
Before we move to examine the resource, I would like to point out something: the various layers do not necessarily communicate with each other via claims. In fact you may have a geneva server that handles the federation settings, which takes care of authenticating calls (if the “account” lives in AD) and sources claims both from AD itself (attributes at the user’s org level) and arbitrary stores: in this case, the first time in which the info above is packaged in form of claims is in the outermost layer. However you could also imagine that the account and personal attributes would be kept in a LOB app not integrated with the directory, in which case you may have an inner STS “wrapping” account and personal attributes, which would then be transformed/extended with org attributes by the federation settings layer (which has access to the org attributes layer directly). I guess you can combine the above in as many ways as you want.
Now, inward to the resource:
- Federation settings. Same as the one around the user’s org, this time in the receiving role. This is where you would apply transformations between incoming claims and whatever claim type makes sense in the inner levels. However, consider the picture below:
Usually you will have many resources, some of them sharing permissions info (maybe they belong to the same app), some of them not; furthermore you may have multiple organization boundaries per the department considerations above, though i spared you the picture of that. That does not look like something that would be really agile to maintain from a central location such as the federation settings layer: probably the mappings you can expect to do here will be coarser than sheer permissions.
- Attributes at the resource’s org level. Here you can expect to find knowledge about the groups & roles which make sense in the local organization; note that this layer has NO CLUE about how to handle foreign claims, all it expects are local groups or roles. Expecting otherwise would, again, lead to violations of boundaries and duplications. It’s the job of the outer layer to make sure that the relevant transformations take place outside. Note: the org progression here could and will be more complex. Just think of how many applications have their own roles: contributor makes sense for a content management system, but doesn’t work as clearance description for an app protecting confidential documents. Modeling such app-specific roles can be made by adding an “org” boundary.
- Permissions. This is the layer in which the kind of permissions admitted by one (or more) resource(s) are known, and the criteria in which they are assigned is known too. Here things can get a bit confusing. Let’s say that there is a call coming from the outer layer with “contributor” role: how does that map to permissions? Do I have to explicitly emit a “CanUpdate” permission claim for every resource in my scope? Remember what we said before: we don’t need to communicate via claims through layers. If our permissions layer can understand and enforce Contributor, then we are done. If it doesn’t, then we have to convert it when crossing the boundary into appropriate permissions/privileges. Here there’s the interesting consideration about how those privilege claims are associated with the actual resource, but i’ll leave this for later
- Resource. If we arrived here, this means that we managed to do all possible checks & external transformations. Interestingly enough, we may not be done yet: we may have specific info (such a PROFILE) that we may want to use to extend the incoming identity. Example: the last 10 books you bought at an online book store are one info that the store will not receive from the outside hence at least conceptually you may imagine they’d add it at the resource level (though personally I’d add those info in the context as soon as a user arrives in, but that’s in the case in which the resource is “very big” in respect to the rest of the org)
Let’s see a little example:
Here we start from account. In the first layer we extract the info about the user Name; in the second layer we find out the group, and in the third we extract a role associated to that group. Role and Name are sent in form of claims, while group was juts an intermediate step and account is implicit (see the beginning of the post).
The resources’ federation layer verifies that the uer belongs to a partner org (via “account”), maps the incoming role in a role that makes sense in the resource’s org, rewrite the name claim; then it maps the transformed role in the corresponding set of permissions, and dispatches the name claim unchanged. Finally the resource itself uses the name claim for retrieving a preference, “font size”.
Now, I ack that all this may not be terribly useful but it seems to me that it can at least stimulate your thoughts about which info flow where, and why.
Just for fun, let’s apply the model to well known scenarios. For example, in the case in which account and resource belong to the same organization:
Seems in line with observation. In fact, the issues we had pre-federation were there because people generalized this instance in the wrong way:
Duplicating the account and personal attributes info allowed all the transformation chains on the resource side to be preserved, at the price of duplicating accounts. Now we know better and we federate. Beware, though! While this is an obvious error when we think of users, when we consider resources we may do exactly the same mistake in mirror image. For example, if you would want to issue privilege claims directly from the user’s org you’d have something like the following:
If we would want the user’s org to be able to issue directly permissions, the user org would need to know a lot of things it does not really own: mainly permission types/values and which permissions apply to that specific resource. That is the equivalent of duplicating info about the resource in the user’s org! This is as bad as duplicating users in pre-federation situations: actually worse, since the resources are usually more volatile than the accounts.
OK, it’s 2:26am and I *really* need to go to sleep. There’s still a crazy amount of things I’d like to say about sourcing claims, especially around how developers and sysadmins should talk to each other (or not) and about discoverability; we’ll touch on those in some later post.