Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seperate authorization to different routes #21

Open
GeorgeTsagk opened this issue Jun 18, 2021 · 6 comments
Open

Seperate authorization to different routes #21

GeorgeTsagk opened this issue Jun 18, 2021 · 6 comments

Comments

@GeorgeTsagk
Copy link

Current implementation has a global perception of authorizing a client.
E.g. After I pay the invoice I can provide the Authorization header and access a protected resource, but this same header will allow me to pass through any other protected route. There is no differentiation between which resources this specific header can access.

I have tried defining different boltwall middleware instances like this

app.get('/download', boltwall(options), fileController.downloadFile);

app.post('/upload', boltwall(options), fileController.uploadFile);

but it doesn't seem to get the job done as paying the /download endpoint will also grant me access to the /upload endpoint

Is there a way to provide access to specific routes and not to the whole API?

@bucko13
Copy link
Collaborator

bucko13 commented Jun 29, 2021

Hey @GeorgeTsagk

Thanks for filing this issue and so sorry for the delay. Not sure why I never got an email from GitHub.

In any case, the most straightforward solution that comes to mind with the given setup would be to create a custom config that checks on a per path basis. A pre-built one comes with boltwall that is going to be similar to what you need, the ORIGIN_CAVEAT_CONFIGS which makes sure that an LSAT is only valid for the originally requesting origin IP. So in your case you would have one for each path, or create a function that takes a path and returns a new config based on that path. That would then get passed into the instantiation of boltwall in the options as you have above. To see what this config would look like take a look at this file. You'll notice in that one that the caveat minter actually gets access to the request object, so you could make this dynamic such the path is pulled from the request object and used to create the caveat that's added.

This seems like a very useful caveat config to have actually. If you end up doing something like this, let me know as I'd be happy to consider adding it to the built in configs available with the library. And if you have any questions about how the caveats work, don't hesitate to reach back out. I'll make sure GH is sending me emails form now on!

@GeorgeTsagk
Copy link
Author

Hey @bucko13 , thanks for commenting back.

I will eventually implement this caveat, and I shall also comment again once that is done.

@brh28
Copy link

brh28 commented Jul 6, 2021

Hey @bucko13, alluding to your comment above, the getCaveats field is a function. To my understanding, this allows us to instantiate one config per many requests. However, the 'minAmount' is defined as a 'string | number,' which fixes the price for each request.

I'm wondering if there's a way is to adjust the 'minAmount' based on the request, without instantiating a unique config for each possible request.

For example:
/paywall?id=1 has minAmount = 5
/paywall?id=2 has minAmount = 10

@bucko13
Copy link
Collaborator

bucko13 commented Jul 7, 2021

So, minAmount doesn't really "fix" the price. Perhaps it's confusingly named, but it's basically just a fallback or a default in case there is no amount indicated in the request so that if there's no way to determine how much to make the invoice for, there's something to use as a default.

The idea in boltwall is that the client can actually be the one that says how much it wants to pay. This may seem counter-intuitive, but when you tie this to the caveats in the LSAT it can be quite powerful: the request indicates how much the client wants to pay, and the caveats can restrict access based on how much they decided. With the caveat you can create access restrictions based on how much the client offered to pay without having to determine a fixed amount. So for example, if you have a time-based system with access for 1 minute per 100 sats, if the client asks for an invoice to pay 1000, boltwall can create an LSAT caveat that expires in 10 minutes. This is essentially what the built-in time config does here.

If you wanted to create a system where the user or client didn't have to make any decisions about the amount, and you wanted this all to happen on the server, you could create a middleware that's before boltwall that sets the amount in the request body (or a query string) based on the route. Then that gets passed to boltwall which will create the invoice based on this value (that happens here).

So, that would look something like this:

app.use((req, res, next) => {
  if (req.query.id === 1) req.query.amount = 5
  else if (req.query.id === 2) req.query.amount = 10
  next()
})

app.use(boltwall())

The above is very rough and you might want to do different customizations for sub paths or something, but hopefully that helps give you an idea.

As you can see, this check doesn't actually have to interact with boltwall at all. If all you want to do is only allow access if an invoice of a certain amount is paid, then you don't actually need a special caveat; the LSAT will be valid if the invoice created was paid and invalid if it wasn't. If you wanted to tie other conditions on it, like time, then you can add that via the configs.

Hope that helps!

@brh28
Copy link

brh28 commented Jul 7, 2021

Thank you @bucko13! Definitely gives some good direction. I’ll play around with this today.

@aaroncj1
Copy link
Contributor

Opened a PR to address this feature: #28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants