# SoarAuthenticationToken [![Gem Version](https://badge.fury.io/rb/soar_authentication_token.png)](https://badge.fury.io/rb/soar_authentication_token) This gem provides authentication token generation and validation capability for the SOAR architecture. ## Installation Add this line to your application's Gemfile: ```ruby gem 'soar_authentication_token' ``` And then execute: ```bash bundle ``` Or install it yourself as: ```bash gem install soar_authentication_token ``` ## Configuration of generators and validators There are three provider groups for operation: JwtToken, RemoteToken or StaticToken ### JwtTokenGenerator/JwtTokenValidator With the JwtTokenValidator provider the tokens are decoded, verified and meta extracted locally using configured key material. In practice the the token generation and validation services run in this mode since their roles are to generate and validate tokens. ### RemoteTokenGenerator/RemoteTokenValidator With the RemoteTokenValidator provider the tokens are passed to a token validation service for validation. This allows for a centralized management of tokens. The key material are therefore managed on the validation service and . In this mode you only have to provide the url of the validation service. ### StaticTokenValidator In this mode the StaticTokenValidator is configured with a list of preconfigured static tokens. Incoming tokens are simply checked against this list. No extraction of meta is performed on the tokens but retrieved from the configuration. Rotation of tokens is simple since many tokens can be configured. This mode is to be used in only two scenarios: * Between the various authentication token services that requires authentication between themselves. These services themselves do not the benefit of another centralized authentication service to rely on. * In test scenarios where you do not want to pull in the authentication services to perform testing of your services. ## Testing Run the rspec test tests using docker compose: ```bash export UID; docker-compose build --force-rm --no-cache docker-compose down export UID; docker-compose run --rm soar-authentication-token docker-compose down ``` ## Updating For test purposes this repo relies on various other repos with services. This is to test the interaction between the generator and validation clients and these services. In order to pull the latest from the referenced projects and build fresh docker images, simply the following commands: ```bash git pull && git submodule foreach 'git fetch origin --tags; git checkout master; git pull' docker-compose down docker-compose build --force-rm --no-cache ``` ## Usage ### KeypairGenerator In support of generating JWT tokens this class is responsible for generating an EC keypairs in PEM format. Use this when rotating keypairs in production or for testing the generators/validators. ```ruby generator = SoarAuthenticationToken::KeypairGenerator.new private_key, public_key = generator.generate ``` ### RackMiddleware The rack middleware allows you to perform validation of all requests before it even hits your resource. The middleware also populates the 'user' key in the rack session with the authenticated identifier and the 'auth_token_meta' key with meta regarding the authentication that might be useful to more sensitive services. First step is to configure the middleware. Actually you are not configuring the middleware but the TokenValidator instance that will be used in the validation. Most of the time you will be reaching out to a remote validation service and configure it as such: ```ruby @iut_configuration = { 'provider' => 'SoarAuthenticationToken::RemoteTokenValidator', 'validator-url' => 'http://authentication-token-validator-service:9393/validate' } @iut = SoarAuthenticationToken::RackMiddleware.new(@test_app, @iut_configuration) ``` The middleware will look for the authentication token in the HTTP header 'AUTHORIZATION'. Please refer to the rack middleware spec for detailed examples on how to use the middleware. ### TokenGenerator The class generates tokens or requests a token from a generator service as configured. For remote token generation, configure as such: ```ruby @configuration_remote = { 'provider' => 'SoarAuthenticationToken::RemoteTokenGenerator', 'generator-url' => 'http://authentication-token-generator-service:9393/generate', 'generator-client-auth-token' => 'xxxx' } ``` For local token generation, configure as such: ```ruby generator = SoarAuthenticationToken::KeypairGenerator.new private_key, public_key = generator.generate @configuration_local = { 'provider' => 'SoarAuthenticationToken::JwtTokenGenerator', 'private_key' => private_key } ``` Create storage client. The example here uses a local stub client that uses a in-memory store. ```ruby gem 'auth_token_store_provider', "~> 1.0.1" require 'auth_token_store_provider' store = AuthTokenStoreProvider::StubClient.new ``` After configuration you simply generate a token like this: ```ruby generator = SoarAuthenticationToken::TokenGenerator.new(configuration) generator.inject_store_provider(store) token, token_generator_meta = generator.generate(authenticated_identifier: 'someone@hetzner.co.za', flow_identifier: 'test-flow-id') ``` ### TokenValidator The class validates tokens or requests validation of a token from a validation service as configured. For remote token validation, configure as such: ```ruby @configuration_remote = { 'provider' => 'SoarAuthenticationToken::RemoteTokenGenerator', 'validator-url' => 'http://authentication-token-validator-service:9393/validate', } ``` For local token validation, configure as such: ```ruby generator = SoarAuthenticationToken::KeypairGenerator.new private_key, public_key = generator.generate @configuration_local = { 'provider' => 'SoarAuthenticationToken::JwtTokenValidator', 'public_key' => public_key } ``` Create storage client. The example here uses a local stub client that uses a in-memory store. ```ruby gem 'auth_token_store_provider', "~> 1.0.1" require 'auth_token_store_provider' store = AuthTokenStoreProvider::StubClient.new ``` After configuration you simply valiate a token like this: ```ruby validator = SoarAuthenticationToken::TokenValidator.new(configuration) validator.inject_store_provider(store) token_validity, token_validator_meta, messages = validator.validate(authentication_token: token, flow_identifier: 'test-flow-id') ``` ## Contributing Bug reports and feature requests are welcome by email to barney dot de dot villiers at hetzner dot co dot za. This gem is sponsored by Hetzner (Pty) Ltd (http://hetzner.co.za) ## Notes ## License The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).