LATEST VERSION: 1.9 - CHANGELOG
Pivotal Cloud Foundry v1.9

User Account and Authentication (UAA) Server

Page last updated:

The UAA is the identity management service for Cloud Foundry. Its primary role is as an OAuth2 provider, issuing tokens for client applications to use when they act on behalf of Cloud Foundry users. In collaboration with the login server, it can authenticate users with their Cloud Foundry credentials, and can act as an SSO service using those credentials (or others). It has endpoints for managing user accounts and for registering OAuth2 clients, as well as various other management functions.

Quick Start

Deploy Locally

To start, fetch the UAA from Git, then build and run all of the components that comprise the UAA and the example programs (uaa, samples/api, and samples/app) with a single invocation of Gradle:

$ git clone git://github.com/cloudfoundry/uaa.git
$ cd uaa
$ ./gradlew run

If successful, the three apps will run together on a single instance of Tomcat listening on port 8080, with endpoints /uaa, /app, and /api.

Deploy to Cloud Foundry

You can also build the app and push it to Cloud Foundry:

$ ./gradlew :cloudfoundry-identity-uaa:war
$ cf push MYUAA -m 512M -p uaa/build/libs/cloudfoundry-identity-uaa-1.8.0.war --no-start
$ cf set-env MYUAA SPRING_PROFILES_ACTIVE default
$ cf start MYUAA

In the steps above, replace the following:

  • MYUAA with a unique application name
  • 1.8.0 with the appropriate version label from your build

Local Command Line Usage

  1. Run the UAA server as described above:

    $ cd uaa
    $ ./gradlew run
    
  2. Start another terminal. From the project base directory, query the login endpoint about the system:

    $ curl -H "Accept: application/json" localhost:8080/uaa/login
    {
      "timestamp":"2012-03-28T18:25:49+0100",
      "app" : {"version":"1.8.3"},
      "commit_id":"cba0958",
      "prompts":{"username":["text","Email"],
        "password":["password","Password"]
      }
    }
    
  3. Log in with the UAA Ruby gem:

    $ gem install cf-uaac
    $ uaac target http://localhost:8080/uaa
    $ uaac token get marissa koala
    

    If you do not specify username and password, you will be prompted to supply them.

    This authenticates and obtains an access token from the server using the OAuth2 implicit grant, similar to the approach intended for a standalone client like the cf CLI. The token is stored in ~/.uaac.yml. Open ~/.uaac.yml to obtain the access token for your cf target, or use --verbose on the login command line above to see it in the command shell.

  4. Log in as a resource server and retrieve the token details:

    $ uaac target http://localhost:8080/uaa
    $ uaac token decode [token-value-from-above]
    

    You should see your username and the client id of the original token grant on STDOUT:

      jti: e3a7d065-8514-43c2-b1f8-f8ab761791e2
      sub: f796d1a2-eca3-4079-a317-f3224f8f7832
      scope: scim.userids password.write openid cloud_controller.write cloud_controller.read
      client_id: cf
      cid: cf
      user_id: f796d1a2-eca3-4079-a317-f3224f8f7832
      user_name: marissa
      email: marissa@example.org
      iat: 1413495264
      exp: 1413538464
      iss: http://localhost:8080/uaa/oauth/token
      aud: scim openid cloud_controller password
    

Remote Command Line Usage

The command line example in the previous section should work against the UAA, although token encoding is unnecessary as you will not have the client secret.

In this case, there is no need to run a local UAA server. Query the external login endpoint about the system:

$ curl -H "Accept: application/json" uaa.run.pivotal.io/login
{
  "timestamp":"2014-09-15T18:25:04+0000",
  "app":{"version":"1.8.3"},
  "commit_id":"git-metadata-not-found",
  "prompts":{"username":["text","Email"],
             "password":["password","Password"]
  }
}

You can then try logging in with the UAA Ruby gem. Make sure you have Ruby 1.9, then:

$ gem install cf-uaac   # If you have not already installed cf-uaac
$ uaac target uaa.run.pivotal.io
$ uaac token get [yourusername] [yourpassword]

