CLI tool
cloudfoundry/uaa avatar
cloudfoundry/uaa

UAA is a standalone OAuth2 server that keeps Cloud Foundry's token endpoints

CloudFoundry User Account and Authentication (UAA) Server

1,638 stars846 forksJavaApache-2.0

At a glance

What is it?
UAA is the Apache 2.0 licensed multi-tenant identity service behind Cloud Foundry, and it runs perfectly well on its own as an OAuth2 and partial OpenID Connect provider with SCIM provisioning. It suits an organisation that wants Cloud Foundry's token semantics without the platform, and Java 25, the hsqldb default and an incomplete OpenID implementation are the boundaries to know about.
Who is it for?
UAA suits a platform team that already lives in the Cloud Foundry ecosystem, or anyone who wants its token, scope and authority model as a standalone OAuth2 provider with SCIM provisioning and LDAP integration rather than a general identity product. It is the wrong choice if you need full OpenID Connect, since the README calls that support partial, or if your build environment is stuck on a JDK older than 25.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What UAA actually is, separate from Cloud Foundry

UAA is described as a multi-tenant identity management service used in Cloud Foundry and also available as a standalone OAuth2 server. Its primary role is as an OAuth2 provider issuing tokens for client applications to act on behalf of Cloud Foundry users.

The endpoints are what make that concrete. There is the standard authorization endpoint at /oauth/authorize and the token endpoint at /oauth/token. There is /login_info for querying which login prompts are required. There is /check_token, which lets a resource server learn what an access token submitted by a client actually grants, and /token_key, which lets a resource server fetch the key it needs to verify token signatures locally. User provisioning is SCIM, and OpenID Connect endpoints support /userinfo.

That last item carries a caveat stated plainly in the README: OpenID support is partial. For a project that needs complete OIDC conformance, that sentence decides the question.

Two supporting documents are named as the coordinates for the design: a note on tokens, scopes and authorities in docs/UAA-Tokens.md, and docs/UAA-LDAP.md for directory integration. The README also links the OpenID certification mark, which is a statement about the project rather than about which features are complete.

Three commands run it, and all of them land on port 8080

The authentication service is a plain Spring MVC webapp named uaa. You deploy it into Tomcat or another container, or run it straight from the source tree with Gradle.

The quick start is a clone and a run:

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

The requirement above that is Java 25, which is the single hardest constraint for anyone trying this in an existing build environment.

There are several Gradle entry points and they are not interchangeable. The README recommends ./gradlew run as an alias that kills any running UAA and starts the application, which is worth knowing because it means the command terminates a previous instance rather than failing on a port clash. ./gradlew bootRun is the built-in Spring Boot task. ./gradlew bootWarRun launches the runnable .war file through a JavaExec task. And ./scripts/boot/boot-with-tls.sh runs both http on 8080 and https on 8443, which is the one to reach for when you need TLS locally.

With Gradle, the base URL is http://localhost:8080/uaa. The co-located sample apps also serve on 8080 at /app and /api, so one process hosts all three.

A curl against /uaa/login is the smoke test

The README gives a one-line check that the server is up, and it is worth keeping as a health probe in CI:

bash
curl --silent --show-error --head localhost:8080/uaa/login | head -1

The expected answer is HTTP/1.1 200. That is the whole of the quick verification, and it does confirm that the context path, the webapp and the login page are all wired correctly.

For anything more than a health check, the README points at uaac, the UAA Command Line Client in the separate cloudfoundry/cf-uaac repository, and calls it more convenient for complex requests. The README links to it as a separate cloudfoundry/cf-uaac repository.

Command line clients can also skip the browser entirely by submitting credentials straight to /oauth/authorize. For a Java client, the README names ImplicitAccessTokenProvider in Spring Security OAuth as the class that handles the mechanics.

Logs go to a file named uaa.log, which the README shows you how to locate with lsof, and it normally turns up under scripts/boot/tomcat/logs/.

Three Gradle tasks, one system property, and a long manual java line

Running the Spring Boot application by hand is documented with the full system property set, and it is the most informative thing in the README about how the thing is configured:

text
java -DCLOUDFOUNDRY_CONFIG_PATH=`pwd`/scripts/boot \
    -DSECRETS_DIR=`pwd`/scripts/boot \
    -Dserver.servlet.context-path=/uaa \
    -Dspring.profiles.active=hsqldb \
    -Dlogging.config=`pwd`/scripts/boot/log4j2.properties \
    -jar `pwd`/uaa/build/libs/cloudfoundry-identity-uaa-0.0.0.war

Several of those properties are doing real work. CLOUDFOUNDRY_CONFIG_PATH and SECRETS_DIR tell the server where to read configuration and secrets, which is how you keep credentials out of the application. server.servlet.context-path is what produces the /uaa prefix, so changing it changes every URL you then have to use. spring.profiles.active selects the database. The logging config points at a log4j2.properties file rather than relying on defaults.

The full block also enables per-request metrics, statsd, an SMTP host and port for mail, file encoding, and user country and language defaults. Statsd is why the repository carries statsd/ and statsd-lib/ directories at the top level.

