The goal of this interaction is to figure out how to use the /check_token endpoint of the UAA to authenticate clients. This is useful if you want to use the UAA to authenticate a particular client (in my case, an AWS Lambda function that calls my API while standing up a CloudFormation stack), as opposed to authenticating individual users.
First, your application needs to be able to talk to the UAA and validate tokens. To enable this, you need to create a new UAA client and secret for your application to use. To do this, we use the uaac
command like so:
$ uaac target uaa.mycfenvironment.com --skip-ssl-validation
Target: https://uaa.mycfenvironment.com
$ uaac token client get admin -s [email protected]
Successfully fetched token via client credentials grant.
Target: https://uaa.mycfenvironment.com
Context: admin, from client admin
$ uaac client add my-api --scope uaa.resource --authorities uaa.resource --authorized_grant_types refresh_token -s [email protected]
scope: uaa.resource
client_id: my-api
resource_ids: none
authorized_grant_types: refresh_token
autoapprove:
action: none
authorities: uaa.resource
lastmodified: 1477062635696
id: my-api
Secondly, whomever or whatever is using your application needs to be able to authenticate to it. So, let’s add another client with the authorized grant type of "client_credentials". These will be the client credentials used by the Lambda function itself to talk to my API.
$ uaac client add my-api-client --authorized_grant_types client_credentials -s [email protected]
To try this out, we turn to curl
. First, let’s test that our new api client can get a token (obviously, "REDACTED" isn’t a valid token):
$ curl -XPOST -u my-api-client:[email protected] http://uaa.mycfenvironment.com/oauth/token --data-urlencode "grant_type=client_credentials" --data-urlencode "response_type=token"
{"access_token":"REDACTED","token_type":"bearer","expires_in":43199,"scope":"uaa.none","jti":"REDACTED"}
When you look at the token you actually get from the API, note that it is a Java Web Token (JWT). There is software out there that will allow you to decode such a token (or at least part of one) for debugging purposes. One I use is jwt.io.
Next, let us now play the role of your application. We now take the value returned in the "access_token" field of the previous command, and pretend that we are receiving this token after the client has acquired it from the UAA.
Note above we use the -u
command line switch to pass the basic auth credentials to the UAA. Here are some other ways you may see to pass credentials:
We could pass the credentials as part of the URL, like this:
$ curl -XPOST http://my-api:[email protected]@uaa.mycfenvironment.com/check_token...
It works, but it is not my first choice.
We could also manually add the Authorization
header, like so:
$ echo -n my-api:[email protected] | base64
bXktYXBpOm15cEBzc3cwcmQx
$ curl -XPOST http://uaa.mycfenvironment.com/check_token -H "Authorization: Basic bXktYXBpOm15cEBzc3cwcmQx" ...
There is an easier option than this, but try it at least once. This shows how the Basic Authentication header is formed. Also, it is key that you use the -n
in echo, which keeps echo from adding a trailing newline character. Otherwise you’ll spend hours wondering why your perfectly valid credentials are not being accepted.
I just use the -u
option to let curl
generate the header for me. Below is the full call and its results:
$ curl -XPOST -u my-api:[email protected] http://uaa.mycfenvironment.com/check_token -H "Content-Type: application/x-www-form-urlencoded" -d "token=REDACTED"
{"client_id":"my-api-client","exp":1477198408,"authorities":["uaa.none"],"scope":["uaa.none"],"jti":"b460e8ef-3f34-45f5-81b0-2d7c0d66dbfe","aud":["my-api-client"],"sub":"my-api-client","iss":"http://uaa.mycfenvironment.com/oauth/token","iat":1477155208,"cid":"my-api-client","grant_type":"client_credentials","azp":"my-api-client","zid":"uaa","rev_sig":"de07cb25"}
So, you have 2 takeaways here:
- You have now taken a token from a client that has authenticated with the UAA, and you have authenticated to that same UAA, and validated that it is a valid token.
- By using
curl
to step through each step of the interaction and examine the output, you now better understand how to implement it in code.
For more information on how the UAA API’s work, there is some pretty good documentation that comes with the UAA on github:
https://github.com/cloudfoundry/uaa/blob/master/docs/UAA-APIs.rst