This topic tells you about the User Account and Authentication (UAA) Server, the identity management service for VMware Tanzu Application Service for VMs (TAS for VMs).

The primary role of UAA is as an OAuth2 provider, that issues tokens for client apps to use when they act on behalf of TAS for VMs users. In collaboration with the login server, UAA can authenticate users with their TAS for VMs credentials, and can act as an SSO service using those, or other, credentials.

UAA has endpoints for managing user accounts, registering OAuth2 clients, and various other management functions.

Different runtimes and services use separate UAA instances. TAS for VMs has two UAA instances by default: one for BOSH Director, used to bootstrap the rest of the TAS for VMs deployment; and one for the BOSH deployment, used as a shared resource by all apps that require user authentication. This is the minimum number of UAA instances TAS for VMs must have. Other runtimes and services also have UAA instances. These instances are separate from each other. If you log into one runtime or service, you are not also logged into other runtimes and services that authenticate using UAA. You must log in to each runtime or service separately.

You can deploy UAA locally or to TAS for VMs.

Deploying UAA locally

To deploy and run UAA locally:

  1. In a terminal window, clone the UAA GitHub repository by running:

    git clone git://github.com/cloudfoundry/uaa.git
    
  2. Go to the directory where you cloned the UAA GitHub repository.

  3. To build and run all the components that comprise UAA and the example programs uaa, samples/api, and samples/app, run:

    ./gradlew run
    
  4. If successful, the three apps run together on a single instance of Tomcat listening on port 8080, with endpoints /uaa, /app, and /api. Tomcat is a library of Java code used by UAA to create its features. For more information, see the Apache Tomcat website.

Using local UAA

