Comments (4)
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.
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.
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.
@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)
- Laziness of boolean operators HOT 3
- Heterogeneous `==` HOT 1
- Dates: TAI64, TAI or UTC? HOT 2
- Purpose of the `Parens` op HOT 2
- `.type()` function
- Add array and map types HOT 1
- Biscuit web key sets HOT 7
- Forgotten symbol in samples.json? HOT 2
- Webauthn signatures
- Allow heterogeneous sets
- `reject if` HOT 4
- Datalog breaking changes
- Nullability HOT 1
- Type casting / parsing operations
- Commonalities and expectations for cross-language use
- Support for lambdas
- Confused over version numbering HOT 6
- Negation X2 HOT 1
- length() on strings HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from biscuit.