How to verify UAA Tokens, part 1
Let’s say you’re an application developer, crafting an application that will be secured by the UAA OAuth 2.0 server. You expose an HTTP endpoint that requires consumers to have an OAuth scope called app-x-read-only
.
An HTTP client has called your endpoint, and handed you a token! Now you’re ready to check:
- Was this token issued by the UAA instance that I trust?
- Does this token authorize contain scope
app-x-read-only
?
To answer these questions, let’s lay some groundwork for UAA tokens. UAA issues tokens in two formats: jwt
and opaque
. Your OAuth client chooses which token format to obtain from the UAA, so likely your application will need to handle either case. JWTs are much larger, but are more flexible (more on this later). Note that in either case, you must configure your application to know what the URL of the UAA is (for the examples below, it’s http://localhost:8080/uaa
), so that your application will understand what OAuth server granted and validates these tokens.
JWT
eyJhbGciOiJIUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvdWFhL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.eyJqdGkiOiJjMjQ1ZDg1N2JhZmI0NTk1OTQwN2FhY2IzMWY5ZGVlNiIsInN1YiI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiY2xpZW50cy5yZWFkIiwiY2xpZW50cy5zZWNyZXQiLCJjbGllbnRzLndyaXRlIiwidWFhLmFkbWluIiwiY2xpZW50cy5hZG1pbiIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiXSwic2NvcGUiOlsiY2xpZW50cy5yZWFkIiwiY2xpZW50cy5zZWNyZXQiLCJjbGllbnRzLndyaXRlIiwidWFhLmFkbWluIiwiY2xpZW50cy5hZG1pbiIsInNjaW0ud3JpdGUiLCJzY2ltLnJlYWQiXSwiY2xpZW50X2lkIjoiYWRtaW4iLCJjaWQiOiJhZG1pbiIsImF6cCI6ImFkbWluIiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInJldl9zaWciOiJlZmY0ZjJhNCIsImlhdCI6MTU4MTA5MTg1OSwiZXhwIjoxNTgxMTM1MDU5LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvdWFhL29hdXRoL3Rva2VuIiwiemlkIjoidWFhIiwiYXVkIjpbInNjaW0iLCJjbGllbnRzIiwidWFhIiwiYWRtaW4iXX0.5hf45nvH7Mka-fijrp0PREjKs8MzYR0sGQuxg1_nzHE
The UAA issues tokens that are signed (JWS), but not encrypted (JWE). Thus these tokens can be base64-decoded and read by anyone. Production applications will typically use the RS256 signing algorithm, whereas locally running the UAA will use HS256.
I won’t go into details of how to validate JWTs in general — comprehensive guides for this already exist [1]. This guide is meant to be specific to the UAA. To see more a more comprehensive guide of validating UAA-issued JWT tokens, please see part 2 [ref coming soon]. For now, you can use the same approach outlined in the following section regarding Opaque tokens.
Opaque
6e71ea1ea0dd44b3a86f48cf62401542
One thing to note about these opaque keys — they contain no inherent information. This is a bearer token that is nothing more than a unique identifier. You must use the UAA’s token introspection endpoint /introspect
[3] to verify whether this key is valid or not. I’ll describe more about this in a later part of the series [ref coming soon] but for now you will need to follow these steps.
- Your application must be a registered OAuth client of the UAA, with authority of
uaa.resource
. This is out of scope for this series of blog posts, but UAA client management is not usually performed by application developers. - Your application must be configured with the appropriate
client_id
,client_secret
, and URL of the UAA. - Your application can retrieve a
client_credentials
token from the UAA as described in [5]. - Your application can use its own
client_credentials
token to authenticate itself to the/introspect
endpoint so that it can validate tokens [3].
Pay careful attention to the details of the introspect
endpoint. It is RFC-7662 compliant, which means it may return a 200 even if the token being validated is not valid! Instead, use the active
response field to indicate whether the token is currently valid.
The /introspect
endpoint will return the scopes that the token contains. For opaque tokens, this is the only way to retrieve this information. JWTs will contain this information in the scope
claim. Your application can check whether this list contains scope app-x-read-only
to determine whether to grant access to your HTTP endpoint.
Coming soon
There are many tradeoffs when considering how you may want to recognize a UAA token as valid. If your API users provide JWT tokens, you may decide to perform offline validation [6], which will be slightly different depending on whether your UAA is configured with asymmetric (RS256) or symmetric (HS256) signing keys. Note that asymmetric keys are recommended for production use. Other factors that come into play are token expirations, revocations, and rotation of UAA signing keys. These will be discussed in low detail in later parts of this series.
If you have any questions, please reach out to us on CloudFoundry Slack channel #uaa.
[0]
https://github.com/cloudfoundry/uaa
https://docs.cloudfoundry.org/concepts/architecture/uaa.html
[1]
https://auth0.com/docs/tokens/guides/validate-jwts
[2]
Link coming soon!
[3] https://docs.cloudfoundry.org/api/uaa/version/74.4.0/index.html#introspect-token — please be sure to use the API docs version corresponding to your UAA version (see the UAA’s /info
endpoint for your version of the UAA).
[4]
Link coming soon!
[5]
[6]
The UAA provides the public portion of its signing keys at the token_key
endpoint, which is documented at https://docs.cloudfoundry.org/api/uaa/version/74.4.0/index.html#token-key-s