To access and use a locally deployed UAA server:

  1. Run the UAA server as described in Deploy Locally.

  2. Open another terminal window. From the project base directory, run curl localhost:8080/uaa/info -H "Accept: application/json" to confirm the UAA is running. You can see basic information about the system. For example:

    $ curl localhost:8080/uaa/info -H "Accept: application/json"
    {
      "app": {
        "version": "4.19.0"
      },
      "links": {
        "uaa": "http://localhost:8080/uaa",
        "passwd": "/forgot_password",
        "login": "http://localhost:8080/uaa",
        "register": "/create_account"
      },
      "zone_name": "uaa",
      "entityID": "cloudfoundry-saml-login",
      "commit_id": "af93628",
      "idpDefinitions": {},
      "prompts": {
        "username": [
          "text",
          "Email"
        ],
        "password": [
          "password",
          "Password"
        ]
      },
      "timestamp": "2018-05-25T15:34:31-0700"
    }
    
  3. To install the TAS for VMs UAA Command Line Client (UAAC) Ruby gem, run:

    gem install cf-uaac
    
  4. To target the local UAA server endpoint, run:

    uaac target http://localhost:8080/uaa
    
  5. Run uaac token client get CLIENT_NAME -s CLIENT_SECRET to obtain an access token. Replace CLIENT_NAME and CLIENT_SECRET with actual values. For example, when starting up the UAA locally for development, you must have a predefined admin client to use:

    uaac token client get admin -s adminsecret
    

    If you run the command without -s CLIENT_SECRET, UAAC shows an interactive prompt where you must create the client secret value. The uaac token client get command requests an access token from the server using the OAuth2 client credentials grant type. For more information about the OAuth2 client credentials, see Client Credentials in the OAuth 2.0 Authorization Framework.

  6. View your UAAC token context. When UAAC obtains a token, the token and other metadata is stored in the ~/.uaac.yml file on your local machine. To view the token you have obtained, run uaac context. For example:

    $ uaac context
    [0]*[http://localhost:8080/uaa]
    
    [0]*[admin]
      client_id: admin
      access_token: eyJhbGciOiJIUzI1NiIsImtpZCI6ImxlZ2FjeS10b2tlbi1rZXkiLCJ0eXAiOiJKV1QifQ.eyJqdGkiOiIxOWYyNWU2Y2E5Y2M0ZWIyYTdmNTAxNmU0NDFjZThkNCIsInN1YiI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiY2xpZW50cy5yZWFkIiwiY2xpZW50cy5zZWNyZXQiLCJjbGllbnRzLndyaXRlIiwidWFhLmFkbWluIiwiY2xpZW50cy5hZG1pbiIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiXSwic2NvcGUiOlsiY2xpZW50cy5yZWFkIiwiY2xpZW50cy5zZWNyZXQiLCJjbGllbnRzLndyaXRlIiwidWFhLmFkbWluIiwiY2xpZW50cy5hZG1pbiIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiXSwiY2xpZW50X2lkIjoiYWRtaW4iLCJjaWQiOiJhZG1pbiIsImF6cCI6ImFkbWluIiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInJldl9zaWciOiIyNjcxOTlkMSIsImlhdCI6MTUyODIzMjAxNywiZXhwIjoxNTI4Mjc1MjE3LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdWFhL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbInNjaW0iLCJjbGllbnRzIiwidWFhIiwiYWRtaW4iXX0.L2cn6HqLQAEyqTrYYkL9Al_8JyfwB330er7DshUb9wg
      token_type: bearer
      expires_in: 43199
      scope: clients.read clients.secret clients.write uaa.admin clients.admin scim.write scim.read
      jti: 19f25e6ca9cc4eb2a7f5016e441ce8d4
    
    Copy the access token from this output for the next step.
  7. Run uaac token decode ACCESS-TOKEN-VALUE to view information in the token, which is encoded using the JSON Web Token (JWT) format. Replace ACCESS-TOKEN-VALUE with your access token, copied from the uaac context output. The UAAC displays all the claims inside the token body. For example:

    $ uaac token decode eyJhbGciOiJIUzI1NiIsImtpZCI6ImxlZ2FjeS10b2tlbi1rZXkiLCJ0eXAiOiJKV1QifQ.eyJqdGkiOiIxOWYyNWU2Y2E5Y2M0ZWIyYTdmNTAxNmU0NDFjZThkNCIsInN1YiI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiY2xpZW50cy5yZWFkIiwiY2xpZW50cy5zZWNyZXQiLCJjbGllbnRzLndyaXRlIiwidWFhLmFkbWluIiwiY2xpZW50cy5hZG1pbiIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiXSwic2NvcGUiOlsiY2xpZW50cy5yZWFkIiwiY2xpZW50cy5zZWNyZXQiLCJjbGllbnRzLndyaXRlIiwidWFhLmFkbWluIiwiY2xpZW50cy5hZG1pbiIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiXSwiY2xpZW50X2lkIjoiYWRtaW4iLCJjaWQiOiJhZG1pbiIsImF6cCI6ImFkbWluIiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInJldl9zaWciOiIyNjcxOTlkMSIsImlhdCI6MTUyODIzMjAxNywiZXhwIjoxNTI4Mjc1MjE3LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdWFhL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbInNjaW0iLCJjbGllbnRzIiwidWFhIiwiYWRtaW4iXX0.L2cn6HqLQAEyqTrYYkL9Al_8JyfwB330er7DshUb9wg
    
    Note: no key given to validate token signature
    
      jti: 19f25e6ca9cc4eb2a7f5016e441ce8d4
      sub: admin
      authorities: clients.read clients.secret clients.write uaa.admin clients.admin scim.write scim.read
      scope: clients.read clients.secret clients.write uaa.admin clients.admin scim.write scim.read
      client_id: admin
      cid: admin
      azp: admin
      grant_type: client_credentials
      rev_sig: 267199d1
      iat: 1528232017
      exp: 1528275217
      iss: http://localhost:8080/uaa/oauth/token
      zid: uaa
      aud: scim clients uaa admin
    

Deploying UAA to TAS for VMs

To build the UAA as an app and push it to TAS for VMs using the Cloud Foundry Command Line Interface (cf CLI):

  1. Clone the UAA GitHub repository by running:

    git clone git://github.com/cloudfoundry/uaa.git
    
  2. Go to the directory where you cloned the UAA GitHub repository.

  3. Build the UAA as a WAR file by running:

    ./gradlew :cloudfoundry-identity-uaa:war
    
  4. Run the cf CLI cf push APP-NAME -m 512M -p PATH-TO-WAR-FILE --no-start command to push the app to TAS for VMs. Replace APP-NAME with a name for your UAA app, and PATH-TO-WAR-FILE with the path to the WAR file you created in the previous step. For example:

    cf push MYUAA -m 512M -p uaa/build/libs/cloudfoundry-identity-uaa-1.8.0.war --no-start
    
  5. Run cf set-env APP-NAME SPRING_PROFILES_ACTIVE default to set the SPRING_PROFILES_ACTIVE environment variable with the value default. Replace APP-NAME with the name of your app that you used in the previous step. For example:

    cf set-env MYUAA SPRING_PROFILES_ACTIVE default
    
  6. Run cf start APP-NAME to start your app. Replace APP-NAME with the name of your app. For example:

    cf start MYUAA
    

Using remote UAA

You use a UAA server that you pushed as an app to TAS for VMs in a similar way to one you run locally. You do not need app token encoding because you do not have the client secret.

To access and use a UAA server that you pushed as an app to TAS for VMs:

  1. Follow the procedure in Deploy UAA to TAS for VMs.

  2. From the project base directory, run curl -H "Accept: application/json" APP-FQDN/login to query the external login endpoint about the system. Replace APP-FQDN with the fully qualified domain name (FQDN) of your app. For example:

    $ curl -H "Accept: application/json" uaa.example.org/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"]
      }
    }
    
  3. Install the UAA Command Line Client (UAAC) Ruby gem by running:

    gem install cf-uaac
    
  4. Target the remote UAA Server endpoint by running:

    uaac target APP-FQDN
    

    Where APP-FQDN is the FQDN of your app.

  5. Log in by running:

    uaac token get USERNAME PASSWORD
    

    Where:

    • USERNAME is your username.
    • PASSWORD is your password. If you do not specify a username and password, the UAAC prompts you to supply them.

    The uaac token client get command 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.

