RailsConf 2015
Adventures in Federating Authorization and Authentication with OAuth

Adventures in Federating Authorization and Authentication with OAuth

by Lance Gleason

The video "Adventures in Federating Authorization and Authentication with OAuth" features Lance Gleason discussing the complexities of implementing OAuth in federated systems, particularly within microservices architectures. The key points outlined in the talk include:

  • Introduction to Web Services and Microservices: Gleason introduces the concept of microservices as an evolution of application architecture, emphasizing the challenges that arise as applications grow larger.
  • Understanding Federation: He explains federation as integrating disparate systems under a common interface, which allows functionalities like Single Sign-On (SSO) to streamline user access across multiple services.
  • Security Challenges: Gleason highlights the importance of security in the context of OAuth, noting that no application can be entirely secure and drawing analogies to safes and Wi-Fi networks.
  • Traditional Authentication Issues with Devise: While many Rails developers are familiar with Devise, he points out the complications it introduces in service-oriented architectures, such as the burden of multiple passwords for users.
  • Single Point of Failure: He discusses the drawbacks of having a single entry point for authorization and authentication, as it can lead to downtime and bottlenecks during high-traffic scenarios.
  • Importance of Token Management: Gleason details the OAuth workflow, emphasizing the need for secure, timely processing of access tokens and authorization codes to prevent interception and enhance security.
  • Innovative Solutions and Architecture: The presentation leads to the exploration of a delegate-driven model where Doorkeeper operates as an authentication service, allowing other applications to communicate with it without direct integration, thus minimizing dependencies.
  • Load Testing and Outcomes: He concludes with a discussion of substantial load tests that revealed the system's capacity to handle over 30,000 concurrent requests without problems, validating the effectiveness of the federated approach.
  • Takeaways on Security and Reflection: Gleason encourages developers to frequently reflect on their security practices and remain vigilant about how authentication frameworks are implemented to ensure robust tokens and secure access points.

This insightful session from RailsConf 2015 provides both a theoretical and practical understanding of federating OAuth in microservices, culminating in a call for continuous evaluation of security measures within complex architectures.

