efixler / scrape

Web Scraping Service
Mozilla Public License 2.0
5 stars 4 forks source link

JWT generation and verifications #21

Closed efixler closed 4 months ago

efixler commented 4 months ago

Background:

This PR is the first in a set of changes adding authorization capabilities to scrape to support access [over the open internet] from both AWS (for Pocket) and Outerbounds GCP clusters (for ML).

The recommended approach was to use Google's IAP auth proxy. I spent some with the docs/tooling -- it's a bit complicated and apparently non-trivial to up.

At the same time, using IAP and also requires the ability to make and verify JWT tooling in an app that uses it so I'm building those pieces, which can also provide an generic authorization token capability with or without IAP. We'll get to IAP in a later step.

What's here:

This PR adds a package to scrape to create, sign, verify and decode JWTs, along with a pair of shell commands (scrape-jwt-encode and scrape-jwt-decode) to generate HS256 secret encode/sign and decode/verify tokens from the command line.

The JWT claims themselves are pretty minimal, containing the essentials of what you need to implement API consumer-type authorization (sub for the consumer you're issuing the key to, an expiration time, etc.)

This PR does not change any facet of authorization for a running service instance, that will come in a later PR.

Steps to test

Getting Started

  1. Checkout this branch
  2. From the repo root, run make

To run the unit tests, run make test. To test the new shell commands, read on.

All of the test steps use the scrape-jwt-encode and scrape-jwt-decode binaries. You can get complete help for these by invoking either with -h.

Making an HS256 secret key

  1. ./build/scrape-jwt-encode -make-key

The app will print out a base64 encoded string representing a cryptographically random 256 bit key.

For the next tests, you'll need to pass that secret to the apps to encode and decode JWT keys. The easiest way to do that is to:

  1. Set an environment variable called SCRAPE_SIGNING_KEY to the base64 string from the above step. (e.g. export SCRAPE_SIGNING_KEY=8q6R97jhw4cH6PExQ8MvWoANfBbA97CsAA3lsZfmo2Q=)

Encode a JWT key

  1. ./build/scrape-jwt-encode -sub pr-test

You should see a result like this:

./build/scrape-jwt-encode -sub pr-test                                

Claims:
------
{
  "iss": "scrape",
  "sub": "pr-test",
  "aud": [
    "moz"
  ],
  "exp": 1747083931,
  "iat": 1715547931
}

Token:
-----
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY3JhcGUiLCJzdWIiOiJzb21lb25lIiwiYXVkIjpbIm1veiJdLCJleHAiOjE3NDcxMDUwNzQsImlhdCI6MTcxNTU2OTA3NH0.YqDlwXXNgwQXN_EBeKe5_UMBiOy18cUEjBKJxLzkHUk

The echoed token contains the claims listed above them, signed with with key that was generated in the above test.

Copy this token to your clipboard, you will use it in the next test.

Decode a JWT key

./build/scrape-jwt-decode eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzY3JhcGUiLCJzdWIiOiJzb21lb25lIiwiYXVkIjpbIm1veiJdLCJleHAiOjE3NDcxMDUwNzQsImlhdCI6MTcxNTU2OTA3NH0.YqDlwXXNgwQXN_EBeKe5_UMBiOy18cUEjBKJxLzkHUk

Output should show the claims matching the above:

This JWT is valid. Claims:
------
{
  "iss": "scrape",
  "sub": "pr-test",
  "aud": [
    "moz"
  ],
  "exp": 1747083931,
  "iat": 1715547931
}