Design Principles for Seamless User Authentication

This post was originally published as “Design Principles for Seamless User Authentication” on the Apigee Blog.

In a previous post, we discussed the recommended approaches to dealing with multiple user communities. To recap, they are (in order of preference):

  • Common technology in an identity stack with a single federation server and a separate user repository for each user repository
  • A single federation server that can communicate across a variety of user repository instances and technologies (LDAP and Active Directory, for example)
  • A single federation server that has established federation relationships across other federation servers that can access the user repository(ies) for the target user communities
  • Out-of-the-box functionality that allows for accessing multiple LDAP repositories or active directory domains
  • Functionality implemented through custom code

The rise of the standards-based approach

If I was writing this ten years ago, most of the conversation would have been centered around the LDAPS protocol. Since then, WS-Trust and OAuth2/OIDC have come along to provide a standards-based approach for any system actor to communicate with the identity stack. Even a decade ago, SPNEGO, SAML2 Browser Profile, and similar mechanisms existed, but these had nowhere near the market penetration and standardization in product feature sets that they do today. All of those tended to be focused on web app SSO only.

In 2005, the gold standard for web app SSO was SPNEGO, which was a Microsoft-developed standard supported by Internet Explorer. On Jan. 1, 2005, IE had 90.31% market penetration for web browsers; this generally worked for most parties at the time — though, this was just about the peak of IE market penetration :). SPNEGO tended to have interoperability problems outside of the Microsoft technology stack.

Token transformation

If an API provider doesn’t have the capability to have the end user passed to it in the form of an identity token, then it’s likely that some type of generic service account is provided that has the appropriate permissions to perform whatever tasks are required on behalf of the original calling identity. Replacing the caller’s identity token with the service account’s username and password in the HTTP authorization header is an example of a very common security integration pattern called token transformation.

In this situation, the service account will have to be placed into one of the user repositories described above. If this API provider only processes requests from a single user community, then the natural decision is to place the service account into that user repository. If the API provider processes requests from multiple user communities, then there is a judgement call that needs to be applied — here, consistency is probably the most important rule. There may be overriding information security standards within your organization that may dictate the design decision. Of course, not every API provider has to support every user community.

In a similar fashion, an API consumer likely has a specific user community that it targets. If the same application serves users across multiple communities, that works too. Likewise, not every API consumer will support every user community

Multiple communities, the same APIs

It gets interesting when users from multiple communities begin using applications that invoke the same APIs. Then, we see the same identity mechanisms on the API gateway and identity stack authenticate and authorize API requests in a seamless fashion. Here, it’s important to adhere to the following design principles:

  • Each system should have a single identity provider it communicates with. Stated another way, the API gateway should not have to determine what type of user it just received a request from in order to make the authentication call to the correct identity provider.
  • The API gateway should trust a single identity provider. This keeps the identity concerns for this non-identity system simple, relatively speaking. The identity provider should have preexisting trust (federation) relationships with other identity providers necessary to support the legitimate use cases of system actors within the security realms if it does not have direct access to the user repositories. These federation relationships will likely reflect the needs of supporting B2E, B2B, and B2C user communities for the system. The API gateway should have a single endpoint (on that single identity provider) to communicate with for authentication of users — not a separate endpoint for each type of user community.
  • For authorization, a role abstraction layer should prevent runtime components from having to do something different between members of the disparate user communities.

Not every company experiences the B2C, B2B, and B2E user communities all at once. But many do. Some will have more granular definitions of user communities. Regardless of how these communities are split up in your organization or how many of them there are, the same basic pattern discussed here can be used. The API gateway described in my SAML2 vs JWT series must be able to authenticate and authorize users from each of the desired communities against a single identity provider that meets the qualifications described here.

Image: Flickr Creative Commons/”T”eresa