blog single gear
Tutorials

How to Integrate an Application with Cloud Foundry using OAuth2

This article explains how to use Cloud Foundry APIs from a user application using the built in identity management solution in the User Account and Authentication Service (UAA). The UAA acts (amongst other things) as an OAuth 2.0 Authorization Server, granting access tokens to Client applications for them to use when accessing Resource Servers in the platform, such as the Cloud Controller. This article describes the responsibilities of a Client application and the mechanics of setting one up. It uses a simple example Client application (available on github), and recasts it into various forms to help developers with different language and tool preferences to get to grips with the topic (Ruby, Java, Grails).

Quick Introduction to OAuth2

In a typical OAuth2 scenario (as developed in the sample application) OAuth2 is a protocol with 4 main participants:

  1. Client application, often a web application
  2. Resource Owner, usually a User
  3. Resource Server (another web application or web service)
  4. Authorization Server

The User tells an Authorization Server that he trusts the Client to access the Resource Server on his behalf. In OAuth2 terms we are going to see a sample Client application in which the Authorization Server grants a bearer token to the Client using an Authorization Code flow. This scenario is composed of 4 steps:

  1. Client redirects User to Authorization Server /oauth/authorize to authorize a token grant
  2. Authorization Server authenticates the User and obtains his approval, redirecting back to the Client with a one-time Authorization Code
  3. Client contacts the Authorization Server directly at /oauth/token, exchanging the Authorization Code for an Access Token
  4. Client presents the Access Token in a request to Resource Server

Responsibilities of a Client Application

A Client application has these responsibilities:

  1. Register with the UAA and get a client id and secret
  2. Do not collect User credentials – delegate to the Login Server
  3. Send a unique state parameter with each request to the /oauth/authorize endpoint, and check it later in a callback
  4. Keep the Access Token and any associated Refresh Token a secret
  5. Watch out for access denied responses from the Resource Server and take appropriate action
  6. Use the Login server if there is one
  7. Don’t log the User out of Cloud Foundry unless they explicitly ask for it

Register With the UAA

A Client application must have a pre-existing relationship with the UAA. This is a standard OAuth2 feature, and is necessary to ensure that the platform can control access and give Users peace of mind that there is some control over the access to their data and applications.

When a Client registers with the UAA the owner or developer of the Client provides a redirect URI (or list of them) where it will accept callbacks from the UAA, and in return will get an id and a secret, and a list of scopes that it is allowed to access on behalf of a user. The sample application is registered in the local UAA by default with these properties:

{
  "client_id": "app",
  "client_secret": "appclientsecret",
  "scope": ["cloud_controller.read",
    "cloud_controller.write",
    "openid", ...],
  "redirect_uri": ["http://localhost"]
}

The scope values allow the client to operate the Cloud Controller (read and write) and to get the user’s profile data (“openid”). These are similar to the scopes granted to vmc in production. Note that if you were to register a client with the UAA on cloudfoundry.com you would expect the scopes would be limited by default (e.g. we would not normally expect Client applications to be able to change user’s passwords).

The redirect URI in the example above is actually not the value you will see in a local UAA by default: there it would be an empty list. An empty redirect URI in the client registration allows a client to request a redirect to any address, so this would not be allowed in production. In production a redirect is required to prevent an attack by a bad guy who might want to steal authorization codes or access tokens (see the earlier CSRF article for details of the attacks).

Client registrations on cloudfoundry.com are available on a case-by-case basis only at the moment, so please contact the Support Team ([email protected]) for help if you would like to try this in the real system. The Identity Team are also working on some features to automate client registration and open it up to more users, so keep an eye out on the cloudfoundry.org and cloudfoundry.com blog sites for news.

Authentication

When a Client registers with the UAA it will get an id and a secret which must be used any time a Client needs to authenticate itself with the platform. Principally this will be at the OAuth2 token endpoint /oauth/token, when exchanging an authorization code for an access token. The token endpoint requires a Client to send the id and secret in a standard HTTP Basic header, e.g.

POST /oauth/token HTTP/1.1
Authorization: Basic YXBwOmFwcGNsaWVudHNlY3JldA==

{
  access_token: FUYGKRWFG.jhdfgair7fylzshjg.o98q47tgh.fljgh,
  expires_in: 43200,
  client_id: app,
  scope: openid,cloud_controller.read
}

State Parameter

