I am struggling to retrieve session data on routes after initially writing to the Redis database.
When I insert into the session, i can imeediatley after view those statements with session.entries() or session.get::<>(). When I trythis from another route, session is always empty.
I assume this means sessions are not persisting between routes. I do not fully understand how sessions are sorted on the browser, other than that it is stored securely, and automatically sent with HTTP requests? This has made it hard to tell if the issue is with how the session data is being sent to the browser, or how the session is being retrieved from the browser.
Below is some snippets of my code.
#[post("/login")]
async fn login(session: Session, user_info: web::Json<LoginDetails>) -> impl Responder {
...
password auth
...
session.insert("user_id".to_string(), user_id);
session.insert("status_level".to_string(), status_level);
session.insert("login_status".to_string(), true);
let user_session = UserSession {
session_string: session_string.to_string(),
session_details
};
dbg!(session.entries()); // This shows the entries :)
dbg!(session.get::<u8>("user_id"));
return HttpResponse::Ok().status(StatusCode::from_u16(200).unwrap()).json(user_session);
},
...
pub fn validate_session(session: &Session) -> Result<u8, HttpResponse> {
let user_id: Option<u8> = session.get("user_id").unwrap_or_else(|err| { println!("Error getting user_id from session: {}", err); None });
dbg!(session.entries()); //This will be empty :(
dbg!(&user_id);
match user_id {
Some(id) => {
// keep the user's session alive
session.renew();
Ok(id)
}
None => Err(HttpResponse::Unauthorized().json("Unauthorized")),
}
}
#[get("/campaign_names")]
async fn campaign_names(session: Session, req: HttpRequest) -> impl Responder {
let id = validate_session(&session).unwrap_or(0);
println!("id {}",id); // prints 0
...
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let secret_key = Key::generate();
HttpServer::new(move || {
let cors = Cors::permissive();
App::new()
.wrap(cors)
.wrap(
SessionMiddleware::builder(
RedisActorSessionStore::new("127.0.0.1:6379"),
secret_key.clone(),
)
// allow the cookie to be accessed from javascript
.cookie_http_only(false)
// allow the cookie only from the current domain
.cookie_same_site(SameSite::Strict)
.build(),
)
.service(campaign_names)
I must be missing something obvious?
Here is the example I modled off of: https://github.com/actix/actix-extras/blob/master/actix-session/examples/authentication.rs
I have tried using non-actor session. I have also verified in Redis the data is being set.
It feels like I should be sending a session id to the browser and having it returned and then checking against that, but that seems to be handled by the session middleware.
All I needed to do was send a request from my frontend with {withCredentials: true}
Then I was able to set the session ID in the browser, as well as send it to the backend for the middleware to handle the session.