cutelyst / cutelyst

A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
https://cutelyst.org
BSD 3-Clause "New" or "Revised" License
895 stars 115 forks source link

Stash after User Authentication #463

Open simaxw opened 1 week ago

simaxw commented 1 week ago

Hello,

I am running Cutelyst 4.3.0 and using the Authentication Plugin. So in my authentication route which is decorated like:

C_ATTR(login, :Local :Args(0) :ActionClass("RenderView") :View("json_view"))
void login(Context *c);

so, returns a JSON representation of the stash once I authenticate the user successfully using:

if (!Authentication::authenticate(c, {                                         
        {"name", username}, {"password", password}                               
        })) {                                                                    
    RESPONSE_ERR_CODE("Login Failed with Credentials", Response::Forbidden);     
  }                                                                              

AuthenticationUser userObject = Authentication::user(c);
// Do something wth the user info returned from the authstore

c->setStash("message", "Login successful");

which works perfectly fine. However, since c is passed to authenticate, it is used to alter the stash which results in:

> curl -s -H 'Content-Type: application/json' --data '{"username":"holgi", "password":"letmein"}' http://localhost:4000/authen/login | jq
{
  "_c_authentication_user": null,
  "_c_authentication_user_realm": "cutelyst_authentication_default_realm",
  "_c_session_expires": 1719788796,
  "_c_session_extended_expires": 1719788796,
  "_c_session_id": "b664bb3347fa4812b9b38d83b3b40b50",
  "_c_session_store_file_data": {},
  "_c_session_tried_loading_expires": true,
  "_c_session_tried_loading_id": true,
  "_c_session_updated": true,
  "_c_session_values": {
    "__authentication_user": null,
    "__authentication_user_realm": "cutelyst_authentication_default_realm",
    "__created": 1719781596,
    "__updated": 1719781596,
    "_c_authentication_user_realm": "cutelyst_authentication_default_realm"
  },
  "message": "Holger Schmidt-Luchtenberg logged in."
}

This arises two questions:

  1. An attempt is made to serialize the AuthenticationUser instance which fails and just returns null. But even if it would succeed: Is that really desirable? Maybe the object from the store does not always match what we want to return to the client.
  2. Various variables are repeated in _c_session_values and the realm name is present three times under different keys. Was this intended?
dantti commented 1 week ago

You can filter what you want exposed with setExpose.. https://api.cutelyst.org/classCutelyst_1_1ViewJson.html#ae94f43054d685f4b0fd348f1db09fe16 I myself don't actually use ViewJson as I prefer to just call c->response()->setJsonObjectBody({ {"foo", "bar" } });

dantti commented 1 week ago

about the duplicate values they are likely from the same source but maybe exposed with different Q_PROPERTIES, not sure woul need to investigate further

simaxw commented 1 week ago

Hi dantti, thank you for the quick reply. Regarding the setExpose: As far as I could see only the first level is checked and filtered. In case I have a JSON structure on a deeper level I have to take care of it myself I guess.

But the actual issue/question is: Why does serialization of AuthenticationUser instance it return null even though you Q_DECLARE_METATYPE'd it?

dantti commented 1 week ago

because it doesn't know how to serialize that to a json value