GithubHelp home page GithubHelp logo

Comments (4)

Geal avatar Geal commented on July 28, 2024

there might be something I am missing here, so please tell me where I am turning the wrong way:

  • the microservices can be started with a list of allowed domains, so they can be configured
  • that means they can be configured with a list of bwks URLs, and they can be downloaded on startup (and refreshed regularly)
  • try to verify the token signature using each of the bwks (using the root key id to select them if provided)
  • if the microservice needs to know the token's origin for something else than signature verification (ex: to load some specific policies), now you know which one matched

Architectures where you would download the list of keys on demand are generally dangerous, because it is then easy to fall into the flaw of hammering on the identity provider, or worse, starting to download from random URLs during verification. Root keys should be loaded out of band, not in the hot path (which is why the RootKeyProvider in rust is not async)

from biscuit.

pcolmer avatar pcolmer commented on July 28, 2024

I can identify one main philosophy difference here ... your comment seems to suggest an assumption that the microservices start up and then continue running. I'm inferring that from your suggestion that the bwks can be downloaded on startup and refreshed regularly.

Our code is running as AWS Lambdas, triggered by API Gateway. There isn't any persistence. Given the bwks specification, we were going to follow a similar approach to the one we use when verifying Auth0 JWTs ... you query the well known URL at the point of verifying the token.

In a stateless system, fetching bwks from multiple URLs potentially has a serious performance impact, hence the suggestion of using a domain mechanism.

I guess we could tackle it by using an out of band process for pulling the keys into, say, AWS Secrets Manager for the Lambda code to cycle through each public key in turn, but that just doesn't feel elegant. It feels almost brute force when one considers that the biscuit knows the root key ID - it just doesn't (currently) know who created it.

starting to download from random URLs during verification

That shouldn't happen given the proposal that the client knows which domains are acceptable and the authorizer would only fetch the bwks if the client's domain list includes the domain recorded in the biscuit.

Part of the reason for proposing this was because the Golang library doesn't support unauthenticated inspection of a biscuit. So we aren't able to retrieve the domain fact from the biscuit without creating an authorizer first, which requires the public key ...

from biscuit.

Geal avatar Geal commented on July 28, 2024

I can identify one main philosophy difference here ... your comment seems to suggest an assumption that the microservices start up and then continue running. I'm inferring that from your suggestion that the bwks can be downloaded on startup and refreshed regularly.

ok, your question makes more sense in the context of lambdas. I would still caution against downloading the keys on demand. While providers like Auth0 can handle a reasonable traffic, most IdPs tend to rate limit JWKS downloads, because the IdP is not supposed to bear the same load as the application.

I guess we could tackle it by using an out of band process for pulling the keys into, say, AWS Secrets Manager for the Lambda code to cycle through each public key in turn, but that just doesn't feel elegant. It feels almost brute force when one considers that the biscuit knows the root key ID - it just doesn't (currently) know who created it.

honestly that's the kind of solution that would feel more reasonable to me. Even if it's not elegant, you don't run the risk of authorization failing if an easily cacheable file cannot be downloaded.

Part of the reason for proposing this was because the Golang library doesn't support unauthenticated inspection of a biscuit. So we aren't able to retrieve the domain fact from the biscuit without creating an authorizer first, which requires the public key ...

This is a more important issue. In the rust library, we have the UnverifiedBiscuit structure for that, and token blocks contain a context field that you could use to recognize token origin. The UnverifiedBiscuit API tends to be strict in preventing access to block data before verifying signature, but maybe that could be relaxed for the context field. Anyway, it should be added to the Go library

from biscuit.

pcolmer avatar pcolmer commented on July 28, 2024

@Geal I understand your concerns about downloading the bwks too frequently.

How about taking your philosophy and using it to influence my suggestion? Rather than passing an array of domain strings, how about passing a dict of bwks blobs, with the keys being the domain strings? For example:

{
   "example.org":     [
      {
         "algorithm": "ed25519",
         "key_bytes": "edaabea9448310d5b54874a0ca5e431b4fed84f949d311c17945104f32afd77c",
         "key_id": "de76f169-22ed-4b29-88f4-3d98c0604067",
         "expires_at": 1704480249918
      },
      {
         "algorithm": "ed25519",
         "key_bytes": "1b4fed84f949d311c17945104f32afd77cedaabea9448310d5b54874a0ca5e43",
         "key_id": "3d98c0604067-4b29-88f4-de76f169-22ed",
         "expires_at": 1703370138818
      }
   ]
}

So code (call it the Client for reference later) wanting to creating an authorizer for an incoming biscuit will already have the bwks blobs for each of the domains they support. The code passes that dict to a new "authorize with bwks" function. That function tries to match the dictionary keys against the domain fact and, if no match, authorization fails.

If the domains match, the next test is the root key id. Again, if no match, authorization fails.

If the IDs match then the authorizer knows which public key to try ... and if that fails, authorization fails.

Otherwise, I'm struggling to see the value of the bwks file. Yes, it is a means of publishing the public key but the code wanting to create an authorizer needs to try each public key in turn which seems a waste of time when the biscuit (optionally) contains the root key ID which should match the key ID.

using the root key id to select them if provided

But reading the root key ID presumably requires the unverified access, along with the Client then needing to understand the internal structure of a biscuit ... something that then brings the added complexity of needing to update the Client when a new version of the biscuit structure is released. If the libraries instead are responsible for understanding the biscuit structure, getting them to process bwks blobs would seem to take that responsibility away from the Client in a clean way.

from biscuit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.