00:00:11.840 Hello everyone, my name is Lance Gleason, and I run a small consultancy. Along with wearable prototyping and mobile development, we also have a smaller company called Attend, which focuses on web analytics in physical spaces using technologies like beacons. Additionally, I'm one of the co-organizers of Ruby Hooso, which, up until this year, was the only Ruby developer conference in Africa. I'm thrilled that another small Ruby conference has launched in Nairobi, as it brings us joy to spread the Ruby love. I'm also an organizer of RubyCamp Zed.
00:00:34.640 Quick question for everyone here: how many of you have heard of Extreme Programming? Pretty much everyone. How about Pair Programming? A good number, awesome! Now, how many people regularly practice Pair Programming? A decent amount. Being a boutique consultancy, we often thought about how to maintain the benefits of Pair Programming while facing constraints that larger organizations may not encounter, such as budget limitations or insufficient personnel.
00:01:04.640 This led me to an idea: How about substituting a human pair with a feline companion? Imagine practicing Pair Programming with a cat. So here we are, preparing for a standard session, and I have a comfortable chair set up for my new partner, using a single keyboard approach. I've learned a few things from this experiment. Initially, I thought when my cat Ally jumped onto my keyboard, she was demanding attention; however, she was actually indicating that I was doing something silly.
00:01:24.000 This experience has led to many misconceptions. Some argue that the cat is merely an observer, akin to rubber duck programming. I disagree; she participates, and her insights can lead to breakthroughs, as demonstrated during a particularly challenging debugging session. Speaking of companions, how many of you are dog people? We also conducted experiments with our canine friends. Max, for example, helped solve a Ruby problem, while another dog assisted in resolving issues related to gambles.
00:01:36.640 While utilizing our pets, I noticed that a Shih Tzu didn't seem as motivated as my cat during our coding sessions. Clearly, our feline friend emerged as the technical and motivational leader. We even created a little website for this venture, and I brought some fun T-shirts too. But let's not digress; we are not here to talk about programming with pets.
00:01:48.080 We are here to discuss web services, particularly microservices. I wasn't present for earlier discussions about the potential downsides of microservices, but if you share that sentiment, I encourage you to hear us out. Today, we will delve into the subjects of web services, federation, security, and even some homework.
00:02:08.640 So, what are services? First, let's see how many of you understand what web services are. It seems a good number of you do, which is great. Now, how many have worked within a service-based architecture? Quite a few hands. For those who have not, my best explanation of a service is an evolution of your platform. Think of it like starting off with a small Rails application, similar to a puppy or a playful kitten.
00:02:27.680 Over time, this small application can grow, becoming more complex until it feels more like an overwhelming task, where you may want to break it up. There are typically two types of engineers: those who've experienced this situation firsthand and those who haven't, but they are lying about it. When we encounter a particularly problematic codebase, our understanding evolves, but we often reflect on the difficulties we faced.
00:02:55.440 So why break up our application into services? Usually, some event pushes us toward that route. It may be that the monolith is slowing down or that we need to scale effectively. In snowballing like this, we encounter our projects becoming less manageable as demands continue to grow.
00:03:02.640 Let’s now discuss federation, particularly with OAuth services. Federation is defined as integrating disparate systems under a common interface, allowing these systems to act as one. A common use case for federation would be implementing Single Sign-On (SSO), where multiple sub-services can be accessed through one login.
00:03:18.560 The concept of SSO was a driving force behind my ideas for this talk. On a recent project, we aimed to implement Single Sign-On for our application. Before diving into that, allow me to touch on security. When we think about security, we often want to prevent unauthorized access to our application.
00:03:38.400 However, it's essential to remember that no application can ever be 100% secure. For example, safes are rated by the duration it would take for an experienced safe-cracker to access them. Similarly, your Wi-Fi network may feel secure, but as seen in various hacking examples, it's still vulnerable. Even with adequate security, determined hackers can bypass safeguards.
00:03:56.640 When working with a Rails application, we often lean towards using a tool like Devise for authentication. To gauge the familiarity, display your hands if you've used Devise. It appears that nearly everyone has. While it is a great tool, problems arise when employing it in a service-oriented architecture.
00:04:17.680 If you are federating your application, then expanding it means multiple instances of your application will require similar authentication measures. Consequently, you may encounter annoying situations where users have several passwords to keep track of, leading to confusion and potential security risks. There are instances where companies must implement the same password across many instances, causing an inadequate authentication framework.
00:04:31.680 Alternatively, we can explore using firewalls. We can position a single entry point into the application that manages authorization and authentication. As requests reach this layer, very often, they have to pass this point to access other application components. While this option offers some advantages, it also results in a single point of failure in the architecture.
00:04:52.320 If that layer experiences downtime, your entire application can become inaccessible to users. Even with a well-defined architecture, it can lead to bottlenecks, especially if numerous requests are queued up waiting for access, creating negative user experiences.
00:05:02.640 When determining whether a direct-access architecture is appropriate, consider the traffic flow. For example, if your application has a high read-to-write ratio, where 90% of content is read-only against 10% requiring authentication, you may find this architecture presents challenges.
00:05:16.080 In an instance where we anticipated spikes in traffic—upwards of 30,000 concurrent requests—we evaluated whether that single point architecture would suffice. With these traffic shifts, if that single authorization point failed, users wouldn't be able to access the resources they requested.
00:05:37.440 When we initially attempted to design a federated architecture, we encountered several other hurdles pertaining to security compliance. For example, we weren't dealing with particularly sensitive information, which granted us room for flexibility during implementation. However, it remained essential to manage user sessions effectively to ensure a smooth user experience.
00:05:52.320 Now, let's discuss OAuth implementations. Take note that many approaches to OAuth employ something known as a bearer token method. To provide some context, a bearer token is not what you may imagine, such as a gaming token. It allows authenticated requests to interact with the server’s resources.
00:06:05.440 The OAuth workflow generally begins with an authentication request, which then gets forwarded to the server. The user would go through a login phase, often redirecting to Twitters, for instance, to complete that authentication process. Once authorized, an authorization code would return to the application, which is captured through the URL.
00:06:25.440 What’s important in understanding the token workflow is that the authorization code is returned within the URL, which brings about the need for short-lived and one-time use of the code. Security measures are necessary to mitigate any attempts at interception that may arise during this transaction.
00:06:46.400 After the user receives a successful authorization code, a subsequent request is made to the OAuth server, requesting an access token based on the previously obtained authorization code. Once everything scrutinizes successfully, it then provides the required access token for the user or the application to request their authenticated resources.
00:07:06.560 Now, let’s reiterate how doable this is from a Rails developer’s perspective. Many of us have probably encountered using established integrations like Doorkeeper to implement OAuth for our services. You’d likely go through the simple steps, generating a Doorkeeper installation and performing database migrations as a basic setup.
00:07:26.640 However, upon shifting towards a service-oriented architecture, your applications start needing dedicated databases set up for each service due to the increased complexities introduced by using multiple instances. Switching to Doorkeeper meant many services would require distinct data store integrations, thus causing challenges to provisioning and development.
00:07:45.680 In simplifying our approach to solve these issues, we opted to investigate basic authentication methods employing Doorkeeper coupled with Devise. This combination yielded a scenario with numerous user accounts and contexts across services, leading us through the tedious setup process. The underlying authentication prompts became too cumbersome to manage.
00:08:00.960 At that stage, we reviewed potential alternatives that might work more efficiently beyond the separate services endpoint. Many of these methods lead to scattered management, generating different credential sets across services that led to user experience setbacks.
00:08:12.640 Given those experiences, we recognized the significance of employing a streamlined process and began exploring a delegate-driven model for our authentication service—Doorkeeper would operate on one dedicated service while other applications don't directly need it installed. Instead, they could simplify authentication with OAuth through delegation.
00:08:28.960 For illustration, this architecture could entail using Doorkeeper in a solitary microservice while making requests through it from the others to manage token checks. Thus, we keep functionalities defined, with separate services dedicated to user management and Doorkeeper handling requests.
00:08:42.880 With this distribution of responsibilities, any of our secondary services would communicate to the main Doorkeeper service in cases requiring validation of tokens, forming lesser threads of access and cutting down resource-heavy tasks from multiple services.
00:08:58.000 What we ended up with was a literate procedure to maintain user sessions across services without each instance requiring a full suite of dependencies and databases. Therefore, our secondary services focus solely on what they were designed to do, allowing Doorkeeper to simply handle authentication and authorization.
00:09:16.480 In order to optimize further, we introduced token caching for improved efficiencies across services. The premise was simple: each service would cache tokens received via the current session and verify validation status before forwarding the requests onto Doorkeeper. It significantly lessened the burden placed on the token-verifying infrastructure, keeping high availability.
00:09:31.680 As we concluded our implementation, we ramped load tests to challenge our traffic spikes of up to 30,000 concurrent requests. The architecture experienced no triggering issues during tests, cementing our view that this separation was functional. Eager to migrate and push our architectural designs into production, we found success.
00:09:45.840 In retrospect, we have valuable lessons to learn about federated applications and fault tolerance, particularly concerning how security has varied implications depending upon architectures engaged. While we were fortunate not to have encountered detrimental hacks during our build, it served as an essential reminder that ultimately, securing those tokens and access points are crucial.
00:10:04.560 In implementing security features, it became clear that our experience often feels painfully inconsistent when examining how pieces come together. Continuous reflection on the practices of token management and evaluating structural choices led us to recognize areas in which we must remain vigilant to secure our services fully.
00:10:18.720 Ultimately, I urge fellow developers to reflect on their implementations frequently, acknowledging that adopting existing frameworks like Doorkeeper should always involve an understanding of their security implications—remain cautious if you find yourself rolling certain implementations around without guidance.
00:10:30.720 Thank you for your attention, and I'd like to open up the floor for any questions.