Skip to content

JSON Web Token / JWT

The UAA publishes self-encoded access tokens. That is, the access token are not a random sequence of numbers and letters that must be looked up in the UAA database. Rather it is two encoded JSON objects. The encoded JSON objects are called a JSON Web Token, or JWT.

We can inspect the contents of any access token using:

uaa-deployment auth-client
uaa context --access_token

Copy and paste this string into the educational site jwt.io inside the left-hand side Encoded text area:

jwt-client-credentials

The two decoded JSON objects are displayed on the right hand side.

  • Header - describes the encoding algorithm for the payload JSON and the signing key label
  • Payload - the metadata associated with the authenticated user/client

The client credentials for client uaa_admin example above includes the list of authorities and scopes. The UAA API or other UAA client applications can uses the values in these lists to enable or restrict functionality.

The decoded access token of a password-grant user looks similar. Copy and paste a password-granted user's access token into jwt.io:

uaa get-password-token airports -s airports -u airports-all -p airports-all
uaa context --access_token

jwt-user-password

Decoding secret JWTs locally

The jwt.io website is pretty, but it is a third-party site that we don't control.

Your access token grants anyone/any system with it access to systems that want to agree to it. You should not give it away to strangers who have access to your systems. Fortunately, your uaa-deployment up UAA is local to your laptop, is short lived, and does not contain critical data; so we can be less worried about pasting our example access tokens into jwt.io.

But please do not copy and pasting access tokens to your production systems into jwt.io, or any third-party site that you don't trust entirely.

For example, you might want to inspect your access token to your public Cloud Foundry authorization. Anyone who gets hold of this token will have access until it expires in a few hours time. You can find AccessToken: bearer <access token> within ~/.cf/config.json.

Instead, here are some examples for decoding JWT tokens locally and safely:

bearer_and_access_token=$(cat ~/.cf/config.json  | jq -r .AccessToken)
echo $bearer_and_access_token | python -c "import base64, sys; print base64.urlsafe_b64decode(sys.stdin.read().split(' ')[1].split('.')[1])" | jq .

Or try the purpose-built jwt-cli:

jwt decode $(cat ~/.cf/config.json| jq -r .AccessToken | cut -d' ' -f2)

Verify JWT signature

Since a JWT string is easily encoded and decoded by anyone it is important to ensure that we trust that our JWT access tokens were definitely provided by our own UAA, not someone else we don't trust.

jwt-invalid-signature

jwt-signature-verified

Refresh Access Token

jtw vs opaque methods

Rotating JWT keys

TODO: Waiting on Slack discussion on how UAA team expects ppl to curate their keys overtime via BOSH.

The UAA is designed to encourage operators to routinely rotate thru JWT signing keys. If it is possible for a signing key to be guessed or hacked, then regularly rotating the signing keys reduces the time that a hacker has to perform the malicious activity before their hacked keys are made invalid.

Adam Eijdenberg:

Google I think rotate theirs approx once a day, and their equivalent to /token_keys seems to always return 2 values: https://www.googleapis.com/oauth2/v3/certs

The UAA created by uaa-deployment up starts with one JWT signing key:

uaa token-keys

To add an additional key and make it the new primary key we need to create operators/8-jwt-key-2.yml:

mkdir -p operators
cat > operators/8-jwt-key-2.yml <<-YAML
- type: replace
  path: /instance_groups/name=bosh/jobs/name=uaa/properties/uaa/jwt/policy/active_key_id
  value: uaa-jwt-key-2

- type: replace
  path: /instance_groups/name=bosh/jobs/name=uaa/properties/uaa/jwt/policy/keys/uaa-jwt-key-2
  value:
    signingKey: ((uaa_jwt_signing_key_2.private_key))

- type: replace
  path: /variables/-
  value:
    name: uaa_jwt_signing_key_2
    type: rsa
YAML

And now re-deploy your UAA:

uaa-deployment up

The /token_keys endpoint will now return both keys - the old and the new. To view them:

