In the movie Ferris Bueller’s Day Off, a valet attendant takes a fully restored 1961 Ferrari out for a joyride. How do you prevent the same thing from happening to your brand-new Mustang? Some cars now come with special keys that allow the owner to provide limited authorization to valet attendants (or kids!) and prevent activities such as opening the trunk and driving at excessive speeds.
OAuth was created to solve the same core issue online.
When Google first released the Google Calendar API, it provided the ability for application developers to read and manipulate a user’s Google Calendar. However, the only way for a user to provide delegated access was to give the application his or her account username and password, which the application would then use with Google’s proprietary ClientLogin protocol.
Proprietary protocols like ClientLogin and standard protocols like HTTP Basic authentication resulted in both small and big applications requesting passwords from users to get access to their data. This wasn’t affecting just desktop apps—applications all over the Web were prompting for credentials. Flickr, an online photo-sharing site, was one such application. Originally an independent company, Flickr was acquired by Yahoo! a few years after Google bought Blogger. The idea of Yahoo! asking for Google user passwords scared both firms, leading to the development of new proprietary protocols that tackled this problem on the Web.
With these new protocols, such as Google’s AuthSub (see Figure 1-1) and Yahoo!’s BBAuth, an application would redirect users to an authorization page on the provider’s site if the app needed access to user data. Users would log in to their accounts and grant access, and then the application would get a token to use for accessing the users’ data.
While this solved some security issues, it also created costs for developers. Developers integrating with multiple major API providers had to learn and implement several web-based authorization protocols in their applications. Startups building new APIs were not comfortable implementing the proprietary auth schemes, nor developing their own custom schemes, which might introduce security vulnerabilities. Instead, these startups and major API providers decided that they needed to create a standard protocol to improve consistency for these web-based authorization flows.
With wide adoption of collaboration platforms and social networks, application developers have the opportunity to connect users with their data wherever they are on the Web. Connecting users with their data results in improved day-to-day efficiency by eliminating data silos and also allows developers to differentiate their applications from the competition.
OAuth provides the ability for these applications to access a user’s data securely, without requiring the user to take the scary step of handing over an account password.
Types of functionality provided by OAuth-enabled APIs include the following:
Getting access to a user’s social graph—their Facebook friends, people they’re following on Twitter, or their Google Contacts
Sharing information about a user’s activities on your site by posting to their Facebook wall or Twitter stream
Accessing a user’s Google Docs or Dropbox account to store data in their online filesystem of choice
Integrating business applications with one another to drive smarter decisions by mashing up multiple data sources such as a Salesforce CRM and TripIt travel plan
In order to access or update private data via each of these APIs, an application needs to be delegated access by the owner of the data. Each of these APIs, and over 300 more around the Web (according to Programmable Web in February 2012), support OAuth for getting access.
Having a common protocol for handling API authorization greatly improves the developer experience because it lessens the learning curve required to integrate with a new API. At the same time, an authorization standard creates more confidence in the security of APIs because the standard has been vetted by a large community.
Usernames and passwords are typically the lowest common denominator for authentication and authorization on the Web. They are used for HTTP Basic and HTTP Digest authentication and on countless login pages. However, asking a user for their password has a number of side effects:
A user may not trust providing their password to your application.
Even if the user is comfortable providing their password to your application, making the user comfortable doing this around the Web can have negative long-term effects, such as making phishing scams more effective.
When the user provides their password to your application, you get access to not only the data your application needs, but all other data in the user’s account. The application has an obligation to its users to securely store these passwords and prevent them from leaking. Many developers do not want the risk exposure of having this additional responsibility.
When a user changes their password, your application no longer has access to their data.
The only way a user can revoke access to your application is by changing their password, which also revokes access to all other apps.
When an API provider supports federated authentication mechanisms such as OpenID or SAML (see Federated Authentication), users may not have passwords on their accounts. This makes it impossible for those users to use applications powered by the API.
If an API provider requires passwords for API authentication, it becomes challenging to improve account security with technologies like CAPTCHAs or multifactor authentication (such as one-time password tokens).
In order to understand OAuth, it’s important to first understand the relevant terminology. We’ll introduce some key terms up front, and then discuss additional terms throughout the book.
Authentication is the process of verifying the identity of a user—knowing that the user is who they claim to be.
In the real world, when a police officer asks for your identification, she’s verifying your identity by ensuring that the picture on your identification matches your likeness.
On desktop computers and on the Web, authentication is about knowing that the user at the keyboard is the owner of the account. Authentication is typically performed by asking a user for a username and password. The username represents the user’s claimed identity, and the software application assumes that if the user provides the correct password that they are indeed that user.
Although many applications have their own system of accounts (including usernames and passwords), some applications rely on other services to verify the identity of users. This is called federated authentication.
In a corporate IT environment, applications may trust an Active Directory server, a LDAP server, or a SAML provider to authenticate users.
On the Web, applications often trust OpenID providers (such as Google or Yahoo!) to handle the authentication of users. There are many benefits to federation for both application developers and users. OpenID is the most common open web protocol for handling federated authentication.
Although OpenID has been used on the Web for many years, we’ll discuss only OpenID Connect, which is the next-generation version of OpenID based on OAuth 2.0.
Authorization is the process of verifying that a user has the right to perform some action, such as reading a document or accessing an email account. This typically first requires valid identification of the user (authentication) in order to check whether the actual user is authorized.
When a police officer pulls over your car for speeding, she first authenticates you using your driver’s license (to verify your identity) and then checks the license (expiration date, restrictions, etc.) to ensure you’re authorized to drive.
The same process happens online—a web application first verifies your identity by logging you in, and then it ensures that you access only the data and services you’re allowed to, typically by checking an access control list for each operation.
Delegated authorization is granting access to another person or application to perform actions on your behalf.
When you drive your car to a classy hotel, they may offer valet parking. You then authorize the valet attendant to drive your car by handing him the key in order to let him perform actions on your behalf.
OAuth works similarly—a user grants access to an application to perform actions on the user’s behalf and the application can only perform the authorized actions.
There are several key actors in the OAuth protocol flows:
The server hosting user-owned resources that are protected by OAuth. This is typically an API provider that holds and protects data such as photos, videos, calendars, or contacts.
Typically the user of an application, the resource owner has the ability to grant access to their own data hosted on the resource server.
An application making API requests to perform actions on protected resources on behalf of the resource owner and with its authorization.
The authorization server gets consent from the resource owner and issues access tokens to clients for accessing protected resources hosted by a resource server. Smaller API providers may use the same application and URL space for both the authorization server and resource server.
OAuth 1.0 required cryptographic signatures be sent with each API request to verify the identity and authorization of the client. Cryptography is challenging for the casual developer to grasp and also challenging for even highly skilled engineers to master. This led to plenty of developer frustration and, presumably, less adoption of APIs than could have been achieved with an easier authorization protocol.
When OAuth 1.0 was developed in 2007, it was decided that cryptographic signatures were necessary to support the security of APIs. At the time, many top API providers hosted their APIs at vanilla HTTP endpoints, without SSL/TLS protection. Over the years, SSL/TLS became a more common way of protecting APIs and the need for signatures decreased in the eyes of some members of the security community.
Combining the perception of low API adoption due to the complexity of cryptography in OAuth 1.0 and the greater prevalence of SSL/TLS support for APIs led to the development of the OAuth Web Resource Authorization Profiles (WRAP) specification. OAuth WRAP is the predecessor to OAuth 2.0—it eliminated the complex signature requirements and introduced the use of bearer tokens.
Even as OAuth 2.0 nears finalization in the standards community, there remains some strong individual opposition to not requiring the use of signatures, including by Eran Hammer-Lahav, the editor of the specification. Eran has written a blog post titled OAuth 2.0 (without Signatures) Is Bad for the Web, in which he acknowledges the complexity of signatures for some developers but defends their value. He mainly points out that removing signatures from OAuth 2.0 makes it easy for developers to make mistakes and accidentally send their credentials to a malicious API endpoint, which can then abuse these credentials to make additional requests because they’re not protected by a signature. While he argues that this isn’t likely today, he does believe it will become more critical as automated discovery is added for API and OAuth endpoints. Others identify cryptographic signatures as a feature that allows for greater confidence in the origin of API requests as the requests pass through multitiered architectures.
Engineers often have to strike a delicate balance between security and usability, and this case is no different.
One of the primary concerns with the elimination of signatures is that developers will not properly verify SSL/TLS certificate chains when making requests to the authorization and resource servers. This is required by the specification and addressed in the OAuth 2.0 threat model document, but the ease of disabling proper certificate and certificate authority validation in popular libraries, combined with the difficulty of fixing issues associated with it, has resulted in many developers taking shortcuts that threaten the security of their applications.
When implementing OAuth 2.0, calling any APIs, or using a library, you should verify that it properly handles SSL/TLS certificate chain validation by doing the following things:
Checking that the hostname on the certificate returned by the server matches the hostname in the URL being accessed
Verifying each certificate in the chain properly chains up to a valid and trusted certificate authority (CA)
Ensuring that the certificate authority bundle on your server is secure and not able to be modified by potential attackers
The MAC Access Authentication specification defines how clients can sign their OAuth 2.0 requests when signatures are supported or required by the API provider.
Author’s Note: If you’re thinking MAC only refers to a type of computer, you can understand why signatures are hard for many developers! You might want to find a good book on cryptography.
In order to sign requests using MAC authentication, the client
must first get a MAC key. This can be issued by the OAuth
authorization server. In this case, the key is returned each time an
access_token
is returned by the
authorization server. This MAC key must be for use in either the
hmac-sha-1 or hmac-sha-256 algorithms. Alternatively, the MAC key can
be issued in an out-of-band process, such as when the developer
registers their application with the API provider. Regardless of how
the key is issued, it must always be issued over a secure SSL/TLS
channel and must be kept confidential.
When connecting to OAuth-enabled APIs that require signatures,
each API request must include a MAC signature in the Authorization
header of the request. The
process of generating this signature involves creating a normalized
request string (nonce, HTTP method, request URI, host, port, optional
body hash, etc.) and performing a cryptographic signature. It is
highly recommended that developers use a prebuilt library to handle
OAuth MAC signing if needed. If you need to build your own
implementation, please see the specification,
as the details are out of scope for this book.
OAuth requires that applications register with the authorization server so that API requests are able to be properly identified. While the protocol allows for registration using automated means, most API providers require manual registration via filling out a form on their developer websites.
At the time of this writing
Google requires you to register your client by visiting its APIs Console, as shown in Figure 1-2.
Microsoft Windows Live requires you to register your client using its application management site.
Facebook requires you to register your client on the Facebook Developers site.
As an example, the following information is required to register an OAuth client with Google via their APIs Console:
Google Account
Product Name
Product Logo (optional)
Website URL used for Redirect URIs (for web applications only)
After registration is complete, the developer is issued client credentials:
Specified as client_id
when
interacting with the resource server
Specified as client_secret
when exchanging an authorization code for an access token and
refreshing access tokens using the server-side Web Application Flow
(see Figure 7-1).
Registration enables the application developer to obtain client credentials, which are used to authenticate requests made to the authorization server. These credentials are critical in protecting the authenticity of requests when performing operations such as exchanging authorization codes for access tokens and refreshing access tokens (as described in Chapter 2).
Registration also gives the API provider information to improve the user experience during the authorization process. When presenting an application’s request for data access to the user, the API provider will often display the name and logo of the application.
See Figure 2-3 for an example of how Google uses the registration information on the approval screen.
The first version of OAuth was designed primarily to handle API authorization for classic client-server web applications. The specification did not define how to handle authorization in mobile applications, desktop applications, JavaScript applications, browser extensions, or other situations. While each of these types of apps have been written using OAuth 1.0, the method of implementation is inconsistent and often suboptimal, as the protocol wasn’t designed for these cases.
OAuth 2.0 was architected with this variety of use cases in mind.
OAuth 2.0 defines several important client profiles:
An OAuth client running on a web server. The web application is accessed by a resource owner (user) and the application makes the appropriate API calls using a server-side programming language. The user has no access to the OAuth client secret or any access tokens issued by the authorization server.
An OAuth client running in a user’s web browser, where the client has access to the application code and/or API requests. The application could be distributed as JavaScript included in a web page, as a browser extension, or using a plug-in technology such as Flash. The OAuth credentials are not trusted to be kept confidential from the resource owner, so some API providers won’t issue client secrets for applications using this profile.
An OAuth client which is very similar to the client-side application, as the credentials are not trusted to be kept confidential. However, since it’s an installed application, it may not have access to the full capabilities of a web browser.
Although signature-based MAC Access Authentication was mentioned earlier, most OAuth 2.0 authorized APIs require only bearer tokens to make authorized requests. Bearer tokens are a type of access token whereby simple possession of the token values provides access to protected resources. No additional information, such as a cryptographic key, is needed to make API calls.
Whether you’re building a server-side web application, client-side web application, or a native application, the end goal of using OAuth is the same: you’re trying to obtain an OAuth access token that your application can use to perform API requests on behalf of a user or the application itself.
After obtaining an access token, the token can be sent along with
your requests in one of several ways. The preferred method of
authorizing requests is by sending the access token in a HTTP
Authorization
header:
GET /tasks/v1/lists/@default/tasks HTTP/1.1 Host: www.googleapis.com Authorization: Bearer ya29.AHES6ZSzX
The Authorization
header is the preferred
mechanism because
The header is rarely logged by proxy servers and web server access logs.
The header is almost never cached.
The header doesn’t get stored in the browser cache when making requests from the client.
While the other mechanisms are defined in the specification, API providers are not required to implement any of these additional methods, so your mileage will vary:
Including the access_token
as a URL query
parameter is useful for debugging and when libraries make it
difficult to modify the Authorization
header.
This mechanism is also valuable when using the client-side flow
and sending a token in a JSONP request. For example,
https://www.googleapis.com/tasks/v1/lists/@default/tasks?callback=outputTasks&access_token=ya29.AHES6ZTh00gsAn4
This is a fallback mechanism for when an application cannot
modify the Authorization
header on requests. It
is only to be used when a HTTP body would normally be sent and can
then be added as an additional form parameter in an
application/ x-www-form-urlencoded
body. This
mechanism is not supported by the Google Tasks API.
Each of the client profiles needs to be accommodated with an appropriate protocol flow for obtaining authorization from the resource owner for access to their data. The core OAuth 2.0 protocol defines four primary “grant types” used for obtaining authorization and also defines an extension mechanism for enabling additional grant types.
This grant type is most appropriate for server-side web
applications. After the resource owner has authorized access to
their data, they are redirected back to the web application with
an authorization code as a query parameter in the URL. This code
must be exchanged for an access token by the client application.
This exchange is done server-to-server and requires both the
client_id
and client_secret
, preventing even the
resource owner from obtaining the access token. This grant type
also allows for long-lived access to an API by using refresh
tokens.
The implicit grant is the most simplistic of all flows, and is optimized for client-side web applications running in a browser. The resource owner grants access to the application, and a new access token is immediately minted and passed back to the application using a #hash fragment in the URL. The application can immediately extract the access token from the hash fragment (using JavaScript) and make API requests. This grant type does not require the intermediary “authorization code,” but it also doesn’t make available refresh tokens for long-lived access.
This grant type enables a resource owner’s username and password to be exchanged for an OAuth access token. It is used for only highly-trusted clients, such as a mobile application written by the API provider. While the user’s password is still exposed to the client, it does not need to be stored on the device. After the initial authentication, only the OAuth token needs to be stored. Because the password is not stored, the user can revoke access to the app without changing the password, and the token is scoped to a limited set of data, so this grant type still provides enhanced security over traditional username/password authentication.
The client credentials grant type allows an application to obtain an access token for resources owned by the client or when authorization has been “previously arranged with an authorization server.” This grant type is appropriate for applications that need to access APIs, such as storage services or databases, on behalf of themselves rather than on behalf of a specific user.
These additional flows are defined outside of the core spec:
The device profile was created to enable OAuth to be used on devices that do not have built-in web browsers or have limited input options—such as a game console or electronic photo frame. The user typically initiates the flow on the device and is then told to use a computer to access a website and approve access for the device by typing in an authorization code displayed in the device. Facebook has a great example of this flow referenced in its documentation.
This profile enables exchanging SAML 2.0 assertion for an OAuth access token. This is useful in enterprise environments that already have SAML authorization servers set up to control application and data access.
18.219.239.118