Chapter 1. Introduction

How OAuth Was Born

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.

Google’s AuthSub approval screen, asking users for permission for their Google Calendar
Figure 1-1. Google’s AuthSub approval screen, asking users for permission for their Google Calendar

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.

Why Developers Should Care About OAuth

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.

Why Don’t These APIs Just Use Passwords for Authorization?

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:

Trust

A user may not trust providing their password to your application.

Decreased user sensitivity to phishing

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.

Expanded access and risk

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.

Limited reliability

When a user changes their password, your application no longer has access to their data.

Revocation challenges

The only way a user can revoke access to your application is by changing their password, which also revokes access to all other apps.

Passwords become required

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.

Difficulty implementing stronger authentication

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).

Terminology

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

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.

Federated Authentication

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

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

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.

Roles

There are several key actors in the OAuth protocol flows:

Resource server

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.

Resource owner

Typically the user of an application, the resource owner has the ability to grant access to their own data hosted on the resource server.

Client

An application making API requests to perform actions on protected resources on behalf of the resource owner and with its authorization.

Authorization server

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.

The Great Debate over Signatures

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.

Mitigating Concerns with Bearer Tokens

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

Signing Your OAuth 2.0 Requests

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.

Getting the key

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.

Making API requests

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.

Developer and Application Registration

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’s APIs Console for OAuth app registration
Figure 1-2. Google’s APIs Console for OAuth app registration

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:

Client ID

Specified as client_id when interacting with the resource server

Client Secret

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).

Why Is Registration Necessary?

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.

Client Profiles, Access Tokens, and Authorization Flows

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.

Client Profiles

OAuth 2.0 defines several important client profiles:

Server-side web application

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.

Client-side application running in a web browser

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.

Native application

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.

Access Tokens

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:

Query parameter

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
Form-encoded body parameter

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.

Authorization Flows

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.

Authorization code

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.

Implicit grant for browser-based client-side applications

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.

Resource owner password-based grant

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.

Client credentials

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:

Device profile

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.

SAML bearer assertion profile

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.181.36