Asymmetric JWT (JWS)

The E-Commerce Team has updated our OAuth access token endpoint to optionally return a JWT access token. This is an implementation of a previously-distributed design. Our current implementation relies on a shared secret key to sign JTWTs. We want to avoid sharing secrets across our IDAs as this poses a security risk and requires simultaneous IDA deployment/downtime to update the key. Asymmetric keys allow us to share only the public key while limiting access to the private key solely to the authentication server. Additionally, OpenID Connect's Discovery protocol gives us a standard by which we can distribute the public key without needing to redeploy reliant IDAs.

OpenID Connect's Discovery protocol supprts providing a link to one, or more, public keys at a well-known endpoint. We will use this endpoint to share our public keys. IDAs will be updated to retreive, and cache, these keys periodically. A management command will also be in place manually update the keys when necessary.

Updating signing keys

Updating signing keys is a two-step process. Step 1: add the new public key to the array of  keys returned by the well-known endpoint. This will allow clients to pick up the new key. Step 2: remove the old public key from the array after all JWTs signed with the old key have expired. It is important that we wait until we are reasonably certain the tokens have expired; otherwise, we run the risk of erroneously revoking a valid request.

Revoking signing keys

In the event that a private key is compromised, all previously-issued JWTs should be considered invalid. Thus, a new key should be generated to replace the existing key. The key update management command should be run on all IDAs.

 

Implementation notes

  1. This work is being tracked by ECOM-3629 - Getting issue details... STATUS .
  2. We can choose to either generate our own keys or use certificates that can be validated against a certificate authority (CA) for added security.
  3. An implementation of the well-known endpoint is provided in django-oidc-provider at https://github.com/juanifioren/django-oidc-provider/blob/a0c7b3c0c40af08c6eccf8a2731fb21a9804871e/oidc_provider/views.py#L176-L225.