As protection against Cross Site Request Forgery (CSRF), the OAuth2 spec allows for a state parameter to be sent in the authorization request, and if it is there the Authorization Server sends it back in the callback that contains the authorization code. It is the Client’s responsibility to generate a value for the state and to assert that it issued that particular value when it comes back. The value of the state parameter should be unique (e.g. random), and not easily generated by an attacker. The Client can implement the state in one of two ways, either by storing the value in between the two requests as a key in a user session, or by encoding some information in it that can be verified when it sees it again (e.g. a unique id in a special format encrypted with a secret that only the Client knows).

When the callback comes to the Client application with an authorization code in the query parameters, the Client extracts the state parameter and verifies that it generated the value. If it cannot verify this then it should not proceed: an unrecognised state value can be a sign of a CSRF attack and it should be rejected.

In most cases Client applications will use a library to manage the authorization and token grant, and the library will take care of the state for you. It is the browser that actually sends both requests, the first to the Authorization Server, and the second to the Client application, so in principle a user session is available and that is normally the easiest way to implement the state check. Many of the libraries (e.g. omniauth-oauth2 as used in the Ruby sample, and Spring Security OAuth in the Java sample) do this for you. Some do not (e.g. Scribe as used in the Grails sample), in which case you should take care to add that feature to your application; i.e. it is not recommended to use the Grails sample as it is.

Using the Access Token

Once you have a token, your Client application can send it in a request header to protected resources on the platform. E.g. getting the current user’s profile information from the UAA:

GET /userinfo HTTP/1.1
Authorization: Bearer eYFDLKJHLKJ.DYOGFKHDLJDF.uIOFDUF

HTTP/1.1 200 OK
{
  "user_id":"ec5797e2-24dd-44c9-9e92-f03d0ef9d11e",
  "user_name":"marissa",
  "given_name":"Marissa",
  "family_name":"Bloggs",
  "name":"Marissa Bloggs",
  "email":"[email protected]"
}

Note that Cloud Foundry, unlike some older OAuth2 providers (e.g. Facebook), in general does not accept an access token as a request or form parameter. You must use the Authorization header, as recommended in the OAuth2 specification.

Responding to Unauthenticated or Access Denied Errors

If your access token is expired or invalid, you should see an HTTP 401 UNAUTHORIZED response from a protected resource. For example:

GET /userinfo HTTP/1.1
Authorization: Bearer GARBAGE

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="UAA/oauth", error="invalid_token", error_description="Invalid access token: GARBAGE"

{
  "error":"invalid_token",
  "error_description":"Invalid access token: "
}

The error response will tell the Client the difference between an expired or invalid token. In either case you can ask for a new one, and if the problem was an expiry then you might also have a refresh token that you can exchange for a new access token without needing to get the user’s approval again (the refresh token would have been granted at the same time as the original access token and it is the Client’s responsibility to hold on to it).

Or if the token has insufficient scope to access the resource you asked for, you should see an HTTP 403 FORBIDDEN. For example:

GET /Users HTTP/1.1
Authorization: Bearer eYFDLKJHLKJ.DYOGFKHDLJDF.uIOFDUF

HTTP/1.1 403 FORBIDDEN
WWW-Authenticate: Bearer error="insufficient_scope", error_description="Insufficient scope for this resource", scope="scim.read"
{
  "error":"insufficient_scope",
  "error_description":"Insufficient scope for this resource","scope":"scim.read"
}

In both cases there was a JSON body, and a WWW-Authenticate header to tell you what went wrong, and a little bit about how you can fix it. The fact that a Bearer token is required is indicated, and in the case of the scope issue, also the required scope that you are missing. Your client or user may not have permission to acquire a token with that scope, in which case there is nothing you can do, but in other cases the information is useful and you may be able to get another token that does what you need.

The example responses above are from UAA resources (i.e. APIs provided by the UAA itself). At the time of writing the 401 and 403 responses from the Cloud Controller may not resemble precisely the examples above, but they should be similar.

Requesting Scope for an Access Token

In the sample applications the tokens are all acquired without specifying a scope explicitly, so they have the default scopes allowed to the Client and User. This is always an option, but in general it is good practice for clients to only ask for tokens with a specific scope that allows them to do as much as they need but no more – e.g. do not ask for cloud_controller.write if you only need cloud_controller.read. This allows the UAA to alert the user specifically to what your application wants to do, and in turn they can make a better decision about whether or not to allow it. A user is more likely to grant permission for a third party application to read data than write it, for instance.

The Login Server

The Login server is a UI for the UAA in cloudfoundry.com whose features, design and implementation will be covered in a separate article. For the purposes of this article it suffices to say that a Client application should us the Login server if it is available for the OAuth2 /oauth/authorize endpoint. This ensures that applications authenticating with Cloud Foundry have a uniform user experience including seamless single sign on (SSO).

