00:00:06.020
Hi and welcome! Today we're going to be talking about delegation, federation, assertions, and claims.
00:00:11.059
A little introduction before we get started: My name is Lyle Mullican. You can find me on most social networks under the handle @Mullican.
00:00:17.760
I've been working with Rails for a long time, since version one. I'm currently a principal engineer at PayNearMe.com.
00:00:23.520
We are hiring, so feel free to come talk to me in the Discord chat if you're interested in exploring opportunities there.
00:00:29.460
Today, I'm going to be talking about user authentication, specifically the protocols we use for single sign-on.
00:00:35.880
Before we dive into that, I think it’s worth starting with the question of why we should care about these things as developers.
00:00:42.420
I’m probably not in the business of implementing protocol-level details on a daily basis, so why should I care how they work?
00:00:48.660
I think there are two answers to that. The first is that almost all of the security controls we have depend on having a reliable authentication system in place.
00:01:01.920
If there’s a way to impersonate a valid user, especially a privileged user, then a lot of the other security controls that we’ve carefully put in place to protect our applications become irrelevant.
00:01:14.280
So I believe that security is a shared responsibility, and every developer should be as educated about it as possible.
00:01:20.280
The second reason, though, is more practical. The law of leaky abstractions applies very much to the concept of user authentication.
00:01:32.880
If this isn’t a term that you’ve heard of before, it was coined almost 20 years ago by Joel Spolsky.
00:01:38.880
It states that all non-trivial abstractions, to some degree, are leaky.
00:01:44.520
So what this means is that as programmers, we benefit from all kinds of abstractions that are meant to protect us from details.
00:01:50.700
This allows us to focus on solving the problems that we care about, but there’s always some point at which those abstractions fail us.
00:01:57.320
The concerns we’re trying to avoid end up leaking through.
00:02:03.000
For Rails developers, one of the most obvious examples of this principle is Active Record.
00:02:09.660
It’s an abstraction meant to protect us from the database so that we can interact with it without needing to understand SQL.
00:02:16.260
However, most of us have encountered cases where that abstraction fails.
00:02:22.560
For performance reasons or other issues, database concerns leak through, and we find that we need to understand things at a lower level.
00:02:29.760
The same is true of authentication systems. Even if the gems or services we use abstract away many concerns around user authentication, at some point those concerns are likely to leak through.
00:02:44.580
Having some knowledge of what's going on at a lower level can serve us well.
00:02:56.580
Today, we’re going to talk about some authentication protocols specifically relevant to web applications.
00:03:09.120
We’ll also step back and discuss considerations for developers when integrating them and where they might cause problems.
00:03:15.000
Authentication aims to answer the question: who is sitting at the other end of a keyboard?
00:03:20.580
It’s a fundamentally hard question to answer and comes in two parts: how a person establishes their identity first, and then how they prove they are the same person when they return.
00:03:27.540
Most of what we think of as authentication falls in that second category.
00:03:34.440
There are analogies to this in the physical world. If this were an in-person conference, most of us would have had to board a plane to get here.
00:03:39.599
Consider what happens when I walk up to the gate to board a flight. An agent who’s never seen me before has to decide if I’m allowed to be there.
00:03:47.160
In early days of air travel, it was a simple process—anyone could walk up to the gate with a ticket.
00:03:54.960
Now, airport security is much more sophisticated; there’s a clear separation between secure and public areas.
00:04:05.940
To enter the gate area, I need to provide a government-issued ID, typically a passport or driver’s license, which is a long-term credential.
00:04:12.240
Then, at the gate, I show a boarding pass, which is a short-term credential valid only for my flight.
00:04:19.320
Most web applications do something similar—each request made to access a protected resource has to include a token that must be trusted.
00:04:27.180
Traditionally, this is done with a long-term credential like a username and password, similar to a government ID.
00:04:36.060
Providing this once gives me a session cookie, acting as a short-term credential for other requests in that session.
00:04:42.960
This creates a separation between the validation of a long-term credential and the short-term credential it’s exchanged for.
00:04:50.820
Often, different parts of the same application handle these roles, but such separation allows for different authentication models.
00:04:57.600
If I were to create a new Rails app, I might implement local authentication, where my application has direct access to users’ long-term credentials.
00:05:11.100
This means storing passwords as hashes. I hope securely!
00:05:17.160
The application takes user input, computes the hash, and verifies it.
00:05:23.880
Local authentication has a long history; it’s been in use since the early days of Unix and boasts many advantages.
00:05:30.840
It’s simple, reliable, easy to test, reason about, and understand.
00:05:38.640
However, just as the threat model for air travel evolved since the 1960s, the threat model for software has too.
00:05:45.120
In modern contexts, storing a local database of password hashes involves a lot of supporting infrastructure.
00:05:56.640
It’s really a lot to take on, and maybe not every app wants to deal with all those things.
00:06:02.820
Additionally, software architecture has evolved, leading to many cases where local authentication becomes problematic.
00:06:09.780
Use cases include multiple applications with a common user base, which necessitates seamless transitions between them.
00:06:18.480
In cases where client-side JavaScript runs in the browser or a native application accesses private data from multiple sources, local authentication can become a challenge.
00:06:26.520
Another use case is when you land a huge enterprise client who has 30,000 users that they don’t want to create accounts for.
00:06:34.200
They want those users to click a link on their intranet and transfer their internal identities to your product.
00:06:41.220
Identity validation can be handled by a centralized system you own or by a third-party you’ve outsourced.
00:06:51.840
There are a couple of related terms that you’ll hear in these conversations that I think are helpful to define up front.
00:06:59.520
Federation means that, within a defined environment, there’s a central source of information about users.
00:07:08.040
Other systems can rely on this single source of information.
00:07:15.180
Single sign-on means that, as a result of federation, users can access many different applications with one set of credentials.
00:07:21.120
Let’s take a look now at how that’s done and what implications these protocols have for building software.
00:07:28.440
The first one we’ll look at is SAML, which stands for Security Assertion Markup Language.
00:07:36.840
It’s been around for almost 20 years, and whether or not you’ve worked with it directly, you’ve probably heard of it.
00:07:45.099
This is a standard maintained by an organization called OASIS, which stands for the Organization for the Advancement of Structured Information Standards.
00:07:52.440
SAML is probably the protocol they are best known for.
00:07:59.220
It was the first single sign-on protocol for web applications to achieve widespread adoption.
00:08:07.620
By the mid-2000s, many large organizations like Google and Oracle were using SAML in their products and promoting its adoption.
00:08:14.700
Like all new standards, early versions had some issues, leading to a couple of revisions.
00:08:20.640
Version 2.0 is what everyone typically refers to today.
00:08:27.059
Now, I think the name of the protocol is somewhat misleading because SAML is much more than just a markup language.
00:08:34.560
The specification covers both the message format and the way they’re communicated between systems, making it a true protocol.
00:08:41.640
There are a few other terms specific to SAML that I think are helpful to define as well.
00:08:48.240
An identity provider is the system holding the user information and checking passwords.
00:08:56.040
A service provider is the entity the user is trying to access.
00:09:03.000
An assertion is a statement the identity provider makes to the service provider about the user.
00:09:10.200
An assertion can be positive, recognizing the user, or negative, stating that login failed.
00:09:16.920
Here’s an example of an assertion—this is the simplest version. As you can see, they’re XML documents and generally quite large.
00:09:24.540
This can sometimes cause problems, which we’ll discuss later.
00:09:31.459
Importantly, authentication can be initiated at either end.
00:09:37.440
As a user, I can start with the identity provider and ask it to authenticate me for a service.
00:09:44.220
Alternatively, I can start with the service and request that the identity provider authenticates me.
00:09:51.840
Both of these workflows are valid.
00:09:57.720
Messages are exchanged between systems via SAML bindings.
00:10:04.560
SAML is designed for web applications, thus everything occurs over HTTP.
00:10:10.560
This can involve a GET request, POST request, or a more complex process called artifact resolution, which we’ll detail shortly.
00:10:18.300
Let’s try a practical illustration to make this concept more concrete.
00:10:27.180
Imagine we have a library of rare books and a patron named Alice who wants to see one.
00:10:32.640
Alice goes to the fiction desk and asks to see their first edition of The Hobbit.
00:10:40.860
Bob, the friendly librarian, isn’t permitted to check library cards, so he redirects her to Carol.
00:10:49.740
Carol is responsible for validating library cards.
00:10:56.400
Alice approaches Carol, provides her library card, and Carol verifies Alice’s record.
00:11:04.740
Carol checks if Alice is a registered patron in good standing, ensuring she doesn’t have excessive fines or other issues.
00:11:10.560
Satisfied that Alice is a good patron, Carol writes a signed letter to Bob.
00:11:16.020
This letter informs Bob that Alice’s card has been verified.
00:11:23.520
Alice takes this signed letter back to Bob, who recognizes Carol's signature.
00:11:31.100
As a result, he grants Alice access to the book.
00:11:39.180
This is how a service provider-initiated SAML login may work, using HTTP redirect or post bindings.
00:11:45.960
For an identity provider-initiated process, Alice would approach Carol first.
00:11:52.320
After identifying herself, Carol would give Alice a signed letter to present to Bob.
00:12:01.560
In this case, Bob must only check the letter.
00:12:09.420
In both cases, Alice carries and delivers a communication that Bob relies on to verify her identity.
00:12:16.200
Though convenient, this introduces risks because Alice controls the document.
00:12:22.440
We’ll later discuss how this can lead to interesting vulnerabilities.
00:12:30.240
For SAML, there's also a method to transfer the assertion called artifact resolution.
00:12:37.200
In this case, Carol files the letter under a number after signing it, just providing Alice this number.
00:12:45.720
When Alice presents this number to Bob, he can request the letter from Carol directly.
00:12:52.260
He retrieves the letter without Alice seeing it, mitigating some risks.
00:12:58.740
However, this setup is a bit more complex, requiring the identity provider to store assertions.
00:13:07.420
The identity provider must communicate directly with the service provider, which is often not possible.
00:13:15.840
Now, the fundamental question in such a system is, what makes an assertion trustworthy?
00:13:24.780
Unlike passwords, assertions do not require a pre-shared exchange of secret knowledge.
00:13:34.320
Thus, the service provider must ensure that assertions aren't forged.
00:13:41.100
If anyone can create valid assertions, they could easily impersonate any user.
00:13:49.800
The service provider also needs assurances that an assertion cannot be reused if access is revoked.
00:13:58.260
Assertions must reliably maintain specific attributes that confirm their trustworthiness.
00:14:06.240
SAML supports both encryption and signing of assertions, but encryption alone doesn’t suffice.
00:14:16.440
Digital signatures ensure integrity, but incorrect implementations of digital signatures can lead to vulnerabilities.
00:14:23.160
XML signatures require careful handling, as even a single altered byte renders the signature invalid.
00:14:31.320
To correctly sign an XML document, it must first undergo a specific canonicalization before signing.
00:14:37.320
You can sign all or only parts of the document, complicating SAML's signature process.
00:14:44.520
This complexity leads to potential vulnerabilities, as shown in research papers.
00:14:51.240
Remember that assertions are usually large documents, and additional signatures further increase their size.
00:14:57.720
Parsing XML is resource-intensive, making processing SAML assertions a performance problem.
00:15:06.420
As a result, SAML isn’t ideal for apps with heavy JavaScript.
00:15:10.680
Nonetheless, for enterprise scenarios, SAML might be your only option.
00:15:20.520
Not long after SAML 2.0, OAuth emerged as another identity-related protocol.
00:15:27.840
Rooted in Twitter's needs, OAuth became an IETF standard.
00:15:33.840
It's essential to note that OAuth primarily deals with authorization, not authentication.
00:15:41.520
With OAuth, you delegate your identity on one site to another.
00:15:48.540
For example, if I have a WordPress blog, I could authorize it to tweet on my behalf with OAuth.
00:15:55.860
I log in to Twitter, get a token representing my identity, and this token can be used by WordPress.
00:16:04.560
This setup seems like single sign-on, but it leads to misconceptions.
00:16:11.700
It's like if Alice gave Bob a key to her apartment to verify her identity, which isn't the intended use.
00:16:18.540
OAuth isn't suitable for scenarios focused purely on identity verification.
00:16:25.320
However, it does have advantages over SAML, including smaller, JSON-formatted messages.
00:16:34.200
It also supports mobile and browser-based workflows that SAML doesn't adequately address.
00:16:44.400
The creators of these protocols designed OpenID Connect, layering it over OAuth to encompass authentication needs.
00:16:52.800
It's different from the earlier OpenID standard, which OpenID Connect mostly replaces.
00:17:01.560
OpenID Connect shares many concepts with SAML.
00:17:08.040
Relying parties still rely on identity providers to validate users.
00:17:15.360
OpenID Connect introduces the ID token, containing information about the user, akin to a SAML assertion.
00:17:22.740
User attributes in OpenID Connect are known as claims, while SAML generally refers to them as attributes.
00:17:30.720
Messages in OpenID Connect are formatted in JSON, which is more efficient and easier to process than XML.
00:17:38.040
Another advantage of OpenID Connect is its discovery protocol that allows identity providers to publish configuration info.
00:17:45.120
This reduces the setup work when integrating different systems compared to SAML.
00:17:52.320
Here we have Google’s OpenID Connect metadata, which provides essential information for integration.
00:18:01.200
OpenID Connect’s main advantages over SAML are smaller messages that are faster to parse.
00:18:08.520
It’s easier to set up integrations and anticipates more modern use cases for JavaScript-heavy applications.
00:18:16.200
OpenID Connect offers various ways to authenticate users, each with different security implications.
00:18:24.660
The first is the authorization code flow, existing in both OpenID Connect and OAuth 2 workflows.
00:18:30.780
It resembles the SAML artifact resolution protocol.
00:18:37.680
After authenticating with the identity provider, the user receives an authorization code upon redirection.
00:18:45.300
The relying party uses this code along with a secret to obtain an access token and ID token.
00:18:52.020
This flow fits traditional server-to-server interactions.”
00:18:58.860
JavaScript or native apps can't keep secrets from users, making this flow non-ideal for those contexts.
00:19:06.960
Nonetheless, access tokens remain useful, including calling a user info endpoint for more user attributes.
00:19:14.040
ID tokens typically contain minimal information about a user.
00:19:21.360
In cases where code can’t maintain a secret, different flows exist.
00:19:29.640
Historically, the implicit flow was popular, but it’s now largely considered deprecated.
00:19:38.880
This flow allows ID tokens to be included in the redirect after user authentication.
00:19:46.200
While the process isn’t inherently broken, it poses security trade-offs.
00:19:53.520
The client cannot prove its identity to the identity provider; only redirect URLs are pre-registered.
00:20:01.560
Tokens can be passed via query strings or URIs and are more at risk of leaking through the front channel.
00:20:09.840
JWTs support various signature algorithms, not all of which are safe in every configuration.
00:20:16.920
For instance, HMAC-based signatures require a pre-shared secret while public key signatures are generally recommended.
00:20:25.560
The implicit flow can create several challenges due to the lack of security.
00:20:32.520
A modern approach is the Proof Key for Code Exchange (PKCE), which allows public clients to create temporary, single-use secrets.
00:20:40.740
This bolsters security and is preferred when possible.
00:20:48.960
A hybrid flow combines elements of both implicit and authorization code flows.
00:20:56.220
Its use cases are narrow, mainly for apps requiring early user identification, along with the need for access tokens.
00:21:01.400
In conclusion, most single sign-on processes in production today use OpenID Connect or SAML.
00:21:08.640
Now, let’s step back and revisit the original question: why should developers care about these protocols?
00:21:14.580
Authentication, a challenging problem, is relevant to almost all web applications.
00:21:21.960
Understanding these protocols underpins several other security controls.
00:21:27.960
Each version update reflects researcher feedback, identifying flaws in their designs.
00:21:34.260
This maturation doesn’t eliminate potential problems; vulnerabilities often arise from implementation.
00:21:41.220
Thus, many developers shouldn't implement these protocols at a low level directly.
00:21:46.920
Instead, relying on thoroughly tested code is wiser.
00:21:54.240
Understanding is essential, though.
00:22:01.560
Let’s look at a simple example related to JSON Web Tokens (JWTs).
00:22:08.180
A JWT has three parts—header, payload, and signature—separated by dots.
00:22:16.560
The header and payload are base64 encoded JSON strings.
00:22:23.520
To parse and validate a JWT, I could split the token and decode those parts.
00:22:30.140
Next, I’d determine the issuer and retrieve their signing key from their discovery info.
00:22:37.680
However, I need to know the specific signing algorithm employed.
00:22:44.640
If a symmetric algorithm was specified in the header of the JWT, trusting it could be problematic.
00:22:50.880
If I used a public key to verify it, anyone could submit a valid token.
00:22:58.720
Similar mistakes have been found in widely-used JWT libraries previously.
00:23:04.440
Additionally, an unsigned token claiming a none algorithm presents its own vulnerabilities.
00:23:12.660
These issues are not exclusive to OpenID Connect and JWTs; similar pitfalls exist in SAML implementations.
00:23:20.980
Thus, rather than avoiding third-party code, we should thoughtfully leverage trusted libraries.
00:23:28.340
As implementers, we must ensure the libraries we’re using remain maintained and patched.
00:23:34.520
When considering identity or authentication functions, especially if external systems handle them, we should analyze our assumptions.
00:23:41.900
Even with reliable codebases, each integration point necessitates careful evaluation of trust.
00:23:48.720
For instance, granting users the ability to sign in through several different providers leads to variability.
00:23:54.060
While the email claim is common, its handling may differ widely across providers.
00:24:01.800
Some might allow multiple accounts per email, while others may bypass verification processes.
00:24:07.860
Understanding how providers interpret claims is critical.
00:24:14.700
Even basic assumptions about email addresses can introduce risks if they diverge.
00:24:22.080
To summarize, protocols and cryptographic algorithms facilitate flexible authentication designs.
00:24:29.760
However, they must be used with caution.
00:24:36.480
An identity token, in most cases, is just another form of user-controlled input with specific trust boundaries.
00:24:43.320
While the signature validates message integrity, we must still verify message content.
00:24:50.520
Testing scenarios for potential failures is relatively uncomplicated.
00:24:56.840
For instance, what if a malicious token arrives containing unexpected information?
00:25:04.560
What if a token issued to a different application is processed by mine?
00:25:10.080
Consideration of various possibilities aids in mitigating risks.
00:25:16.680
Additionally, it's vital to keep third-party libraries up-to-date.
00:25:23.280
Systematically evaluating third-party dependencies is essential.
00:25:30.240
Asking questions about potential breaches, acquisitions, policy changes is imperative.
00:25:35.400
Bear in mind, single sign-on can create a single point of failure.
00:25:41.400
For more hands-on experience, especially with Rails applications, consider setting up local instances of both an identity provider and a service provider.
00:25:49.240
Observe how the messages are exchanged and experiment with it.
00:25:56.080
Using the Doorkeeper OpenID Connect gem can expedite establishing an identity provider.
00:26:02.840
Web-based tools like JWT.io assist in debugging JWTs, while oidc-debugger.com provides a sandbox for OpenID Connect flows.
00:26:10.300
Finally, here are several documents for further reading regarding these systems.
00:26:18.040
The specifications themselves are very readable and valuable for understanding protocols.
00:26:24.920
An article from oauth.net explains why OAuth doesn’t serve as an authentication protocol.
00:26:32.200
The original article on the law of leaky abstractions is worth the read.
00:26:40.200
Additionally, there are research papers analyzing various implementation issues in JWT and SAML libraries.
00:26:48.000
Lastly, PayNearMe is hiring, so please feel free to talk to me if you're looking for a new opportunity.
00:26:55.520
Thank you very much!