Running integration tests

When you run integration tests, it makes sure that the UAA instance is running properly.

To run integrations tests:

./gradlew integrationTest

This command 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 where you change the URLs used in the tests, and where you can set the UAA server context root.

Customizing your YAML configuration

A custom YAML configuration gives integration tests access to your UAA instance by sharing credentials in YAML file.

To create a custom YAML configuration:

  1. Create a uaa.yml file in the following format:

    uaa:
      host: UAA-HOSTNAME
      test:
        username: USERNAME
        password: PASSWORD
        email: EMAIL-ADDRESS
    

    Where:

    • UAA-HOSTNAME is the FQDN of UAA app. For example, uaa.example.org.
    • USERNAME is a valid username. For example, [email protected].
    • PASSWORD is the password for the previous username.
    • EMAIL-ADDRESS is the email address for the previous user. Example: [email protected].
  2. From the uaa/uaa directory, run:

    CLOUD_FOUNDRY_CONFIG_PATH=/tmp ./gradlew test
    

The web app looks for a YAML file in the following locations when it starts, with later entries overriding earlier ones:

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

Testing with PostgreSQL or MySQL

The default UAA unit tests, ./gradlew test, use a HyperSQL database.

To use a different database management system:

  1. Create a uaa.yml file containing spring_profiles: default,OTHER-DBMS in the src/main/resources/ directory. Replace OTHER-DBMS with the name of the other database management system to use.

  2. Run the unit tests using your specified database management system instead of a HyperSQL database:

    echo "spring_profiles: default,OTHER-DBMS" > src/main/resources/uaa.yml
    ./gradlew test integrationTest
    

    Where OTHER-DBMS is the name of the database management system you specified in your uaa.yml file.

You can find the database configuration for the common and scim modules at common/src/test/resources/(mysql|postgresql).properties and scim/src/test/resources/(mysql|postgresql).properties.

UAA projects

The following UAA projects exist:

  • common: A module containing a JAR with all the business logic. common is used in the web apps.

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

  • api: A sample OAuth2 resource service that returns a mock list of deployed apps. api provides resources that other apps might want to access on behalf of the resource owner.

  • app: A sample user app that uses both api and uaa. app is a web app that requires single sign-on and access to the api service on behalf of users.

  • scim: The System for Cross-domain Identity Management (SCIM) user management module used by UAA. For more information about SCIM, see Managing Users & Groups with SCIM.

UAA server

The authentication service, uaa, is a Spring MVC web app. You can deploy it in Tomcat or your container of choice, or run ./gradlew run to run it directly from the uaa directory in the source tree. When run with Gradle, uaa listens on port 8080 and has the URL http://localhost:8080/uaa.

The UAA server supports the APIs defined in the UAA-APIs document which include:

  • The OAuth2 /authorize and /token endpoints.

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

  • An /introspect endpoint to allow resource servers to obtain information about an access token submitted by an OAuth2 client.

  • A SCIM user-provisioning endpoint.

  • OpenID Connect endpoints /userinfo and /check_id to support authentication.

Command-line clients can perform authentication by submitting credentials directly to the /authorize endpoint.

An ImplicitAccessTokenProvider exists in Spring Security OAuth to use if your client is Java.

By default, uaa runs with a context root /uaa.

Configuration

A uaa.yml file exists in the app. This file provides defaults to the placeholders in the Spring XML.

You can override any occurrences of ${placeholder.name} in the XML by adding it to your uaa.yml file, or by providing a System property with the same name, -D, to your Java virtual machine.

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

User account data

The default uses an in-memory relational database management system (RDBMS) user store, pre-populated with a single test user marissa with the password koala.

To use PostgreSQL for user data, you must activate the Spring profile postgresql.

