# Bridgeman Accessible Auth Keystore This is the implementation of the Bridgeman Accessible Auth Keystore. Keystores form the foundation for how [JSON Web Keys (JWKs)](#jwks-and-node-jose) management happens within the [Bridgeman Accessible Auth library](https://git.bridgemanaccessible.ca/Bridgeman-Accessible/ba-auth). JWKs play an important role in signing and encrypting JWTs and other information which are used throughout that library. Having a flexible but reliable way to store and retrieve JWKs is one of the most critical backbones for that infrastructure to work properly. ## Table of Contents - [Provided Here](#provided-here) - [Testing](#testing) - [Background / Info](#background--info) - [Why A Separate Library](#why-a-separate-library) - [Flexibility / Extensibility](#flexibility--extensibility) - [Light Weight](#light-weight) - [JWKs and `node-jose`](#jwks-and-node-jose) - [Existing Keystore Types](#existing-keystore-types) - [New Keystore Types](#new-keystore-types) - [Creating A New Keystore Type](#creating-a-new-keystore-type) - [Registering A New Keystore Type](#registering-a-new-keystore-type) - [Using The New Keystore Type](#using-the-new-keystore-type) ## Provided Here This package/library provides the "abstract" underlying code to make Keystores work. In particular it implements the [Registry Pattern](https://www.geeksforgeeks.org/system-design/registry-pattern/) and provides the centralized registry (`Keystore`) and the underlying abstract base type (`BaseKeystore`). See the [New Keystore Type](#new-keystore-types) section below for more details how this all fits together. ### Testing This package includes testing to be able to validate that the core logic works. The test suite can be run by running `yarn test` in any terminal/shell that supports Yarn. The test suite is run automatically as part of the publish CI/CD automation on push. ## Background / Info ### Why A Separate Library If it forms one of the main backbones for the [Auth library](https://git.bridgemanaccessible.ca/Bridgeman-Accessible/ba-auth) it makes sense to ask the question *why have it as a separate library?* The answer has two main parts: 1. [Flexibility / Extensibility](#flexibility--extensibility) 2. [Light Weight](#light-weight) Not directly related to the rational for having it as a separate library but rather a consequence of it being a separate library is that testing becomes significantly more isolated and concentrated which hopefully means better coverage and overall utility of testing. #### Flexibility / Extensibility A very critical idea we embrace when doing any kind of development on security related code is that the development is never over. That is, security is an always moving target because attackers are forever finding new vulnerabilities or methods of compromising things. As a direct consequence of embracing this idea, we're often trying to develop something that is long-lasting and reusable but flexible enough to deal with the concerns of the day. Or to put it another way, having mechanisms that allow for future extensibility. #### Light Weight In conjunction with the point about flexibility / extensibility above as reusable code that we want used in various different places making this code light weight and "portable" ws something we spent time being intentional about. ### JWKs and `node-jose` The underlying technology of Keystores is [JSON Web Keys (JWKs)](https://datatracker.ietf.org/doc/html/rfc7517) and specifically the [`node-jose`](https://www.npmjs.com/package/node-jose)'s implementation of it ([`node-jose`](https://www.npmjs.com/package/node-jose) was chosen not just for JWKs support but also it's support for standards like [JSON Web Encryption (JWE)](https://datatracker.ietf.org/doc/html/rfc7516), [JSON Web Signatures (JWS)](https://datatracker.ietf.org/doc/html/rfc7515) and [JSON Web Tokens (JWTs)](https://datatracker.ietf.org/doc/html/rfc7519) which are all technologies used extensively throughout the [Bridgeman Accessible Auth library](https://git.bridgemanaccessible.ca/Bridgeman-Accessible/ba-auth) for secure communications). ## Existing Keystore Types *Note, this section is for easy reference but shouldn't be interpreted as authoritative in any way* At time of writing there are several different Keystore types available: - [File Keystore](https://git.bridgemanaccessible.ca/Bridgeman-Accessible/ba-auth_keystore_file) - [Vault Keystore (Hashicorp Vault)](https://git.bridgemanaccessible.ca/Bridgeman-Accessible/ba-auth_keystore_vault) - [Keyvault Keystore (Azure Key Vault)](https://git.bridgemanaccessible.ca/Bridgeman-Accessible/ba-auth_keystore_keyvault) It's worth noting our internal convention for package names that are downstream ("implement") this package is `ba-auth_keystore_` where `` is replaced by the type (`ba-auth_keystore` prefix being the name of this package). ## New Keystore Types Flexibility to develop new Keystore types as/when needed or desired was something we took time and effor to support. ### Creating A New Keystore Type To create a new Keystore type all you need to do is create a subclass of the abstract `BaseKeystore` class which can be imported from this module/package/library and register it on the `Keystore` constant also exported from this library. That said, it's worth noting the most critical part of this is assigning a value to the protected `keystore` property. This is typed as an instance of `JWK` from [`node-jose`](https://www.npmjs.com/package/node-jose) which, in all honesty, isn't the easiest to implement because of choices that were made by those developers when it comes to making most of the methods synchronous instead of asynchronous which for I/O is kind of unfortunate. ### Registering A New Keystore Type To register a new keystore type (once developed as described above) all you need to do is call `Keystore.addKeystoreType` (which `Keystore` similar to `BaseKeystore` is available from this library) and provide a "key" string (how it's identified) and either the class (provided it has a public constructor) or a factory method. ### Using The New Keystore Type It's worth consulting the [Bridgeman Accessible Auth library](https://git.bridgemanaccessible.ca/Bridgeman-Accessible/ba-auth) documentation as the more authoritative resource on how to use new keystore types. But at time of writing, and in principal, during setup of the Client, ResourceServer, Server or other object one of the options is a `keystoreType` string parameter (it varies a bit across the different objects) but if you use the same key that the new keystore type was registered with this will initialize the Keystore of the new type