API Security vs. Web Application Security: Part 2
In this post, we continue our comparison of API Security and Web Application Security. In the first post, we defined the evolution of Web Application Architecture and how this led to the API Gateway concept that is prevalent in modern API Management solutions. Now, we walk through the evolution of Web Application Security, how this evolved into modern API Security (OAuth2 + OpenID Connect), and the differences (and similarities between the two).
Web Application Security
Web Application Architecture #1 and #2 track a user’s security session usually with a JSESSIONID cookie (though, it could be any valid cookie name and this particular cookie is typically used in the Java/JEE world). The value is usually some random GUID — WebSphere Application Server (WAS) uses an encrypted and digitally signed LTPA2 token value for its security session tracking cookie value. That random GUID implies the web server needs a very good random number generator. I was once in a shop running JBoss where they implemented their own “secure” random number generator because they were concerned that what came out of the box was not secure; however, at the same time, they failed to apply even the most basic details from the JBoss Security Hardening Guide that Red Hat publishes (important safety tip, read through and apply the recommendations in that guide). In these simple web application architectures, the security between a traditional web application (Web Application Architecture #1) and an early SPA application that is making API calls (Web Application Architecture #2) does look very similar. In fact, it may be the exact same thing. And, it is simple. Either of these could be accomplished with any application server that can build and maintain an end-user security session. Unfortunately, beyond Web Application Architecture #2, things get much more complicated and the security details between Traditional Web Applications and invoking APIs diverge quickly. My working theory is that this is the origin of the notion that API Security and Web Application Security are exactly the same.
When SAML2.0-based Web Application Single Sign-On (SSO) is used for the authentication of the users in Web Application Architecture #1 and Web Application Architecture #2, the SAML Bearer Token is presented at the initial request (there is an acrobatics display of numerous redirects whose details are not important here, watch this in Fiddler sometime). After that, the SAML token is never seen by the browser or User-Agent again (until the security session expires and the browser is redirected to the Identity Provider to get a new SAML token to reinitialize the security session). That SAML token was almost certainly signed and likely encrypted as well. So, the potential of compromising it is relatively minimal compared to what we will see in a moment. After the initial request with the SAML token and the security session is established, that JSESSIONID cookie (or something similar) I mentioned earlier comes into play. There are other forms of Web Application SSO, but SAML is very common in this space and this series has already become quite lengthy.
The use of a JSESSIONID cookie (or any other cookie value for that matter) necessitates tracking the Security Context on the web server (app server, whatever). This is a very important point that will be revisited later when looking at OpenID Connect and JWT; since the Web Application’s Security Context must be tracked/cached on the web server a degree of statefulness has been introduced to the system. Tracking the Security Context on the server introduces statefulness to anything using Web Application Architecture #1 & #2 regardless of the applications architecture. There is an important exception to this point: WebSphere Application Server. I mentioned above that WAS does not use JSESSIONID to track the security session. That is just used to track HTTP Session (which is used less and less these days, ie, less statefulness). WAS uses an LTPA2 token stored in the LtpaToken2 cookie to track the security session of an authenticated user. An LTPA2 token is a form of bearer token similar to SAML 2.0 Bearer Tokens or JWT tokens — but, LTPA2 is proprietary IBM security technology, an important difference. I have mentioned this in other posts, but will reiterate it here; Application Security should be based upon open standards to the greatest extent possible.
With LTPA2, we see, for the first time, an example of Bearer Tokens being included in every HTTP(S) request. A Bearer Token is a type of Claims-Based Identity Token that describes an authenticated principal (ie, it contains “claims” about the authenticated principal that the token issuer, Identity Provider, knows to be true). A Bearer Token (LTPA2, JWT, SAML 2.0 Bearer Token) can be used to completely rebuild the Security Context from scratch without anything being tracked on the server. Thus, introducing true statelessness — even from an Application Security perspective. From a practical standpoint, in a situation like this, there is likely still a Security Context cache on the application server, but if it were lost (due to server crashes), the user would not be prompted to log in again. Bearer Tokens can be digitally signed, encrypted, describe the token issuer, have expiration dates, creation dates, scope(s), custom attributes, and other security features. To be clear, I am interested in Bearer Tokens that use essentially all of these mechanisms to prove where the token came from; though, from a practical standpoint, encryption of the token is often not used, instead confidentiality is maintained by system actors, the end user, and passing only over encrypted channels). LTPA2 has the drawback of being a proprietary IBM token format; as I’ve mentioned on a number of occasions in this blog, I am proponent of a standards-based approach to security.
Now, consider for a moment how a SAML/WS-Security-based SOAP Security Model works on an Enterprise Service Bus (or any other SOA platform that uses this security technology). There is a SAML 2.0 Bearer Token included on every SOAP call (per the WS-Security specification). Validation of the digital signature and other information known to the server at run-time provides the basis of securely building a Security Context for the SOAP service (however, short-lived the need for that security context may be). This is an efficient way of doing things when compared to running off and doing a WS-Trust call or LDAP(S) bind during the authentication step (for every SOAP call).
Going back to our LTPA2 example from earlier, we see for the first time where an API call with a Bearer Token (the LTPA2 token included) shares characteristics with our WS-Trust/SAML/WS-Security model for SOAP Web Services (described in the last paragraph). The specs are not important, the Bearer Token and statelessness concepts are important.
Now, consider Web Application Architecture #3. This could be implemented a couple of different ways.
- Maybe there is a primary API that most calls go to. The user hits a login service that authenticates the user. At this point, that login service could simply return a JSESSIONID cookie that represents a valid Security Context that is tracked on the web server for the API Provider (more or less like a traditional Web Application). In this case, the security would look more-or-less like what we have in Web Application Architecture #1 above. But, there are other API Providers. Maybe they are provided by third-parties; maybe it is a different group in the same organization. Maybe each one requires logging in and getting a JESSIONID cookie that is sent to that host:port/path. It has been done this way before. But, now we have multiple cookies tracking our security context across these servers. Troubleshooting this will be difficult. The complexity will negatively impact availability in the long-run.
- Perhaps, that login service returns a bearer token instead (let’s assume a JWT). Now, we get the same basic security model from option #1, but now we don’t have to track the Security Context on the API Provider. Unfortunately, there are still multiple APIs that we need to get a token for and keep track of. It is possible that one token could be obtained that has audience information that is relevant to each API Provider. But, this requires close coordination among the API Providers. If the groups involved were that closely aligned, they would very quickly move towards Web Application Architecture #4 (the API Gateway).
This description assumes that there is the same basic security implementation across all of these APIs. From a practical standpoint, this is unlikely — trying to get two development organizations to agree to the most basic of standards is like herding cats.
As a nice transition into a Web Application Architecture #4 discussion, look at how a Bearer Token would be used in this situation. By having all of the APIs advertised on the API Gateway, we can use one bearer token for accessing each of these APIs. So, there is one token to keep track of and its a bearer token so the server (API Gateway) doesn’t have to keep track of the security context. Include role (scope) information into the token and you already have the basis of a reasonable Coarse Grained Authorization security model for interacting with APIs. We will come back to authorization concepts in another blog post.
Web Application Architecture #1, #2, and #3 all have something in common — there is a single client. In Web Application Architecture #2 & #3, this can be described as there is a single API Consumer. In Web Application Architecture #4, we have multiple types of consumers and multiple consumers. This just got a lot more complicated. Rather than trying to build examples of how each type of API Consumer interacts with each API, it again makes sense to introduce the run-time API Gateway concept.
In Web Application Architecture #1 and #2, the group that controls the server also controls the client (these are just pieces of the same application, after all). I previously described this in Web Application Architecture #1 as tight coupling — not necessarily a bad thing in this context. It is certainly simpler and easier to maintain. By the time we get to Web Application Architecture #4, it can no longer be assumed that all clients can be controlled the way they can in Web Application Architecture #1 and #2. Even in Web Application Architecture #3, it’s likely the client code belongs to one of those API providers — but, there is probably a counterexample to that somewhere as well.
If we can no longer control the client, then well-defined patterns (as few as possible) must be established to describe how to build a security session (authenticate the user), propagate identity between the actors, and define the interaction between disparate actors (in the role of consumers) with the server (ie, the API Gateway). Luckily, the industry has done a lot of leg work on this in the form of OAuth 2.0 and OpenID Connect. I say patterns, plural, because this can and will look a bit different depending on the type of client. Luckily, the security model defined on the server-side makes things a little more predictable regardless of the API Provider implementation technology.
At a very high-level, OAuth2.0 + OpenID Connect provide us with two-legged and three-legged authentication + authorization scenarios.
As we covered in great deal above, the use of Bearer Tokens that can be attached to each API request and validated by the server without maintaining a security context or making external calls (from the server) is very helpful. In fact, the OpenID Connect spec mandates that JWT tokens be used as the OAuth 2.0 access_token.
Also in Web Application Architecture #4, we have N API Providers. Some are controlled directly by your organization, some by other Lines of Business within your organization, some by business partners, some are SaaS solutions. The API Gateway must be able to support multiple types of authentication with back-end APIs — this could be JWTs, Basic Authentication, client certificate (transport layer) authentication, SAML v2.0, some other OAuth access token format, subscription keys, or wide variety of proprietary/non-standard approaches. Ideally, JWT tokens issued from the same Identity Provider (IdP) the API Gateway uses would be used on the back end, but that tends to rarely be the case (unless the API Providers are all controlled by the same organization that manages the API Gateway).
All signs are pointing to the future of APIs will look like Web Application Architecture #4. So, why are Web Application Architecture #1 and #4 so different?
- In Web Application Architecture #1, the same organization controls the client and the server. The security mechanism doesn’t have to be flexible. It just needs to work with that one application.
- In Web Application Architecture #4, that one organization doesn’t control the clients in some cases. In other cases, different teams who have never agreed on anything else have clients calling the same APIs. Standards-based approach to security is extremely important. That standard needs to have a lot of flexibility built into it — we have that with OpenIDConnect and OAuth (plus, the related-family of specs.
- Similarly, in Web Application Architecture #4, that organization often doesn’t control the API Providers either (at least, not all of them). In Web Application Architecture #1 and Web Application Architecture #2, direct control of the server is generally assumed.
- Web Application Architecture #2 involves one API; Web Application Architecture #4 involves many APIs. Web Application Architecture #1 doesn’t even involve APIs.
- Web Application Architecture #1 and Web Application Architecture #2 use a session identifier (JSESSIONID or the like) that requires a stateful Security Context to be maintained on the server-side. Web Application Architecture #4 uses a Bearer Token that allows the server (API Gateway) to recreate the Security Context without any external data or checks — ie, it is truly stateless.
- Reverse Proxy technologies (Tivoli Access Manager for eBusiness, F5 APM, CA SiteMinder, others) are geared towards Web Application Architecture #1 and Web Application Architecture #2. Earlier in my career, I spent a lot of time trying to get these to work with SOAP Web Services with varying degrees of success. This was typically met with frustration. Each one was built with the assumption from the first bullet point above hard-coded into its architecture. When (and if) the related WS-* specs were implemented later, it never seemed to come together as gracefully as one might hope. This gave rise to technologies like WebSphere DataPower on the SOAP-side. In a similar fashion those technologies from the SOAP world have tried to adapt to the world of APIs, OAuth, and OpenID Connect. Again, with varying degrees of success. This gap gave rise to the API Management platforms we see today — like Apigee. Though, this is only part of the story behind the evolution of API Management.
As soon we lose the tight coupling between client and server from Web Application Architecture #1, we lose direct control of the clients and introduce many different types of clients. At this point, other aspects of security beyond Identity become even more critically important:
- API request validation (against a Swagger 2.0 definition or similar interface definition)
- XML & JSON schema validation (again, against the interface definition)
- XML Threat Protection.
- JSON Threat Protection
- SQL Injection Vulnerability detection
- Cross-Site Scripting attack detection
With this, you get a further glance of how I view the architecture of API actors, their interaction, and most importantly API Security. Leave comments.