You can configure the active profiles in your uaa.yml file using spring_profiles: postgresql,default.

To use PostgreSQL instead of HyperSQL, run:

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

To bootstrap a microcloud-type environment, you need an admin client. During the bootstrapping process, the database creates a database initializer component that inserts an admin client.

If the default profile is active, the bootstrapping process creates a cf CLI client so that the Gem login works with no additional configuration required. You can override the default settings and add additional clients in the uaa.yml file, as in the following example:

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 must have a client with read/write access to the scim resource to create user accounts. The integration tests handle this automatically by inserting client and user accounts as necessary for the tests.

Sample apps

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

You can run /api and /app with ./gradlew run from the uaa root directory. All three apps, /uaa, /api, and /app, are simultaneously deployed.

API sample app

The api sample app is an example resource server. It hosts a service that returns a list of mock apps under /apps.

App sample app

The app sample app is a user interface app, primarily aimed at browsers, that uses OpenID Connect for authentication and OAuth2 for access grants. app authenticates with the Auth service, then accesses resources in the API service. You can run app with ./gradlew run from the uaa root directory.

The app can operate in multiple different profiles according to the location and presence of the UAA server and the login app. By default, the app looks for a UAA on localhost:8080/uaa, but you can change this by setting the UAA_PROFILE environment variable or System Property.

The app source code, samples/app/src/main/resources, contains multiple properties files pre-configured with different likely locations for those servers. The names of these properties files follow the format app-UAA_PROFILE.properties.

The naming convention for the UAA_PROFILE is:

  • local: a localhost deployment

  • vcap: a vcap.me deployment

  • staging: a staging deployment

Profile names can be hyphenated to indicate multiple contexts. For example, local-vcap can be used when the login server is in a different location than the UAA server.

To see all apps, run:

GET /app/apps

The browser is redirected through a series of authentication and access grant steps.

To see the currently logged-in user details and a selection of attributes from the OpenID provider, run:

GET /app

Login app

The login app is a user interface for authentication. 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 log in app is itself an OAuth2 endpoint provider, but delegates those features to the UAA server. Therefore, configuration for the log in app consists of locating the UAA through its OAuth2 endpoint URLs and registering the log in app itself as a client of the UAA. The UAA locations have a login.ymlfile. For example, 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

You can define the environment variable or Java System property login_secret to use a client secret that the app uses when it authenticates itself with UAA. The login app is registered by default in UAA only if there are no active Spring profiles. In UAA, the registration is located in the oauth-clients.xml config file, as in the following example:

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

To authenticate with the login app, run:

GET /login

The sample app presents a form log-in interface for the back end UAA, and an OpenID widget where a user can authenticate using Google or other credentials.

To approve an OAuth2 token grant, run:

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

This is the standard OAuth2 authorization endpoint. UAA handles client credentials and all other features in the back end, and the login app is used to render the UI.

To obtain the access token, run:

POST /oauth/token

This is the standard OAuth2 authorization endpoint passed through to UAA.

Scopes

UAA covers multiple scopes of privilege, and has access to UAA, Cloud Controller, and to the router. For more information about UAA, see OAuth Scopes.

UAA scopes

The following table describes the scopes of privilege in UAA.

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 scope 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 run the /identity-zones endpoint to read identity zones.
zones.write This scope is required to run the /identity-zones endpoint to create and update identity zones.
scim.zones This is a limited scope that 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 approve or reject clients to act on a user’s behalf. This is a default scope defined in the uaa.yml file.
oauth.login This scope is used to indicate a login app, such as external login servers, can perform trusted operations, such as creating 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 /introspect endpoint.
zones.ZONE-ID.admin This scope permits operations in a designated zone, such as creating identity providers or clients in another zone, by authenticating against the default 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 completes. 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 completes. This scope is used with the X-Identity-Zone-Id header.
zones.ZONE-ID.clients.write his scope translates into clients.write after zone switch completes. 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 completes. 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 completes. 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 completes. 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 completes. This scope is used with the X-Identity-Zone-Id header.

Cloud Controller scopes

The following table describes the scopes of privilege in Cloud Controller.

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.global_auditor This scope gives read-only access to all Cloud Controller API resources except for secrets such as environment variables.

Routing scopes

The following table describes the scopes of privilege in the router.

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.

Scopes of privilege

The following table describes the scopes of privilege in other TAS for VMs services.

Scope Description
doppler.firehose This scope gives the ability to read logs from the How the Loggregator Firehose forwards Logs and Metrics endpoint.
notifications.write This scope gives the ability to send notifications through the Getting started with the Notifications Service.
check-circle-line exclamation-circle-line close-line
Scroll to top icon