User Account and Authentication (UAA) Server
Page last updated:
Warning: Pivotal Cloud Foundry (PCF) v2.3 is no longer supported because it has reached the End of General Support (EOGS) phase as defined by the Support Lifecycle Policy. To stay up to date with the latest software and security updates, upgrade to a supported version.
This topic provides an overview of the User Account and Authentication (UAA) Server, the identity management service for Cloud Foundry
The primary role of the UAA is as an OAuth2 provider, issuing tokens for client apps to use when they act on behalf of Cloud Foundry users. In collaboration with the login server, the UAA can authenticate users with their Cloud Foundry credentials, and can act as an SSO service using those, or other, credentials.
The UAA has endpoints for managing user accounts and for registering OAuth2 clients, as well as various other management functions.
Quick Start
You can deploy the UAA locally or to Cloud Foundry.
Deploy UAA Locally
Follow the instructions below to deploy and run the UAA locally.
In a terminal window, clone the UAA GitHub repository.
$ git clone git://github.com/cloudfoundry/uaa.git
Navigate to the directory where you cloned the UAA GitHub repository, then run the
./gradlew run
command to build and run all the components that comprise the UAA and the example programs,uaa
,samples/api
, andsamples/app
.$ cd uaa $ ./gradlew run
If successful, the three apps run together on a single instance of Tomcat listening on port 8080, with endpoints
/uaa
,/app
, and/api
.
Use Local UAA
Follow the steps below to access and use a locally-deployed UAA server.
Run the UAA server as described in the Deploy Locally section, above.
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 should 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" }
Run
gem install cf-uaac
to install the Cloud Foundry UAA Command Line Client (UAAC) Ruby gem.$ gem install cf-uaac
Run
uaac target http://localhost:8080/uaa
to target the local UAA server endpoint.$ uaac target http://localhost:8080/uaa
Run
uaac token client get CLIENT_NAME -s CLIENT_SECRET
to obtain an access token. ReplaceCLIENT_NAME
andCLIENT_SECRET
with actual values. For example, when starting up the UAA locally for development there should be a predefined admin client you can use:$ uaac token client get admin -s adminsecret
If you do not specify the client secret, UAAC will show an interactive prompt where you must enter the client secret value.
The
uaac token client get
command requests an access token from the server using the OAuth2 client credentials grant type.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, use the commanduaac 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 following step.
Run
uaac token decode ACCESS-TOKEN-VALUE
to view information in the token, which is encoded using the JSON Web Token format. ReplaceACCESS-TOKEN-VALUE
with your access token, copied from theuaac context
output. The UAAC should display 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
Deploy UAA to Cloud Foundry
Follow the instructions below to build the UAA as an app and push it to Cloud Foundry using the Cloud Foundry Command Line Interface (cf CLI).
In a terminal window, clone the UAA GitHub repository.
$ git clone git://github.com/cloudfoundry/uaa.git
Navigate to the directory where you cloned the UAA GitHub repository, then run the
./gradlew :cloudfoundry-identity-uaa:war
command build the UAA as a WAR file.$ cd uaa $ ./gradlew :cloudfoundry-identity-uaa:war
Run the cf CLI
cf push APP-NAME -m 512M -p PATH-TO-WAR-FILE --no-start
command to push the app to Cloud Foundry. ReplaceAPP-NAME
with a name for your UAA app, andPATH-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
Run
cf set-env APP-NAME SPRING_PROFILES_ACTIVE default
to set theSPRING_PROFILES_ACTIVE
environment variable with the valuedefault
. ReplaceAPP-NAME
with the name of your app that you used in the previous step. For example:$ cf set-env MYUAA SPRING_PROFILES_ACTIVE default
Run
cf start APP-NAME
to start your app. ReplaceAPP-NAME
with the name of your app. For example:$ cf start MYUAA
Use Remote UAA
You use a UAA server that you pushed as an app to Cloud Foundry in a similar way to one you run locally. You do not need app token encoding because you do not have the client secret.
Follow the steps below to access and use a UAA server that you pushed as an app to Cloud Foundry.
Deploy UAA to Cloud Foundry as described above.
From the project base directory, run
curl -H "Accept: application/json" APP-FQDN/login
to query the external login endpoint about the system. ReplaceAPP-FQDN
with the 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"] } }
Run
gem install cf-uaac
to install the Cloud Foundry UAA Command Line Client (UAAC) Ruby gem.$ gem install cf-uaac
Run
uaac target APP-FQDN
to target the remote UAA Server endpoint. ReplaceAPP-FQDN
with the FQDN of your app.$ uaac target uaa.example.org
Run
uaac token get USERNAME PASSWORD
to log in. ReplaceUSERNAME
with your user name, andPASSWORD
with your password. For example:$ uaac token get marissa koala
If you do not specify a username and password, the UAAC prompts you to supply them.
Theuaac 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 Cloud Foundry Command Line Interface (cf CLI).
Integration Tests
Run the integration tests with the following command:
$ ./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.
Custom YAML Configuration
Follow the steps below to modify the runtime parameters.
Create a
uaa.yml
file in the following format:uaa: host: UAA-HOSTNAME test: username: USERNAME password: PASSWORD email: EMAIL-ADDRESS
Replace the values in the above format as follows:
- UAA-HOSTNAME: The FQDN of UAA app. Example:
uaa.example.org
- USERNAME: A valid username. Example:
dev@example.org
- PASSWORD: Password for the above username.
- EMAIL-ADDRESS: Email address for the above user. Example:
dev@example.org
- UAA-HOSTNAME: The FQDN of UAA app. Example:
From the
uaa/uaa
directory, runCLOUD_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}
Test with PostgreSQL or MySQL
The default UAA unit tests, ./gradlew test
, use HyperSQL (hsqldb).
To use a different database management system, 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.
For example, run the following command to run the unit tests using PostgreSQL instead of hsqldb:
$ echo "spring_profiles: default,postgresql" > src/main/resources/uaa.yml $ ./gradlew test integrationTest
Run the following command to run the unit tests using MySQL instead of hsqldb:
$ echo "spring_profiles: default,mysql" > src/main/resources/uaa.yml $ ./gradlew test integrationTest
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 listed below.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 bothapi
anduaa
.app
is a web app that requires single sign-on and access to theapi
service on behalf of users.scim
: The SCIM user management module used by UAA.
UAA Server
The authentication service, uaa
, is a Spring MVC web app. You can deploy it in Tomcat or your container of choice, or execute ./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 URL http://localhost:8080/uaa
.
The UAA Server supports the APIs defined in the UAA-APIs document which include the following:
The OAuth2
/authorize
and/token
endpointsA
/login_info
endpoint to allow querying for required login promptsA
/check_token
endpoint to allow resource servers to obtain information about an access token submitted by an OAuth2 clientSCIM user provisioning endpoint
OpenID connect endpoints to support authentication
/userinfo
and/check_id
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
will launch 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 the uaa.yml
file, or by providing a System property, -D
to JVM, with the same name.
All passwords and client secrets in the config files are in plain text, but are inserted into the UAA database encrypted with BCrypt.
User Account Data
The default uses an in-memory RDBMS user store, 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 the following:
spring_profiles: postgresql,default
To use PostgreSQL instead of HyperSQL (hsqldb):
$ echo "spring_profiles: postgresql,default" > src/main/resources/uaa.yml $ ./gradlew run
To bootstrap a microcloud-type environment, you need an admin client. A database initializer component that inserts an admin client exists.
If the default profile is active, for example not postgresql
, a cf CLI client exists 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:
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 the UAA: /api
and /app
.
Run them 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.
Run it 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 form app-UAA_PROFILE.properties
.
The naming convention for the UAA_PROFILE
is as follows:
local
: a localhost deploymentvcap
: avcap.me
deploymentstaging
: 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.
Use Cases
See all apps:
GET /app/apps
Browser is redirected through a series of authentication and access grant steps, and then the photos are shown.
See the currently logged in user details, a selection of attributes from the OpenID provider:
GET /app
LOGIN App
The login
app is 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 app is itself an OAuth2 endpoint provider, but delegates those features to the UAA server.
Therefore, configuration for the login app consists of locating the UAA through its OAuth2 endpoint URLs and registering the login app itself as a client of the UAA.
A login.yml
for the UAA locations exists, 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
An environment variable or Java System property also exists, 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
Authenticate:
GET /login
The sample app presents a form login interface for the backend UAA, and an OpenID widget where a user can authenticate using Google or other credentials.
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 app is used to render the UI.
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 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 /check_token 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 |
This 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
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
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. |