Running standalone this way is also how the integration tests work: ./gradlew integrationTest starts the built application rather than letting Gradle bring up Tomcat, with a system property preventing the Tomcat startup.

hsqldb by default, MySQL or PostgreSQL by profile

The default database is hsqldb, in memory, which is why ./gradlew run needs no setup at all. Switching to a real database is a profile change plus a database you created yourself.

The MySQL route starts a container, creates the database and runs with the mysql profile:

bash
docker run --name mysql1 -e MYSQL_ROOT_PASSWORD=changeme -d -p3306:3306 mysql
mysql -h 127.0.0.1 -u root -p
mysql> create database uaa;
./gradlew -Dspring.profiles.active=mysql run

PostgreSQL follows the same shape with the postgresql profile, and adds a user creation step:

postgresql
create database uaa;
create user root with superuser password 'changeme';

The README notes that once the server has started you can see the tables it created in the uaa database, which means schema creation is automatic on first start rather than something you apply by hand. That is convenient for a first run and is the thing to watch when you move to production, because a service that manages its own schema on boot will want to be told not to.

For debugging there are three property variants worth knowing. ./gradlew run -Pdebug attaches a JDWP agent on port 5005. ./gradlew run -Pdebugs starts suspended, waiting for the debugger before the application boots, which is what you need for start-up code. And the port is not fixed: ./gradlew run -Pdebug -PdebugPort=5006 moves it.

Version numbering in the seventies and monthly releases

The release tags give the project's shape away. Recent versions are 79.8.0 on 2026-09-28, 79.7.0 on 2026-08-27 and 79.6.0 on 2026-08-21. A version number in the high seventies is not vanity numbering, it is Cloud Foundry's long-running platform numbering, and it is what tells you where this code sits in that platform's history.

The cadence is roughly monthly and the default branch is develop, which is the convention that goes with a platform release train rather than a library that cuts semver from master.

Maintenance is active. The last push was on 2026-10-16.

The licence is Apache 2.0, with both a LICENSE and a NOTICE file at the root, which is the standard pairing for that licence and matters if you redistribute, since NOTICE has to travel with the code. The repository also carries AGENTS.md and CLAUDE.md at the top level, plus an ai/ directory, so part of the working method for this codebase is written down for tools that read instructions, not just for people.

Where UAA sits against a general identity provider

The comparison that matters is with a product built for end-user identity: an on-premises directory product, or a cloud identity service. Those give you a management console for people, self-service password reset, MFA enrolment, session management screens and an admin who is not you. UAA's documented surface is protocols and endpoints plus management APIs, and the README describes its extras as user account endpoints, OAuth2 client registration and other management functions. It is an engine for applications to authenticate against, not a place a person goes to manage their own account.

The second comparison is with the OAuth2 provider already inside an application framework. UAA's advantage there is the multi-tenancy and the resource server contract: /check_token and /token_key exist so a separate resource service can validate what it was handed, which is exactly the split the Cloud Foundry platform needs and that a single application usually does not have.

The cost of that specialisation is the partial OpenID Connect support. If your requirement is a full OIDC relying party integration, that gap has to be closed elsewhere in the stack.

Editorial conclusion

UAA suits a platform team that already lives in the Cloud Foundry ecosystem, or anyone who wants its token, scope and authority model as a standalone OAuth2 provider with SCIM provisioning and LDAP integration rather than a general identity product. It is the wrong choice if you need full OpenID Connect, since the README calls that support partial, or if your build environment is stuck on a JDK older than 25. Before anything else, run ./gradlew run and confirm /uaa/login answers on port 8080, then decide deliberately between the hsqldb default and a real database, because the MySQL and PostgreSQL profiles create the schema on first start and switching later means managing that migration yourself.

Frequently asked questions

How do I run the UAA server locally?

Clone the repository and run ./gradlew run from the uaa directory. It listens on port 8080 and the base URL is http://localhost:8080/uaa, alongside the sample apps at /app and /api. Java 25 is required.

Which database does UAA use by default and how do I switch?

The default is hsqldb, so ./gradlew run needs no setup. To use MySQL or PostgreSQL you start a container, create a database named uaa and run with the profile, for example ./gradlew -Dspring.profiles.active=mysql run. The server creates its tables on first start.

Does UAA support full OpenID Connect?

Partially. The README states that the OpenID Connect endpoints support authentication and /userinfo, and describes OpenID support as partial. For complete conformance you would need to cover the gap elsewhere.

How do I debug the UAA JVM?

Run ./gradlew run -Pdebug to attach a JDWP agent on port 5005, or -Pdebugs to start suspended until the debugger connects, which is what you want for start-up code. Set another port with ./gradlew run -Pdebug -PdebugPort=5006. bootRun accepts the same properties.

What endpoints do resource servers use with UAA?

POST /check_token lets a resource server obtain information about an access token submitted by a client, and /token_key returns the verification key for verifying token signatures locally. User provisioning uses the SCIM endpoint.

Official sources

  1. cloudfoundry/uaa on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cloudfoundry-uaa.svg)](https://hysenlabs.com/projects/cloudfoundry-uaa)

Was this useful?