biscuit-haskell icon indicating copy to clipboard operation
biscuit-haskell copied to clipboard

Add pure version of authorizeBiscuit

Open kephas opened this issue 2 years ago • 9 comments

A lot of biscuit's functions that require IO or MonadIO could have either pure versions or versions that could run in a wider range of monads. authorizeBiscuit may be the simplest because its only dependency on IO is because of timer.

This would still require documenting that it must be run in a context where a bad biscuit wouldn't make authorizeBiscuitNoTimeout run for an extended time.

kephas avatar Mar 29 '23 23:03 kephas

Thanks!

I guess that apart from authorize, the other candidates are all functions depending on keypair generation, which could indeed be relaxed to MonadRandom.

Do note that there is planned support for ECDSA, which would turn some currently pure operations into monadic ones (but it should only add a MonadRandom constraint, not full-on IO)

divarvel avatar Mar 30 '23 06:03 divarvel

BTW, our use case is that we have Polysemy actions running in Servant, and it's not yet clear to us where we'd better validate or generate biscuits in our code, but the current implementation would force us to only use functions from biscuit-haskell in IO interpreters.

Having functions that only require MonadRandom would give us more options.

kephas avatar Mar 30 '23 23:03 kephas

BTW, our use case is that we have Polysemy actions running in Servant

Have you looked at biscuit-servant yet? My plan was to try it out with an effect system (probably effecful rather than polysemy though). Basically biscuit authorization is separated in two steps:

  • first, parsing & signature verification : this happens in an auth handler that's provided through Context. Currently this part is polymorphic on the monad (verification itself is pure, but there is a revocation check provided by the caller that has an applicative constraint)
  • then, authorization itself: it can happen either in a helper that you call in each endpoint and takes the handler code as a parameter, or in a natural transformation that you apply on all endpoints at the same time using hoistServer. IO is currently required here, and there are functions used in this context that can introduce a polymorphic monad constraint (when generating the authorizer requires effects: eg getting the current datetime), but there is still a monadio constraint.

Disabling an important check to please an effect system seems a bit dangerous to me. OTOH relaxing IO to MonadRandom for key generation preserves semantics and would unlock nice use cases.

It might be possible to declare the timeout check in a specific typeclass implemented by IO (the actual impl requires getCurrentTime and forkIO amongst other things) to make integrating with an effect system a bit easier

divarvel avatar Mar 31 '23 05:03 divarvel

We are indeed looking at biscuit-servant. At first glance, it would seem useful if we can use biscuit verification without needing effects like Embed IO or Final IO in our effects. It's not the case yet, but I plan to have some interpreters interpret effects in STM, where we could easily provide MonadRandom.

Is there a way to help you try testing an effect system with biscuit-servant?

kephas avatar Apr 01 '23 10:04 kephas

We are indeed looking at biscuit-servant. At first glance, it would seem useful if we can use biscuit verification without needing effects like Embed IO or Final IO in our effects. It's not the case yet, but I plan to have some interpreters interpret effects in STM, where we could easily provide MonadRandom.

MonadRandom is only useful/needed for biscuit generation. IO is needed for timeout management during authorization.

Is there a way to help you try testing an effect system with biscuit-servant?

I don't use Haskell at work anymore so i might not have time to do that before a couple weeks. I have used servant along effectful at my previous job, so i might try that.

That being said, all the servant helpers are polymorphic on the handler monad, so this should work with effects anyway.

Extracting the timeout check in a dedicated typeclass would make things easier if you want to forego timeouts (and IO) completely

divarvel avatar Apr 01 '23 18:04 divarvel

👋 I might have time to assist if you want to try and express the timeout check through a typeclass constraint, that could be discharged by IO itself, or by a dedicated effect.

divarvel avatar Apr 23 '24 19:04 divarvel

Great! How would you want to proceed?

kephas avatar May 03 '24 22:05 kephas

Great! How would you want to proceed?

Once you have rebased the PR to fix conflicts, maybe we can pair-prog on it and try to come up with a typeclass that can be compatible with an effect system (ideally effectful and polysemy)

divarvel avatar May 06 '24 12:05 divarvel

I think I'd be available enough in a few weeks to do that, that sounds like a plan.

kephas avatar May 13 '24 09:05 kephas