Security on the web

This document discusses web service security principles, using the OAuth 2.0 Authorization Framework.

This document was most recently updated in November, 2015. It is intended for entry-level web service programmers.

.

Web app security

In your second-year web programming courses, you learned how to implement security for a web app. How was that done?

First, you created an identity store. Credentials were defined, and maybe other account-related properties (name, age, etc.). The storage and credential management bits were also created.

Then, you created a form (or some other user interface) to gather credentials from the user. After validation, the response from the server would typically include an authorization cookie, and perhaps a response header.

.

Does this work for a web service?

Uh, not really.

Requests to a web service are made programmatically. Responses are typically JSON. Not HTML. So there’s no opportunity to present a user interface for authentication.

And there are other problems. The biggest problem is that the human user may not be directly using the resources published by the web service. Instead, a client app may be making requests on behalf of a human user.

.

What about “HTTP Basic Authentication” – will that work?

RFC 7235 defines “authentication” in the 723x series of RFCs. Should you use this scheme?

No.

Why? It requires the requestor to send their credentials with the request. That’s a problem.

Is there a solution?

Yes.

Don’t send credentials with the request. Instead, send an access token.

An access token is a digital asset, which contains descriptive information about the requestor, and therefore can represent the right to perform a task. It is generated when a requestor authenticates, and then is used to authorize access to a resource.

Refresh your memory… You do know these definitions already (right?), but here’s a refresher:

Authentication – sometimes abbreviated to AuthN – the process of presenting credentials that prove your identity.

Authorization – sometimes abbreviated to AuthZ – the process of determining whether a resource can be accessed.

.

A brief introduction to “access token”

An access token does NOT include credentials in any form.

An access token has a limited lifetime (although it can be refreshed).

There is no ‘standard’ format for the content of an access token. However, the JSON web token (JWT) is popular.

A requestor obtains an access token after authenticating with a token issuing server.

A resource server can ask the issuer whether the token is valid.

The access token is the digital asset that is used to authorize access to a web service resource. It includes information about the user, but does not include sensitive data or secrets.

How do we begin using access tokens in our web service? There are (at least) two approaches:

  1. Create your own design and infrastructure
  2. Take advantage of an existing framework or standard

Today, we will look at the second approach, by studying the OAuth 2 Authorization Framework.

.

So how do we handle security in 2015 and beyond?

This document describes the use of a web service to deliver resources to requestors. The web service’s resources will be protected, and requestors must use the OAuth 2.0 Authorization Framework. Two specific scenarios are described:

1. The first scenario covers the use case where a client app, which does not yet have a valid access token, requests a protected resource.

2. The second scenario covers the use case where a client app, which has a valid access token, requests a protected resource.

A separate client app, perhaps an iOS app, or an ASP.NET web app, would be used to request resources from the web service. Users of the client app will be able to request their own resources after authenticating.

.

OAuth 2.0 Authorization Framework information

The OAuth 2.0 Authorization Framework is described in RFC 6749. A related RFC 6750 covers access token usage.

A gentle overview of OAuth can be found in this Wikipedia article.

Justin Richer and Antonio Sanso have written a book, OAuth 2 In Action. A readable introduction and excerpt is here.

.

OAuth defines four roles:

oauth-resource-ownerResource owner

An entity (e.g. an end user, typically a human person, or a proxy such as credentials in a secure/trusted store) capable of granting access to a protected resource.

.

oauth-resource-serverResource server

A server that hosts a protected resource. It responds to requests by validating an access token.

.

oauth-client-appClient

Also known as a client app, this is an application that makes requests for a protected resource, on behalf of the (human) resource owner, and with its authorization.

.

oauth-authorization-serverAuthorization server

A server that authenticates resource owners, client apps, and issues access tokens.

.

OAuth does NOT define an identity management role. In other words, it does not concern itself with the design and maintenance of user accounts (whether human or programmatic).

In ASP.NET MVC based web apps and web services, ASP.NET Identity provides identity management services.

For a non-Microsoft approach, the OpenID Connect initiative, which does handle identity management, is often used with OAuth.

 

OAuth is a framework that enables a client app to use an access token to request a protected resource. The access token is issued to the client app by an authorization server, with the approval of the resource owner.

There are two defined types of client apps:

  1. Confidential – Capable of maintaining confidentiality of client app credentials. Includes server-based web apps and services. Also includes mobile device (e.g. iPhone) apps that are trusted by the device owner.
  2. Public – Not capable of maintaining confidentiality of client app credentials. Includes JavaScript apps and modules.

.

