After SAML, a study of IAM needs to dig next into OAuth 2.0. It is NOT backward compatible with earlier OAuth versions, and an excellent historical introduction is here.) The official spec is RFC 6749, as well as the spec RFC 6750 for Bearer Token Usage. This post is to present an easy overview by working a specific and common example.
OAuth 2.0 is for authorization, but there is a rather clever extension, OpenID Connect, that provides authentication. They really should be just one standard, and I suggest learning them both in rapid succession.
One primary motivation for OAuth was to provide authorization for the many APIs that are provided vendors such as Google, Facebook, Linkedin, Twitter, and eBay to enhance and extend their products. These vendors view mobile devices as emerging to be the primary user interface, and hence much attention in OAuth is made to support a wide variety of such devices with varying capabilities and security profiles.
OAuth 2.0 has four actors:
- Client C = the application making protected resource requests on behalf of the resource owner and with its authorization. C is a client both of the resource server RS and of the authentication server AS.
- Authorization Server AS = the server issuing access tokens to the client after successful authentication of the resource owner and obtaining authorization. AS has separate authorization and token endpoints.
- Resource Server RS = API = the server hosting the protected resources. RS is capable of accepting and responding to protected resource requests that use access tokens.
- Resource Owner RO = an entity capable of granting access to a protected resource. When the RO is a person, RO = end user.
Clients. The popularity of OAuth stems from the huge variety of client applications directly supported. Individual implementations of authorization servers vary in how they support clients, but the spec gives some guidance. There are two broad client types, confidential and public. Confidential clients are capable of maintaining the confidentiality of their credentials and can authenticate securely. Public clients cannot, e.g. executing on a device used by the RO that is incapable of secure client authentication. The AS should assume the client is public until it meets the AS’s criteria for secure authentication. E.g.,
- A web application that is a confidential client running on a web server. An RO accesses the client application via a browser on the device used by the RO. Client credentials and access tokens are stored on the web server and are not accessible by the RO.
- A user agent based application is a public client in which the client code is downloaded from a web server and executes within a browser on the device used by the RO. Protocol data and credentials are accessible to the RO.
- A native application is a public client installed and executed on the device used by the RO. Protocol data and credentials are accessible to the RO, but are protected from other servers and applications.
Client Registration. Before initiating a request for data, a client application registers (over TLS) with the AS, typically with an HTML form filled out by some end-user. This mechanism is not defined by OAuth. The point here, however, is to establish trust by exchanging credentials and to identify client attributes such as the redirection URIs and client type. The trust established must be acceptable not only to the AS but also to any relying resource server that accepts AS access tokens. Registration can be accomplished using a self-issued or third-party-issued assertion, or by the AS performing client discovery using a trusted channel.
A client identifier is issued by the AS to the client at the time of registration. It is a string, unique to the AS and to the client. Each client registration record in the AS typically includes:
- client identifier (the key to this record) = client_id REQUIRED
- client password
- client public key
- client secret = client_secret REQUIRED
- list of redirection URIs
- other attributes required by the AS: application name, website, description, logo image, acceptance of legal terms, etc.
- client type
If the client is implemented as a distributed set of components, each with a different client type and security context, e.g. a confidential server-based component and a public browser-based component, then the AS must either have specific support for such a client, or should register each component as a separate client. This flexibility of a particular AS can be a competitive advantage for it.
OAuth gives some additional security guidance to the three examples of clients mentioned above. Web applications, confidential clients accessed by the RO via a browser, should store their access tokens on the web server in a way not exposed to or accessible by the resource owner. User-agent-based applications, public clients whose code is downloaded from a web server, should make use of the user-agent capabilities when requesting authorization and storing tokens. These are accessible to the RO. Native applications, installed and executed on the RO’s device, have protocol data and credentials accessible to the RO. Native applications should protect these data and tokens from hostile servers and other applications, even those that execute on the same device.
The registration process must also include RO and RS registration. It includes the authorization endpoint that the client uses to obtain an authorization grant. Each RO registration record in the AS should contain:
- public key
- certification of authenticity
- session cookie info
- authorization endpoint (“application/x-www-form-urlencoded”)
- URI for the associated RS
- access token requirements for RS
As mentioned above, one of the things that makes OAuth 2.0 popular is its flexibility to support a wide variety of devices from traditional workstations and servers to Internet enabled devices such mobile phones and wrist watches. The protocol flow for various instances of device varies in order to deal with various client capabilities. The spec gives some guidance, but the implementations vary. The additional layer OpenID Connect addresses this in more detail.
A typical protocol flow is the one specified for a confidential client C requesting authorization for a specific resource on RS:
- C requests authorization from RO
- C receives authorization grant from RO
- C sends authorization grant to AS
- C receives access token from AS
- C sends access token to RS
- C receives protected resource from RS
It is required that these exchanges use TLS.
A. In this example, the authorization request in (A) is made directly to RO. Without sending its client_secret, C sends and the RO receives this request as a JSON object that includes:
- a list of redirection URIs via the “redirect_uri” request parameter which must be registered with the AS and formatted using the “application/x-www-form-urlencoded” format.
- This request may include a “state” parameter and value.
- A client_id obtained during registration of the client.
- An authorization request number
- Authorization Endpoint
- Response/Grant type requested. REQUIRED. Since there are multiple authorization grant types, there is some variation on authorization requests. Cf. grant types below.
B,C. The authorization grant in (B) and (C) is one of the following four predefined grant types or an extension/custom grant type private to this particular AS:
- Authorization Code – Used when the AS is an intermediary between C and RO
- resource owner password credential – username/password is the auth. Code to get an access token
- client credentials – used as a grant when the client C is acting on its own behalf
- extension/custom grants
B. The Resource Owner might not have the capabilities to process the request or to form the grant. In this case the RO forwards the request to the AS which returns the grant to the RO after processing. The RO then returns the grant to the client C. A good example here is when the RO is an end user with a small mobile device, and the RO, running an application on C, asks C to do something such as print a photo owned by RO but stored in the cloud. C says, ok, but I need access to the photo, and starts step (A) with a resource request. Since the request contains the authorization endpoint, the RO can immediately forward the request to the named AS which can do all the processing needed to produce the grant. (The perspicacious reader might ask, well if the grant gets sent to C in step (B) and then back to AS in step (C) with a request for an access token, why doesn’t AS just return an access token? The point is to formally separate the steps that require client credentials from the steps that require RO credentials.)
B,C. Note authorization grants do not include RO credentials. As our example, let’s look at the Authorization Code grant type. It is a JSON object containing at least:
- grant type, in this case, grant_type: authorization
- authorization end point
- client id
- RO id
- requested scope
- local state
- redirection URI
- the client generated authorization request number
D. AS authenticates C and validates the grant. If valid, AS issues an access token as well as a refresh token. A synonym for access token is bearer token. It is also called a “valet key”, because it provides limited access to resources much like a valet key for an automobile. These tokens are JSON objects defined by RFC 6750 containing:
- Type name: Bearer
- grant type
- client ID
- timestamp when issued
- validity time for this token in seconds beyond timestamp
- original client generated authorization request number
- authorization code (unique number)
- authorization end point
- RO id
- RS id
- RS endpoint
- signature of the AS
- refresh token number
These token attributes are not fully specified by the spec. Anybody in possession of this token will be given access to the protected resources by the RS. Thus, tokens should be protected from disclosure both in storage and in transit.
E. The client C requests the protected resource from RS by presenting the access token for authorization.
F. RS validates access token by checking scope and validation (expiration) date, and serves request.
An example of such an access token is:
HTTP/1.1 200 OK
If the token has expired, C submits the refresh token, its client_id, and its client_secret to AS to get a new access token, and then C repeats (E) and (F).
When an RO provides a distinct C with access to resources, this access is authorized by AS and provided by RS. I think of AS as being a big flat space supported by three legs C, RO, and RS. This is dubbed a “three legged flow”. When is client equals the resource owner (or is entrusted with the RO’s credentials), then the roles of C and RO collapse, and we have a “two legged flow.” This special case can be handled by a resource owner password credential grant type or a client credential grant type.
Finally, quite a number of security concerns are addressed in OAuth 2.0 Threat Model and Security Considerations [RFC 6819]. These security concerns are also discussed in OpenID Connect which is my next post here.
Tags: Authentication, Authorization, authorization grant, authorization scope, Authorization Server, bearer token, Confidential Client, JSON, native application, OpenID Connect, Resource Owner, Resource Server, RFC 6749, RFC 6750, RFC 6819, SAML, TLS, user agent based application, web application