If you do not specify a username and password, you will be prompted to supply them.

This authenticates and obtains an access token from the server using the OAuth2 implicit grant, which is the same grant that a client like the cf CLI uses.

Integration Tests

Run the integration tests with the following command:

$ ./gradlew integrationTest

This starts a UAA server running in a local Apache Tomcat instance. By default, the service URL is set to http://localhost:8080/uaa.

You can set the environment variable CLOUD_FOUNDRY_CONFIG_PATH to a directory containing a uaa.yml file in which the various URLs used in the tests are changed, and the UAA server context root may be set.

Custom YAML Configuration

To modify the runtime parameters you can provide a uaa.yml, as shown in the following example:

$ cat > /tmp/uaa.yml
uaa:
  host: uaa.appcloud21.dev.mozycloud
  test:
    username: dev@cloudfoundry.org # defaults to vcap_tester@vmware.com
    password: changeme
    email: dev@cloudfoundry.org

Then from uaa/uaa:

    $ CLOUD_FOUNDRY_CONFIG_PATH=/tmp ./gradlew test

The webapp looks for a YAML file in the following locations (later entries override earlier ones) when it starts up.

    classpath:uaa.yml
    file:${CLOUD_FOUNDRY_CONFIG_PATH}/uaa.yml
    file:${UAA_CONFIG_FILE}
    ${UAA_CONFIG_URL}

Test with PostgreSQL or MySQL

The default UAA unit tests (./gradlew test) use hsqldb.

To run the unit tests using PostgreSQL:

$ echo "spring_profiles: default,postgresql" > src/main/resources/uaa.yml
$ ./gradlew test integrationTest

To run the unit tests using MySQL:

$ echo "spring_profiles: default,mysql" > src/main/resources/uaa.yml
$ ./gradlew test integrationTest

The database configuration for the common and scim modules is located at common/src/test/resources/(mysql|postgresql).properties and scim/src/test/resources/(mysql|postgresql).properties.

UAA Projects

There are several projects: the main uaa server application, and some samples:

  • common is a module containing a JAR with all the business logic. It is used in the webapps below.

  • uaa is the UAA server. uaa provides an authentication service plus authorized delegation for back-end services and apps by issuing OAuth2 access tokens.

  • api (sample) is an OAuth2 resource service which returns a mock list of deployed apps. api is a service that provides resources that other applications might want to access on behalf of the resource owner.

  • app (sample) is a user application that uses both of the above. app is a webapp that needs single sign-on and access to the api service on behalf of users.

  • scim is the SCIM user management module used by UAA.

UAA Server

The authentication service is uaa. It is a plain Spring MVC webapp. Deploy as normal in Tomcat or your container of choice, or execute ./gradlew run to run it directly from the uaa directory in the source tree. When running with Gradle, it listens on port 8080 and the URL is http://localhost:8080/uaa.

The UAA Server supports the APIs defined in the UAA-APIs document. To summarize:

  1. The OAuth2 /authorize and /token endpoints

  2. A /login_info endpoint to allow querying for required login prompts

  3. A /check_token endpoint, to allow resource servers to obtain information about an access token submitted by an OAuth2 client.

  4. SCIM user provisioning endpoint

  5. OpenID connect endpoints to support authentication /userinfo and /check_id (todo). Implemented roughly enough to get it working (so /app authenticates here), but not to meet the spec.

Command line clients can perform authentication by submitting credentials directly to the /authorize endpoint. There is an ImplicitAccessTokenProvider in Spring Security OAuth that can do the heavy lifting if your client is Java.

By default, uaa will launch with a context root /uaa.

Configuration

There is a uaa.yml file in the application which provides defaults to the placeholders in the Spring XML. Wherever you see ${placeholder.name} in the XML, there is an opportunity to override it either by providing a System property (-D to JVM) with the same name, or a custom uaa.yml (as described above).

All passwords and client secrets in the config files are plain text, but they will be inserted into the UAA database encrypted with BCrypt.

User Account Data

The default is to use an in-memory RDBMS user store that is pre-populated with a single test user: marissa with password koala.

