sessionrustrust-warp

Data stored in warp Session does not persist


I am trying to set up a server backend as an exercise.

I want to store some data in warp_sessions::MemoryStore but I cannot achieve it. I base on the warp_sessions/examples/shared_mutable_session example.

I can get the data written into the session. I can read it back immediately after I write into it (variables _a and _b in the code below), but they don't persist between the calls. The variables _a_pre and _b_pre return empty string on the consecutive handler calls.

Now the questions:

My route handler function looks like this:

pub async fn verify_handler(body: warp::hyper::body::Bytes, mut session_with_store:SessionWithStore<MemoryStore> ) -> Result<(Html<String>, SessionWithStore<MemoryStore>), Rejection>  {

  session_with_store.cookie_options = warp_sessions::CookieOptions {
    cookie_name: "siwe_minimal",
    cookie_value: None,
    max_age:Some(3600),
    domain: None,
    path: None,
    secure: true,
    http_only: true,
    same_site: Some(SameSiteCookieOption::Strict),
  };
  
  let shared_session = Arc::new(RwLock::new(session_with_store.session));
 
  let _a_pre: String = shared_session
      .read()
      .unwrap()
      .get("nonce")  
      ..unwrap_or_default();

  shared_session
      .write()
      .unwrap()
      .insert("nonce", nonce )   
      .unwrap();
    
  let _a: String = shared_session
      .read()
      .unwrap()
      .get("nonce")  
      .unwrap();

  let msgstr = message.to_string();

  let _b_pre: String = shared_session
  .read()
  .unwrap()
  .get("siwe")  
  .unwrap_or_default(); 

  shared_session
      .write()
      .unwrap()
      .insert("siwe", msgstr)  
      .unwrap();

       
  let _b: String = shared_session
  .read()
  .unwrap()
  .get("siwe")  
  .unwrap();

   
  session_with_store.session = Arc::try_unwrap(shared_session)
      .unwrap()
      .into_inner()
      .unwrap(); 


  Ok::<_, Rejection>(
    (
      warp::reply::html("req".to_string()),
      session_with_store
    )
  )

}

the route is defined like this (if it matters):

let session_store = MemoryStore::new();
let verify_route 
    = warp::path("verify")
    .and(warp::post())
    .and(warp::body::bytes())
    .and(warp_sessions::request::with_session(session_store, None))
    .and_then( verify_handler)
    .untuple_one()
    .and_then(warp_sessions::reply::with_session)
    .recover(handle_rejection)
    .with(&cors); 

Solution

  • It looks like you're setting the CookieOptions in the route definition to None, meaning that the warp_sessions code will expect a cookie named sid to get the session ID. Link to code showing this behavior:

    https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/request.rs#L17

    However, in the route handler, you override the cookie_options to a different value, with a cookie name of siwe_minimal. This means that, during the reply portion of the warp_sessions logic, the cookie containing the session ID that will persist your session across calls will be named something different than what the route definition expects.

    Link to where Set-Cookie header is defined in the warp_sessions reply code: https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/session.rs#L98

    Link to to_string definition of CookieOptions which shows how cookie_name is used: https://github.com/ajpauwels/warp-sessions/blob/c440817f41c331cfa21a0c3a995be20ab420bb5e/src/cookie.rs#L24

    In order to solve this, I would suggest either:

    1. Instead of setting CookieOptions to None in your route definition, set your options there

    2. Keeping None in the route definition, and removing the options override in the route handler entirely