Part 1: Authentication for the Modern Web
This is the first part of a tutorial blog series from Ben Finkel addressing the challenges, solutions, and implementation of sound authentication. By the end of this series, you will be confident in your ability to implement an authentication system — even with little-to-no background.
Today, I'm kicking off a series of tutorials, OAuth Authentication with GAE, aimed at getting up and running with a flexible delegated authentication library we can use to bootstrap our Google App Engine applications. First, we'll cover the basic concepts of authentication and OAuth 2.0, and then we'll sit down and hammer out some code.
I'll be using Python because it's terse and legible even if you're unfamiliar with the syntax. If Python is not for you, follow along anyways and you should be able to easily refactor it into the language of your choice. Google App Engine allows us to get an app up and running on the web, both quickly and at zero cost, and the concepts are easily transferable to the platform of your choice.
We'll be writing our own OAuth 2.0 authentication flow. We're going to rely on as few third-party libraries and abstractions as possible. We're going to do this against the advice of many in the industry because I believe it's important for us to understand. This information should not be obscured away behind a firewall of technical writing. Using a third party, as we'll see later, leaves us not only in the dark about how it works but leaves us handicapped when we wish to add OAuth providers to our application.
Whence OAuth OAuth 2.0 is a framework developed to allow a third-party application (a consumer) limited access to protected http-based resources. It does this primarily through a simple user interaction.
This interaction, often called the OAuth 2.0 "flow" or "dance," goes as follows:
The consumer application informs the user that it would like access to their protected resource (their Twitter feed, for example).
The user is redirected to a login page for the application that protects that resource for them (this app is known as the provider).
After logging in, the provider presents the user with the name of the consumer app and the permissions it is requesting.
The user can allow or deny this access by pressing the appropriate button.
If the user allows the access to continue, the consumer and the provider exchange information in the background.
The consumer then uses that information on a go-forward basis to perform whatever tasks it requires.
You've likely danced this dance before. If an app has ever requested access to your Twitter feed, or your Facebook page, or any other site that you normally use, you were engaging in the OAuth flow.
What's cool about this is that you never have to relinquish your login credentials to the consumer app which helps to keep your information safe. During step 5 that's listed above, the provider gives a token to the consumer which is used as a temporary password. If you decide to remove the consumer's access, the provider will offer a way to revoke tokens for specific consumers.
For us as app writers, we can use the process to delegate authentication to one of these providers. Users don't need to create a new username and password for our app, and we don't need to store that information or develop boring code like login pages and password reset emails. By relying on a collection of popular third party providers we can have secure authentication in our app that's convenient for both us and our users.
OAuth Challenges Implementing OAuth is not without its hurdles, however. Like I mentioned before, the official specification, RFC 6749, is dry and laden with technical vocabulary — making it difficult to parse. If you were to sit down without any background knowledge of the subject the RFC would be a tough place to start.
It's also just a framework, which means they leave many of the implementation details up to the provider. This has resulted in a scenario where each provider varies slightly in how they implement, and consequently our authentication library requires specific code for any given provider. This is one way a third-party library falls short. It must have each provider coded individually, and any additional providers we wish to add, require us to modify someone else's code.
In addition, OAuth is an authorization framework. What this means is that while you need to authenticate in order to use OAuth 2.0, there is no standard for what, if any, identity information is passed back to the consumer after the flow completes. Let's imagine we want to use an email address as the way to uniquely identify users on our consumer app. In order to get the email address back from any given provider, we'll need to specifically request it. Due to the point I made above, this will vary from provider to provider. In fact, there's nothing that says a provider even has to offer email address as an accessible resource.
Beyond OAuth – OpenID Connect That last point is a prickly one. It means that any solution using OAuth as an authentication tool will necessarily run into compatibility problems. Every provider has to be uniquely coded in our authentication library if we want to use it. Furthermore, they may roll email address up with a bunch of other resources that we don't actually need. Suddenly, our consumer app has to request a bunch of access that we don't want just to verify the user's identity.
One solution that has gained some traction the past year is called OpenID Connect.
OpenID Connect is a second set of standards that sit "on top" of OAuth 2.0 for authentication purposes. Using the rules defined in OAuth 2.0, as well as a large set of additional rules, OpenID Connect defines a very specific way to retrieve user Identity information. The upshot of all of this is that in our authentication library we can program a single OpenID Connect module and any provider that implements OpenID Connect will work without additional coding on our part. As OpenID Connect becomes more popular and more prevalent (it's already in use by Google, Microsoft, and Salesforce, among others), the allowable providers for our library grows without any additional work on our part.
In our next installment, we'll discuss OAuth 2.0 in further depth, play around with some OAuth dances, and get our project started on Google App Engine
You can read the full tutorial series in these weekly installments:
Part 1: Authentication for the Modern Web
Part 2: Delegating Authentication
Part 3: Let's Play on the OAuth 2.0 Playground
Part 4: Let's Start Running Code
Part 5: Authorization Grant, Our First OAuth Dance Steps
Part 6: Authorization Request, An OAuth "State" of Mind
Part 7: Authorization Grant, Final OAuth Dance Steps
Part 8: Expanding Our Service with GitHub
Part 9: OAuth 2.0: Authorization, Not Authentication
The series will conclude in April 2016.
P.S. – Not a subscriber? Start your free week.
delivered to your inbox.