To use Postgresql for user data, activate the Spring profile postgresql.

You can configure the active profiles in uaa.yml using:

spring_profiles: postgresql,default

To use PostgreSQL instead of HSQL:

$ echo "spring_profiles: postgresql,default" > src/main/resources/uaa.yml
$ ./gradlew run

To bootstrap a microcloud-type environment, you need an admin client; there is a database initializer component that inserts one. If the default profile is active (i.e. not postgresql), there is also a cf CLI client so that the gem login works out of the box. You can override the default settings and add additional clients in uaa.yml:

oauth:
  clients:
    admin:
      authorized-grant-types: client_credentials
      scope: read,write,password
      authorities: ROLE_CLIENT,ROLE_ADIN
      id: admin
      secret: adminclientsecret
      resource-ids: clients

You can use the admin client to create additional clients. You will need a client with read/write access to the scim resource to create user accounts. The integration tests take care of this automatically by inserting client and user accounts as necessary to make the tests work.

Sample Applications

Two sample applications are included with the UAA: /api and /app.

Run them with ./gradlew run from the uaa root directory. All three apps, /uaa, /api, and /app get deployed simultaneously.

The API Sample Application

An example resource server. It hosts a service that returns a list of mock applications under /apps.

The App Sample Application

This is a user interface app (primarily aimed at browsers) that uses OpenId Connect for authentication (i.e. SSO) and OAuth2 for access grants. It authenticates with the Auth service, then accesses resources in the API service. Run it with ./gradlew run from the uaa root directory.

The application can operate in multiple different profiles according to the location (and presence) of the UAA server and the Login application. By default, the application looks for a UAA on localhost:8080/uaa, but you can change this by setting an environment variable (or System property) called UAA_PROFILE. In the application source code (samples/app/src/main/resources), you will find multiple properties files pre-configured with different likely locations for those servers. They are all in the form application-UAA_PROFILE.properties. The naming convention adopted is that the UAA_PROFILE is local for the localhost deployment, vcap for a vcap.me deployment, and staging for a staging deployment. The profile names are double-barreled (e.g. local-vcap when the login server is in a different location than the UAA server).

Use Cases
  1. See all apps

    GET /app/apps
    

    Browser is redirected through a series of authentication and access grant steps (which could be slimmed down to implicit steps not requiring user at some point), and then the photos are shown.

  2. See the currently logged in user details, a bag of attributes grabbed from the open id provider

    GET /app
    

Login Application

A user interface for authentication. The UAA can also authenticate user accounts, but only if it manages them itself, and it only provides a basic UI. You can brand and customize the login app for non-native authentication and for more complicated UI flows, like user registration and password reset.

The login application is itself an OAuth2 endpoint provider, but delegates those features to the UAA server. Therefore, configuration for the login application consists of locating the UAA through its OAuth2 endpoint URLs and registering the login application itself as a client of the UAA. There is a login.yml for the UAA locations, such as for a local vcap instance:

uaa:
  url: http://uaa.vcap.example.net
  token:
    url: http://uaa.vcap.example.net/oauth/token
  login:
    url: http://uaa.vcap.example.net/login.do

There is also an environment variable (or Java System property), LOGIN_SECRET, for the client secret that the app uses when it authenticates itself with the UAA. The login app is registered by default in the UAA only if there are no active Spring profiles. In the UAA, the registration is located in the oauth-clients.xml config file:

id: login
secret: loginsecret
authorized-grant-types: client_credentials
authorities: ROLE_LOGIN
resource-ids: oauth

Use Cases

  1. Authenticate

    GET /login
    

    The sample app presents a form login interface for the backend UAA, and also an OpenID widget so the user can authenticate using Google credentials or others.

  2. Approve OAuth2 token grant

    GET /oauth/authorize?client_id=app&response_type=code...
    

    Standard OAuth2 Authorization Endpoint. The UAA handles client credentials and all other features in the back end, and the login application is used to render the UI (see access_confirmation.jsp).

  3. Obtain access token

    POST /oauth/token
    

    Standard OAuth2 Authorization Endpoint passed through to the UAA.