Logout

A Client application can have user sessions of its own (the sample implementations all do) and so it makes sense for it to have a logout feature. The Login Server (or UAA if there is none) has a logout endpoint as well (/logout.do), and if a Client application wants to it can provide a link to that endpoint, and specify a redirect to itself so that the User lands back in a familiar place after being logged out (see the sample application code for examples, e.g. /logout.do?redirect=http://myapp.cloudfoundry.com/loggedout). If the User clicks that link then he will clear his session with all Cloud Foundry applications, which might not be something he wanted to do. A Client application can and should present Users with the option to logout of Cloud Foundry, once they have logged out of the local session, but the User should be made aware of what they are doing if they follow that link.

The Sample Client Applications

The sample applications accompanying this article are designed to be as simple as possible – the minimum needed to get an interaction between a user and the Cloud Controller, mediated by a UAA bearer token. More complicated functionality should be easy to add, and there are libraries to help do that which we haven’t used in the samples just to keep them simple.

The roles played in the system are

  • Authorization Server = UAA
  • Resource Server = Cloud Controller (or a locally deployed fake)
  • Client = the sample application

All the implementations of the sample have the same features:

  • an authentication filter that only allows valid Cloud Foundry users to use the rest of the application
  • a home page that lists the properties of the currently authenticated user
  • an /apps page that lists the currently deployed applications of the current user in Cloud Foundry
  • a /logout link that clears the local session in the Client itself and then gives the user the option to also logout from Cloud Foundry

The authentication filter is responsible for acquiring an access token from the UAA and storing it in a local session, so it can be re-used without having to ask the UAA on every request (optional, but recommended). The filter also uses the token to build a representation of the User (so we can say “Hello” on the home page). It does this simply by sending it to the /userinfo endpoint on the UAA (a similar feature is available from virtually all OAuth2 providers, e.g. the /me endpoint at Facebook). In a real Client application the user data could be omitted if all you care about is the access token, or it could be used more extensively, e.g. to correlate with a local user database and assign additional, application-specific roles and permissions.

The /apps endpoint also uses the access token. It sends it to the /apps endpoint on the Cloud Controller, gets back a list of the user’s deployed applications, and then renders it. Obviously you could do more than that with the token to build out a richer application, and depending on the runtime or framework you are using there are tools available from Cloud Foundry to help you do that. So, for example, if your application is running on the JVM you can use the Cloud Foundry Java Client to interact with the Cloud Controller in a more convenient way than directly through the JSON endpoints. Similarly, if your application is in Ruby, then there is a Cloud Foundry Ruby Gem that you can use to do similar things.

In all cases you should inject the access token in the appropriate place in the library API and not have to collect user credentials, even though the libraries still support that (for a limited time).

Deploying the Sample

The samples can all be deployed locally for testing purposes, and the UAA instance defaults to one at http://localhost:8080/uaa. They also all default to using a fake Cloud Controller which is the API sample from the UAA repo. The fake Cloud Controller and the UAA can both be launched from the command line using Maven (see instructions in the UAA README):

$ git clone [email protected]:cloudfoundry/uaa.git
$ cd uaa
$ mvn install
$ cd samples/api
$ mvn tomcat:run -P integration

The samples also all work with the real UAA and the real Cloud Controller, but you need a client registration to make that work. If you have a real Cloud Foundry client you should use login.cloudfoundry.com for authentication and user approvals (this is the holder of the single-sign-on state for the platform) and uaa.cloudfoundry.com for the machine endpoints (principally /userinfo in this use case).

Appendix: Sample Implementation Details

The sample applications are in Github under an umbrella project. You can clone them using git:

$ git clone https://github.com/cfid/uaa-samples.git

or you can download the source code from the download link on the github website.

Ruby

The Ruby sample is written in sinatra which has a nice DSL for declaring web endpoints and filters. It uses omniauth-oauth2 to handle the OAuth2 Authorization Code flow and rest-client to access the Resource Servers. There is only one file app.rb and you can launch it from a command line like this (assuming you have Ruby 1.9.2 and bundle on your PATH):

$ bundle # do this once
$ ruby app.rb
...
>> Listening on 0.0.0.0:4567, CTRL+C to stop

The application is now running on http://localhost:4567.

Omniauth works by providing strategy implementations for specific token providers, and there isn’t a UAA strategy available officially yet, so the application adapts an existing abstract “oauth2” strategy. This strategy provides an endpoint at /auth/oauth2 which is where the redirect and callback to the UAA is handled for you. The main thing the application has to do is tell this endpoint the client credentials and also how to send them to the token endpoint on the UAA. The default behaviour of omniauth-oauth2 strategy follows an older specification than the one implemented by the UAA, so we have to do a bit of work to get the client_options and token_params in the form required. (Since the existing abstract strategy doesn’t match the UAA very well we think it might be better to implement an UAA strategy using the [UAA gem][UAAGEM]. We are exploring this possibility on the Cloud Foundry Identity Team, and we need to decide on the implementation before we publish an omniauth strategy for general use.)

The application responds to environment variables for picking up settings of the remote URLs etc:

  • UAA_LOGIN_SERVER = location of the Cloud Foundry Login Server where the Authorization endpoint lives. Defaults to the value of UAA_TOKEN_SERVER, but should be set to https://login.cloudfoundry.com in production.
  • UAA_TOKEN_SERVER = location of the UAA. Defaults to http://localhost:8080/uaa. In production use https://uaa.cloudfoundry.com.
  • CLOUD_CONTROLLER_SERVER = the Cloud Controller root URL. Defaults to http://localhost:8080/api. In production use https://api.cloudfoundry.com.
  • CLIENT_ID = the id in the Client registration. Defaults to app.
  • CLIENT_SECRET = the secret in the Client registration. Defaults to appclientsecret.

Grails

Grails is an opinionated web development and developer productivity tool that uses Groovy, Spring and a set of its own DSLs and conventions. Because of it’s heavy use of convention over configuration it is possible to build quite rich applications with relatively little code.

All the application logic is in HomeController.groovy and there is some configuration in Config.groovy and some properties files with names like application-*.;properties. To launch the application you can import it into a Grails aware IDE (like Spring Tool Suite), or run it on the command line (with Grails 2.1.1):

$ grails -Dgrails.server.port.http=9080 RunApp

The application shows up on [http://localhost:9080/grapps]. Here we show the application being launched on port 9080 so as not to clash with a UAA that you might be running locally. You could also run the UAA, API and Client applications all in the same container on port 8080 (e.g. by building war files and deploying them, or in the IDE with drag and drop).

The sample uses the Grails Scribe plugin to handle the Authorization Code flow. Scribe is quite rich, but too old to support well the most up to date versions of the OAuth2 specification, so we had to do quite a lot of work to make it work with the UAA. Once it is configured it works though and the rest of the Grails community seems to like the Scribe plugin for other OAuth providers like Facebook and Google.

The application responds to environment variables for picking up settings of the remote URLs etc:

  • UAA_PROFILE = a short name for the profile, which is converted into a properties file name to pick up the URL information needed. Default value is default, and properties files are provided for cloud and vcap profiles.
  • CLIENT_ID = the id in the Client registration. Defaults to app.
  • CLIENT_SECRET = the secret in the Client registration. Defaults to appclientsecret.

Java and Spring

The Spring sample uses Spring Security OAuth on the client side (as opposed to the server which is what the UAA is). The filter for authentication is a combination of a standard filter from Spring Security OAuth, and one from the UAA common JAR (a library used to build the UAA, but also useful for building Clients and Resource Servers).

The application logic is in TreeController.java, which uses a RestOperations to access the Cloud Controller API resources. The rest of the features are provided by Spring Security and are configured in the main Spring configuration file at WEB-INF/spring-servlet.xml. The main aspect of that which is important is the filter that handles authentication with the UAA:

<http ...>
    <intercept-url pattern="/**" access="hasRole(&#39;uaa.user&#39;)" />
    ...
    <custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" />
    <custom-filter ref="socialClientFilter" before="FILTER_SECURITY_INTERCEPTOR" />
</http>

With those filters in place the servlet request is automatically populated with a Principal object containing the user’s profile. Spring injects it into the HomeController so that the information can be displayed to the user in home.jsp. The oauth2ClientFilter is responsible for setting up the access token in a context that can be used by the RestOperations (which is an OAuth2RestTemplate) in HomeController.

To launch the application drop it into the same container as the UAA and API running locally (e.g. drag and drop in the IDE). Or run it on the command line separately using

$ mvn tomcat7:run -Dmaven.tomcat.port=9080

The application responds to environment variables for picking up settings of the remote URLs etc:

  • UAA_PROFILE = a short name for the profile, which is converted into a properties file name to pick up the URL information needed. Default value is empty, and properties files are provided for cloud and vcap profiles.
  • CLIENT_ID = the id in the Client registration. Defaults to app.
  • CLIENT_SECRET = the secret in the Client registration. Defaults to appclientsecret.