There are four defined flows or scenarios that enable a resource owner to authorize the issuance of an access token:

  1. Authorization code – A resource owner is able to authenticate directly with an authorization server, and passes on an “authorization code” to the client app.
  2. Implicit – For client apps which are implemented in a browser using a scripting language (such as JavaScript).
  3. Resource owner password credentials – Where there is a high degree of trust between the resource owner and the client app (e.g. a trusted client app on a resource owner’s trusted mobile device).
  4. Client credentials – For access to protected resources that are under the control of the client app (and not to any specific/individual resource owner).

.

Examples:

  1. Authorization code – Browser, with a ‘web app’ as a client (app)
  2. Implicit – Browser (or ‘web view’ object in a native app), with a non-confidential client (app), typically in JavaScript
  3. Resource owner password credentials – Trusted device, with a trusted client (app), typically on iOS and Android mobile devices
  4. Client credentials – A human is not directly involved; could be a component in one of the client (apps) above (e.g. sync, UI assets, etc.)

.

This document will cover the first flow/scenario, “authorization code”, with a “confidential” client.

A separate document will cover the “resource owner password credentials” flow/scenario, with a “confidential” client. That document will be useful to those who are writing an iOS or Android app.

.

Terminology and assumptions for the scenarios

This post uses terminology from the OAuth documents, plus the following terms:

UI = user interface

Web browser = an HTTP requestor application that renders HTML content

Client app = web app, an executable that runs on a web server (this is the OAuth ‘client’)

.

The following diagram is a high-level overview of the software components in the scenarios.

Web service as a resource server v2

.

The authorization server and the resource server share an authorization store. The authorization store holds the following kinds of information collections:

  • resource owner credentials
  • client app credentials (which has a client app identifier that will be used by the web browser)
  • authorization grant (which has a limited lifetime and scope)
  • access token (which has a limited lifetime and scope)

.

Notice that a client app is a distinct entity or construct. It must have its own identity that’s separate from a resource owner. A client app can be used by different resource owners.

.

For the following scenarios, the reader can assume that the resource owner credentials and the client app credentials already exist. Further, the authorization server has the programming, UI, and endpoints that enable the maintenance of these credentials.

The reader can also assume that the authorization server has the programming, UI, and endpoints that enable the maintenance of authorization grants and access tokens.

.

Scenario – first request for a protected resource

This scenario covers the use case where a client app, which does not yet have a valid access token, requests a protected resource.

