The Cloud Foundry Blog

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 (support@cloudfoundry.com) 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":"marissa@test.org"
}

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 git@github.com: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('uaa.user')" />
    ...
    <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.

About Dave Syer

Dave Syer is a member of the Cloud Foundry Identity Team, working on security and identity management solutions for cloudfoundry.com and other installations of the platform. He is an experienced enterprise architect, having worked mainly with Java and open source products, and also an active Spring Framework committer, and founder of the Spring Batch project.
This entry was posted in Cloud Foundry. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>