Scopes

UAA covers multiple scopes of privilege, including access to UAA, access to Cloud Controller, and access to the router.

See the tables below for a description of the scopes covered by UAA:

UAA Scopes

Scope Description
uaa.user This scope indicates that this is a user. It is required in the token if submitting a GET request to the OAuth 2 /authorize endpoint.
uaa.none This scope indicates that this client will not be performing actions on behalf of a user.
uaa.admin This scopes indicates that this is the superuser.
scim.write This scope gives admin write access to all SCIM endpoints, /Users, and /Groups.
scim.read This scope gives admin read access to all SCIM endpoints, /Users, and /Groups.
scim.create This scope gives the ability to create a user with a POST request to the /Users endpoint, but not to modify, read, or delete users.
scim.userids This scope is required to convert a username and origin into a user ID and vice versa.
scim.invite This scope is required to participate in invitations using the /invite_users endpoint.
groups.update This scope gives the ability to update a group. This ability can also be provided by the broader scim.write scope.
password.write This admin scope gives the ability to change a user’s password.
openid This scope is required to access the /userinfo endpoint. It is intended for OpenID clients.
idps.read This scope gives read access to retrieve identity providers from the /identity-providers endpoint.
idps.write This scope gives the ability to create and update identity providers from the /identity-providers endpoint.
clients.admin This scope gives the ability to create, modify, and delete clients.
clients.write This scope is required to create and modify clients. The scopes are prefixed with the scope holder’s client ID. For example, id:testclient authorities:client.write gives the ability to create a client that has scopes with the testclient. prefix. Authorities are limited to uaa.resource.
clients.read This scope gives the ability to read information about clients.
clients.secret This admin scope is required to change the password of a client.
zones.read This scope is required to invoke the /identity-zones endpoint to read identity zones.
zones.write This scope is required to invoke the /identity-zones endpoint to create and update identity zones.
scim.zones This is a limited scope only allows adding a user to or removing a user from zone management groups under the path /Groups/zones.
oauth.approval /approvals endpoint. This scope is required to be able to approve or reject clients in order to act on a user’s behalf. This is a default scope defined in uaa.yml.
oauth.login This scope is used to indicate a login application, such as external login servers, to perform trusted operations, such as create users not authenticated in the UAA.
approvals.me This scope is not currently used.
uaa.resource This scope indicates that this is a resource server, used for the /check_token endpoint.
zones.ZONE-ID.admin This scope permits operations in a designated zone by authenticating against the default zone, such as create identity providers or clients in another zone. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.read This scope permits reading the given identity zone. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.clients.admin This scope translates into clients.admin after zone switch is complete. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.clients.read This scope translates into clients.read after zone switch is complete. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.clients.write This scope translates into clients.write after zone switch is complete. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.clients.scim.read This scope translates into scim.read after zone switch is complete. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.clients.scim.create This scope translates into scim.create after zone switch is complete. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.clients.scim.write This scope translates into scim.write after zone switch is complete. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.idps.read This scope translates into idps.read after zone switch is complete. This scope is used with the X-Identity-Zone-Id header.

Cloud Controller Scopes

Scope Description
cloud_controller.read This scope gives the ability to read from any Cloud Controller route the token has access to.
cloud_controller.write This scope gives the ability to post to Cloud Controller routes the token has access to.
cloud_controller.admin This admin scope gives full permissions to Cloud Controller.
cloud_controller.admin_read_only This admin scope gives read permissions to Cloud Controller.
cloud_controller.permissions

Routing Scopes

Scope Description
routing.routes.read This scope gives the ability to read the full routing table from the router.
routing.routes.write This scope gives the ability to write the full routing table from the router.
routing.router_groups.read This scope gives the ability to read the full list of routing groups.
routing.router_groups.write This scopes gives the ability to write the full list of routing groups.

Other Scopes

Scope Description
doppler.firehose This scope gives the ability to read logs from the Loggregator Firehose endpoint.
notifications.write This scope gives the ability to send notifications through the Notification Service.
Was this helpful?
What can we do to improve?
View the source for this page in GitHub