uaa token-keys

The output might be similar to:

[
  {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "uaa-jwt-key-1",
    "alg": "RS256",
    "value": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0tWt2QL+tJDardFZPpGK\nHjY19FJeuepWE8yoRqFyQslmVTB+uJWRbM3SzTT+IFY2QqS9Jbg2VPU0+zLTlPf+\ng3oIGD/lCqlKwIa9lIF9tQWivCz08dL4PIsFTtPU9EhRtm0CzKx1pZWwzCuGT/vv\ns/9LNh5BhJyEt/QSHPHnl1bN6SarvK5RW5qq827ExWsXsdx2zqYghMnlfWqSD3L/\nHcwS+JBUAgG9swYkjg1djxlU8IBoeV1YR65Cs3E/pgxtoap7mLlEx+HZYEM0Qtfm\nfWbm+iTDSa/YXu8pUQcP7QDEzR06EHhgxKwT7NKYf75quTYjeeD7+cIRbKpGUTTj\nJwIDAQAB\n-----END PUBLIC KEY-----",
    "n": "ANLVrdkC_rSQ2q3RWT6Rih42NfRSXrnqVhPMqEahckLJZlUwfriVkWzN0s00_iBWNkKkvSW4NlT1NPsy05T3_oN6CBg_5QqpSsCGvZSBfbUForws9PHS-DyLBU7T1PRIUbZtAsysdaWVsMwrhk_777P_SzYeQYSchLf0Ehzx55dWzekmq7yuUVuaqvNuxMVrF7Hcds6mIITJ5X1qkg9y_x3MEviQVAIBvbMGJI4NXY8ZVPCAaHldWEeuQrNxP6YMbaGqe5i5RMfh2WBDNELX5n1m5vokw0mv2F7vKVEHD-0AxM0dOhB4YMSsE-zSmH--ark2I3ng-_nCEWyqRlE04yc"
  },
  {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "uaa-jwt-key-2",
    "alg": "RS256",
    "value": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyXy/9N4Znj+iAJeAO2IO\ncslSWjfv6JdPiDKTNQlgjnMw0ALmNMe+8qPqbVnxkN/djoS8Aqy48+6ghvs5wwR0\nXAMWZ4p9YYM5D1UJPA7DdSr/wcZeth+ZgQ/fdfxnhaJBipXVIRuDvYA/1ffCY3Nl\nAcyUfPgqFVr1N18yjBr3PvuOmqRQSCH+U8/Jq2fXbOtzemEBGcduYqX/uS4ao12i\n/gb5Bx1TJBJpBkLpknQ6wj0x4ZIfJKreiSfB+ryjdQyYKSZlFaSW0PZSmc7n2k+8\nELOlgCD35rTZdjBA5lmVzIUNdBZGR4kBsUQEMZbYs5Zrd05ma4qgtEQmn4LuX1nt\nfwIDAQAB\n-----END PUBLIC KEY-----",
    "n": "AMl8v_TeGZ4_ogCXgDtiDnLJUlo37-iXT4gykzUJYI5zMNAC5jTHvvKj6m1Z8ZDf3Y6EvAKsuPPuoIb7OcMEdFwDFmeKfWGDOQ9VCTwOw3Uq_8HGXrYfmYEP33X8Z4WiQYqV1SEbg72AP9X3wmNzZQHMlHz4KhVa9TdfMowa9z77jpqkUEgh_lPPyatn12zrc3phARnHbmKl_7kuGqNdov4G-QcdUyQSaQZC6ZJ0OsI9MeGSHySq3oknwfq8o3UMmCkmZRWkltD2UpnO59pPvBCzpYAg9-a02XYwQOZZlcyFDXQWRkeJAbFEBDGW2LOWa3dOZmuKoLREJp-C7l9Z7X8"
  }
]

Offline Validation

One of the features of JWT is the ability to validate each JWT without accessing the UAA. An access token published for a user can be passed into applications that themselves do not have direct access to the same UAA.