rabbitmq / uaa_jwt

Json Web Token decoder, currently targeting UAA-specific token structure

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

UAA JWT Decoder

Project Status

This library has been folded into the RabbitMQ OAuth 2/JWT plugin plugin.

Overview

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.

Erlang and Elixir versions of the library

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.

Dependencies

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

(Current) Limitations

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 Key Management

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 RFC
  • MAC: 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.

Known UAA Bugs

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

Installation

The package can be installed as:

  1. Add uaa_jwt to your list of dependencies in the Makefile for erlang.mk:
DEPS = uaa_jwt
dep_uaa_jwt = git git://github.com/rabbitmq/uaa_jwt erlang

Usage

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.

Configuration

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">>

Running with demo UAA

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">>}).

Decoding

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.

License and Copyright

2016 (c) Pivotal Software, Inc.

Distributed under the same license as RabbitMQ server.

About

Json Web Token decoder, currently targeting UAA-specific token structure


Languages

Language:Erlang 97.5%Language:Makefile 2.5%