CrowCpp / Crow

A Fast and Easy to use microframework for the web.
https://crowcpp.org
Other
3.13k stars 347 forks source link

HTTP Auth Middleware #363

Open The-EDev opened 2 years ago

The-EDev commented 2 years ago

Since #327 was merged, adding a middleware for HTTP authentication should be possible and would be a better solution than the current guide.

joelguittet commented 2 years ago

I'm interested by this as well.

dranikpg commented 2 years ago

Such a module has to be carefully planned ahead. Many of them end up inflexible or difficuly to use (even in big frameworks).

I'm still not sure to what extend local middleware should be used here. Its a good fit for wrapping a small group of handlers. Authentication is usually applied to the whole application. Except maybe some landing page, Spring hands out its JSESSION out to literally anybody. Authorization (different roles, rights, etc. ) is applied often applied selectively (i.e. you have to admin to access /admin/).

How to apply things selectively on big handler groups?

  1. Some frameworks, like Spring, use a global builder with route prefixes.
  2. Others, like Laravel, use route groups.

What path to take has to be decided ahead, so all middleware stays uniform and all further development and changes conform to it.

  1. Prefixes would look like those in CORS handlers (Yes, I've put that decision off when implementing them 🥲 )
  2. Route groups are more popular in new and evolving libraries (almost all GO frameworks are built around them). We already have blueprints that can be used similarly once you allow to assign middleware to them.
//             | - list special middlware only for that bp
//             |   now you dont have to call CROW_MIDDLEWARES() on each route
//             |
Blueprint<AdminGuard> adminbp(prefix);
// ...
app.register_blueprint(adminbp);

This seems quite convenient to me. But now you're forced to use blueprints everywhere.

The other question is what should be supported. The more features you support, the harder it is to make them flexible.

I'll think about it once again and write back shortly. What's your vision like?

The-EDev commented 2 years ago

How to apply things selectively on big handler groups?

In my experience using Flask I just added @auth.login_required() to the top of any route that needed authentication. Hence my conclusion that Local middleware should be used.

Prefixes would look like those in CORS handlers

I think CORS was a special case in that you needed those headers regardless of which route you took, the difference between routes was which headers would be sent. So it made sense to sort out prefixes inside the middleware rather than before it's even called. That's not exactly the case with Authentication, since a route not requiring Authentication wouldn't need to run any of that code to begin with.

We already have blueprints that can be used similarly once you allow to assign middleware to them.

In my opinion this would be the best and most consistent option.

This seems quite convenient to me. But now you're forced to use blueprints everywhere.

This is somewhat mitigated by the fact that (at least for production applications) you're supposed to use blueprints everywhere, they're designed to segment the application with as little hassle as possible on the developer's side.

It would be ideal if local middleware could also be applied to blueprints, rather than having a third kind of middleware.

The idea generally for Crow is somewhat driven from python Flask, in that it's easy to use and very easy to get started with. But with the addition of keeping the inner workings of HTTP accessible for anyone who wants a feature that hasn't been implemented yet.

I hope this has explained my general stance on the issue. And I'm sorry I didn't respond right away (I tend to take weekends off in order to keep some semblance of work-life balance).

dranikpg commented 2 years ago

Great 👍🏻 I'm in for Blueprints as well. I'm currently working on middleware for them to lay the basis for this feature.

dranikpg commented 2 years ago

Lets close this issue in favour of https://github.com/CrowCpp/Crow/issues/376#issuecomment-1213539833

The-EDev commented 2 years ago

@dranikpg I disagree on the idea that an Auth middleware isn't needed, it might be useful to have some examples on how to implement things like token storage or JWT creation, but handling those (whether it's functions to create tokens that people can assign or authenticating those tokens in a route) should be done through a simple interface.

I think we need to provide some framework to guide people building their auth system (without them needing to access headers directly or splitting strings etc...)