Centralized auth server for issuing JWTs from multiple providers
This is a node/express application that provides centralized and consistent JWT provisioning. It delegates the actual authentication to a variety of identity providers (allowing the true experts to perform the hard part). The JWTs provisioned by this application are signed using PKI to support simple and quick validation using a cached public key.
- Focused on authentication
- Single secure source for signed JWTs
- Leverages existing identity providers
- Provides decoupling from identity providers
- Stateless
- The application (JWTC) provides a simple login page at
/login
that allows the user to select an identity provider. - The user agent is redirected to the identity provider for the OAuth or OpenID Connect authorization code flow.
- After the user authorizes the application, the user agent is redirected back to the JWTC callback.
- Various code and state values are validated, and an access token is acquired from the identity provider.
- In most cases, the access token is used to request the user profile from the identity provider.
- JWTC creates a JWT from the profile.
- JWTC signs the JWT with a private key.
- JWTC returns the JWT to the user agent
- The user agent caches the JWT to be used for API endpoints.
- The API service can validate the JWT by using the cached public key (paired with the key used to sign the JWT).
PassportJS provides an easy way to include pluggable libraries for various identity providers. There is an extensive collection of middleware modules in the passport ecosystem.
Uses the google account email as the subject.
Uses the github profile URL as the subject. Note see this related to the latest version. For now you'll notice a github reference for this in package.json.
- JWTs should be carefully protected. They can be a single point of failure in a secure system.
- HTTPS should be used for all traffic that includes a JWT
We're using a strategy that uses short-lived dynamic tokens for the state parameter. The user agent holds onto the state token for the duration of the authentication/authorization flow. This prevents CSRF attaches to the callback endpoint (details here).
Most of the time, you'll deploy a configurable reverse proxy in front of both JWTC and your own web application to avoid cross-domain issues. With this approach, JWTC is effectively bundled with your own web application (running as a micro-service). This is the model expected by most identity providers when you register an application with them.
JWTC can also serve as a single authentication service supporting multiple APIs. In this scenario, you'll need to architect an out-of-band method to pass the JWT from the user agent to your API client. You would register JWTC as a generic authentication application with the identity providers.
The client module can be found here.
First, install the dependencies:
npm install
Create a production RSA key for JWT signing:
cd scripts
sh ./genkeys.sh
To start the server, edit the run.sh script as necessary and:
cd scripts
sh ./run.sh
Clients can download the public key at /key
with something like:
curl localhost:8000/key
npm install -g mocha
mocha
npm install -g jshint
jshint app
jshint test