This library has been folded into the RabbitMQ OAuth 2/JWT plugin plugin.
This library can decode JSON Web Tokens returned by Cloud Foundry UAA.
The tokens are issued by UAA to OAuth 2 resource servers and a resource server can decode and verify the tokens to authorize access to its resources.
This library was switched to pure Erlang version. You can still use it from Elixir, but will have
to change module names from UaaJWT
, UaaJWT.JWT
and UaaJWT.JWK
to uaa_jwt
, uaa_jwt_jwt
and uaa_jwt_jwk
respectively.
To use elixir version of this library, please use the elixir
tag.
The elixir version is not maintained anymore, sorry.
The project is based on a number of dependencies:
-
erlang-jose, a JWT management library and inherits all of its algorithm limitations. Supported algorithms and JWK types can be configured by configuring
erlang-jose
. -
jsx as JSON decoder
This project can be used to decode and verify JWT tokens issued by UAA or other providers. Encoding or signing of JWTs is currently out of scope for this library.
The project doesn't make any requests to UAA server and requires UAA keys to be pre-configured. This is by design. See [Usage][Usage] for more info.
UAA uses JWK keys to sign JWTs.
Signing key can be retrieved from UAA using a /token_key API request.
There can be two types of keys:
RSA
: standard RSA key type described in JWA RFCMAC
: UAA specific symmetric key
To handle MAC
key type, the project transform JWK with this type to standard oct
type by
replacing kty
field and adding k
field with base64url
encoded key value.
UAA prior to version 3.10.0
returns an invalid alg
values for a signing key.
UAA issue #132796973
This project provides a workaround to correct (normalize) such values.
It is not recommended to use this library with UUA version prior to 3.10.0
The package can be installed as:
- Add
uaa_jwt
to your list of dependencies in theMakefile
forerlang.mk
:
DEPS = uaa_jwt
dep_uaa_jwt = git git://github.com/rabbitmq/uaa_jwt erlang
To verify tokens, you should configure one or many signing keys (JWK).
You can do that using the application environment or the uaa_jwt.add_signing_key
function.
To configure keys using the application environment:
or erlang .config
:
[{uaa_jwt, [{signing_keys, #{
<<"key1">> => {map, #{<<"kty">> => <<"oct">>, <<"k">> => <<"dG9rZW5rZXk">>}},
<<"key2">> => {pem, <<"/path/to/public_key.pem">>},
<<"legacy-token-key">> =>
{json, "{\"kid\":\"legacy-token-key\",\"alg\":\"HS256\",\"value\":\"tokenKey\",\"kty\":\"MAC\",\"use\":\"sig\"}"}
}}]}]
This config defines three signing keys.
The first one is a standard JWK
octet sequence key with base64url
encoded value for k
.
The second one is a filename for RSA public key.
The third one is a JSON result from a /token_key
request to UAA. It should be a binary or a string
To add a key using the uaa_jwt:add_signing_key
function:
uaa_jwt:add_signing_key(<<"key1">>, map, #{<<"kty">> => <<"oct">>, <<"k">> => <<"bXlfa2V5">>}).
This function will try to validate a key and add it to signing_key
application environemnt.
If a JWK token doesn't contain a kid
field, "default" key will be used.
Default key can be selected by using defeult_key
environment variable.
For example, if we want to make key1
a default key:
[{uaa_jwt, [{default_key, <<"key1">>}, ...]}].
By default, default key value is <<"default">>
If not configured, UAA server will use a MAC
symmtric key with a tokenKey
value by default.
To configure this plugin to decode tokens from unconfigured UAA, you should add this key to the configuration:
[{uaa_jwt, [{signing_keys, #{
<<"legacy-token-key">> =>
{map, #{<<"alg">> => <<"HS256">>,
<<"value">> => <<"tokenKey">>,
<<"kty">> => <<"MAC">>,
<<"use">> => <<"sig">>}}
}}]}].
Or you can add it dynamically:
uaa_jwt:add_signing_key(<<"legacy-token-key">>, map, #{<<"alg">> => <<"HS256">>,
<<"value">> => <<"tokenKey">>,
<<"kty">> => <<"MAC">>,
<<"use">> => <<"sig">>}).
After configuring the keys, you can decode a token using the uaa_jwt:decode_and_verify
function:
uaa_jwt:decode_and_verify(binary()) -> {true | false, map()} | {error, term()}.
The signing key will be selected according to the kid
field in
the JWS
part of the token.
Following functions can be used for debug purposes:
To get the kid
field only from a token:
uaa_jwt_jwt:get_key_id(Token).
To decode a token without signature verification:
uaa_jwt_jwt:decode(Token).
To validate a JWK
key (provided as a map or JSON document):
uaa_jwt_jwk.make_jwk(Jwk).
Please consult erlang-jose dosumentation for more functions and options.
2016 (c) Pivotal Software, Inc.
Distributed under the same license as RabbitMQ server.