This scenario is documented on a sequence diagram, shown below. Each signal is identified with a number in square brackets, [#], and you will find them in the text that follows.

.

How was this sequence diagram created? Click here and read this post for details. 

.

A human resource owner, using a web browser, begins interacting with content in a client app. This begins a new “session” between the resource owner‘s user-agent (the web browser), and the client app.

The resource owner performs an action (e.g. clicks on a link or a button) [1] in the web browser, which causes a “GET protected resource” request to be created. The web browser sends the request to the client app [2].

Note: The web browser does NOT typically have/show the protected resource URIs from the resource server. The client app typically publishes (HTML) links that are in its domain, and maintains the mapping/lookup in its executable code.

In other words, you will typically NOT see this kind of link in the HTML markup of the web browser:

http://resourceserver.com/customer/3/

Instead, you will see this kind of link:

http://clientapp.com/customer/3

.

The client app asks “does this session have a valid access token?”

The answer will be “no”, because this is the first request for a protected resource.

Next, the client app asks “does the request from the web browser have a valid authorization grant?”

Again, the answer will be “no” (because this is the first request for a protected resource).

Consequently, the following sequence will be initiated, which will result in the acquisition of a valid access token:

  1. The resource owner authenticates with the authorization server
  2. The authorization server delivers an authorization grant to the client app
  3. The client app requests that the authorization server exchange the authorization grant for an access token

.

Before continuing, the essence of the original “GET protected resource” request must be retained. The sequence (below) will include three (3) HTTP 302 redirects, and we will be unable to persist the original request in a query string parameter.

There are several state persistence schemes available to us. For example, the client app can save this information in session state. Or, it can be sent (in the following response) as a web browser cookie. Whatever scheme you select as the programmer, you just need to retrieve the value later, when you need it.

.

Sequence step 1: The resource owner authenticates with the authorization server

The client app responds back [3] to the web browser with the following:

  1. a 302 redirect status code
  2. a “location” header with the URI of the authorization server‘s authentication UI, and the following query string key-value pairs…
    • response_type=code – for a typical interaction
    • client_id= the client app identifier
    • redirect_uri= a previously-established (between the client app and the authorization server) “redirection endpoint”

.

The web browser creates a new request, [4] “GET authentication UI”, and sends it to the (above) URI of the authorization server‘s authentication UI.

Note: The authorization server‘s authentication UI may be a specially-created page/interface, solely for the use of resource owners who want to authorize a client app. Alternatively, it may be the page/interface that is used by other general interactive users of the resource server.

.

The authorization server validates the request (to ensure that all required key-value pairs are present), and responds with the authentication UI [5], which will typically be an HTML form. (The key-value pairs are retained, in the URI query string, or in the authorization server‘s state management and persistence system.)

.

The resource owner views the form [6], enters their credentials [7], and submits them (typically with a button click). The web browser creates a [8] “POST resource owner credentials” request, and sends the request to the authorization server.

After successfully authenticating, the authorization server responds back [9] to the web browser with the following:

  1. a 302 redirect status code
  2. a “location” header with the URI of the client app‘s redirection endpoint, and the following query string key-value pair…
    • code= the authorization grant (known as the authorization code) that was generated by the authorization server

.

Sequence step 2: The authorization server delivers an authorization grant to the client app

The web browser now has a valid authorization grant.

Using the URI from the response’s “location” header, the web browser creates a new request, [10] “GET authorization grant exchanged”, and sends it to the client app.

The client app inspects the request, which was received on the redirection endpoint, and asks “does the request from the web browser have a valid authorization grant?”

The answer will be “yes” (because a valid authorization grant was received on the redirection endpoint).

Before responding to the web browser, the client app continues with the following.

.

Sequence step 3: The client app requests that the authorization server exchange the authorization grant for an access token

A valid authorization grant can be exchanged for an access token. Therefore, the client app will create a new request, [11] “POST request access token“, and send it to the “token endpoint” on the authorization server. The request includes:

  1. an “authorization” header, which includes the client app credentials
  2. HTML form-encoded key-value pairs for the following parameters…
    • grant_type=authorization_code
    • code= the authorization grant (known as the authorization code) that was generated by the authorization server
    • redirect_uri=the previously-established (between the client app and the authorization server) redirection endpoint

.

The authorization server will inspect the request. It validates the client app credentials (with a lookup to the authorization store). It validates the authorization grant (with a lookup to the authorization store). If successful, it responds with an access token [12].

The access token consists of a number of parameters, serialized as a JSON object, in the message body of an HTTP 200 response. The parameters include:

  • access_token – string – the actual access token
  • token_type – string – for example, “bearer”
  • expires_in – integer, optional – the lifetime, in seconds, of the access token

.

Now that the client app has a valid access token, it typically persists it in session state.

The client app is now ready to respond to the “GET authorization grant exchanged” request from the web browser (in sequence step 2 above).

The client app creates a response [13] that includes the following information, and sends it to the web browser:

  1. a 302 redirect status code
  2. a “location” header with the URI of the original “GET protected resource” request (which may be retrieved from a web browser cookie, or the client app‘s session state)

.

Upon receipt, the web browser creates a [14] “GET protected resource” request, and sends it to the client app.

As above (when we started this journey), the client app asks “does this session have a valid access token?”

This time, the answer will be “yes”.

The client app creates a [15] “GET protected resource (with access token)” request, and sends it to the resource server. It includes:

  1. a request URI for the actual resource
  2. an “authorization” header that includes 1) the token_type, and 2) the access_token values

.

After validating the access token, the resource server responds back to the client app with the requested resource [16].

The client app now has the protected resource that was originally requested. The protected resource is rendered for the web browser [17], where it can be viewed [18] by the resource owner.

.

Scenario – subsequent requests for protected resources

This scenario covers the use case where a client app, which has a valid access token, requests a protected resource.

This scenario is documented on a sequence diagram, shown below. Each signal is identified with a number in square brackets, [#], and you will find them in the text that follows. The numbers used for the signals are the same as you saw in the first sequence diagram (but signals 3 through 14 inclusive aren’t there, because this scenario’s client app has a valid access token).

.

The resource owner performs an action (e.g. clicks on a link or a button) [1] in the web browser, which causes a “GET protected resource” request to be created. The web browser sends the request to the client app [2].

As above, the client app asks “does this session have a valid access token?”

As you would expect, the answer will be “yes”.

The client app creates a [15] “GET protected resource (with access token)” request, and sends it to the resource server. It includes:

  1. a request URI for the actual resource
  2. an “authorization” header that includes 1) the token_type, and 2) the access_token values

.

After validating the access token, the resource server responds back to the client app with the requested resource [16].

The client app now has the protected resource that was originally requested. The protected resource is rendered [17] for the web browser, where it can be viewed by the resource owner [18].

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: