Giter Club home page Giter Club logo

async-session's People

Contributors

chrislearn avatar dependabot[bot] avatar flakm avatar goto-bus-stop avatar jalcine avatar jbr avatar johntitor avatar joshtriplett avatar maxcountryman avatar oconnor663 avatar yoshuawuyts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

async-session's Issues

MemoryStore not valid for production usage

Welcome!

I've recently gotten an opportunity to do first pet project in rust and decided on using axum which gives an example of using async-session:

    // `MemoryStore` is just used as an example. Don't use this in production.
    let store = MemoryStore::new();

https://github.com/tokio-rs/axum/blob/main/examples/oauth/src/main.rs#L42

The same warning is memory store itself

/// # ***DO NOT USE THIS IN A PRODUCTION DEPLOYMENT.***

Is there a reason why this should not be used in production if losing all sessions on application crash acceptable behavior and application is not clustered? If there is I would love to add it in documentation in pointed places for others to understand.

Also many kudos for your work! ๐Ÿฅ‡

Update blake3 to at least v1.2.0

There's a security issue on x86 introduced in 0.3.7 and fixed in 1.2.0 with SSE2 optimisations. Aarch64 would also benefit with NEON being supported by blake3.

Cannot modify session expiry

It seems when using the Session with tide's session middleware, it's not possible to modify the session expiry because it is not wrapped in an Arc (I think).

This can be a somewhat tricky thing to reason with because of the session lifecycle in a request (and how it is cloned), but testing reveals that there are two things that would prevent this:

  1. the expiry not being wrapped in Arc so the cloned session (via tide session middleware's handler) does not update the session expiry
  2. Session::expire_in does not mark the session data_changed, so unless the check is disabled in the middleware, changes to session expiry will not cause the session to be updated by the store even it 1 is fixed

These are relatively straightforwards things to resolve, but may have some more subtle implications since it will change how sessions behave and existing code may be out there which depends on these quirks.

How do you setup async-redis-session as a layer

Hi, how do you setup async-session-redis as layer in Axum so that connection can be used in handlers?

At the moment I have session_layer but when I insert a record in Redis in one handler, I'm unable to retrieve it in another handler from the session.

Specifically how do you add the Redis store as a layer in Axum?

Framework is Axum. Thanks for any pointers or example.

Session API requirements for Privilege-Level Changes, based on OWASP recommendations

A few features are missing from the Session api:

  1. session key renewal
  2. session purge

1. Session key renewal
Two of the most common events in a web application where there are "privilege-level changes" are login and logout, but there are others. Each of these events requires the Session ID be renewed. With this given, the Session API requires renewal functionality so that one may renew the session key on-demand. Although the Session ID changes, state is preserved.

2. Session purge
Purging involves removing the session state AND the cookie (ie "purge"). Purging is done during the logout process, for instance.

If you'd like to see an example implementation, such functionality exists in actix-web and an example useful for integration testing can be found here.

What's the `cookie_value` in `Session` using for ?

Why the cookie_value is not cloned or serialized, I can't get the point of doing this. Can someone explain why we should have this field, and make it not cloned or serialized. Thanks a lot. ๐Ÿ˜‚

Use v3 with Tide?

It seems that the removal of async-std in v3 has broken the use of async-session with tide. If you try a simple tide program like the one in the async-mongodb-session/examples but with async-sqlx-session v0.4.0 you get build errors like

the trait `SessionStore` is not implemented for `SqliteSessionStore`

Moving async-sqlx-session back to async-session v2.0.1 from v3.0.0 makes the build error go away. I think this is a bug in async-session not async-sqlx-session because moving async-mongodb-session to async-session v3.0.0 from v2.0.1 results in the same build errors but for MongodbSessionStore, and I just don't see anything else in the latest async-sqlx-session that seems like it could be the cause.

Thoughts? Anything more I can do to help troubleshoot?

Status of this crate?

Hi folks, it looks like the last published release was in May of 2021.

I'm curious if the maintainers could let us know if we should expect future releases or if projects utilizing this crate should instead publish their own releases?

Creating a custom `SessionStore`.

Hey,

I'm trying to write a custom MemoryStore that works with a sqlx postgres database to store sessions for axum-login.
I've got the following SQL, which has space for all the non-serde-skipped parts of Session:

CREATE TABLE auth_sessions (
    id TEXT PRIMARY KEY NOT NULL,
    expiry TIMESTAMP
);

CREATE TABLE auth_session_data (
    k TEXT NOT NULL,
    v TEXT NOT NULL,

    session_id TEXT NOT NULL,
    CONSTRAINT fk_session_id
        FOREIGN KEY (session_id)
        REFERENCES auth_sessions(id)
        ON DELETE CASCADE
)

Unfortunately, I can't work out a way to get the session contents to/from SQL, as I can't seem to find a constructor for making a Session, or getting all of the data - I can get values from keys but if I don't know what keys are being used (and would rather not have to hardcode a list from axum-login), and I can make a new cookie and add data but I can't do things like set the ID.

PostgresStore

Hi I am writing a PostgresStore for this, I wonder if I just dump the whole session into Postgres or there are more preferable approach?

Something like this:

serde_json::to_string(&session).ok()

New release timing?

Are there any plans to release a new version? Lot's of dependencies moved and some crates that use async-session need to make the upgrade and it would be much cleaner this way.

Session backends are not interchangeable

I've tried using MemoryStore, but when I try to load the session and then alter it and finally save it the result of the store_session call is None, even though the session is not empty.

The way I handle it is as follows:

        let jar = match session_cookie {
            Some(session_cookie) => jar.add(Cookie::build(SESSION_COOKIE_NAME, session_cookie).finish()),
            None => jar.remove(Cookie::named(SESSION_COOKIE_NAME)),
        };

Apparently, this crate expects me to do this instead:

        let jar = match session_cookie {
            Some(session_cookie) => jar.add(Cookie::build(SESSION_COOKIE_NAME, session_cookie).finish()),
            None => { /* do nothing */ },
        };

The problem with this API is that the library does not provide itself control over how the cookie actually has to be set. Meaning, the library must be aware that some cookie (either the whole set of values, encoded somehow, or a key into the database with the sessions) must be set, and at some point, that cookie has to be updated (almost never when the id is stored, and a lot when the session value is stored) or removed (in both cases, when the session is destroyed). The library can thus expect to return the effective cookie value for the server to set on the client; the server handling the cookie can then check if the cookie has to be set.

I propose that we change the API as follows:

async fn store_session(...) -> Result<CookieAction>;
enum CookieAction {
  /// Set the cookie with this new value.
  Set(String),
  /// Remove the cookie.
  Remove,
  /// No action is required (the cookie value should not change).
  NoAction,
}

Or at least remap the semantics of what None encodes currently to make it so it means "remove the cookie value on the client side".


Without this change, it seems I wouldn't be able to swap between the Memory and Cookie stores - as I'd have to knowledgeably choose whether to set the cookie or not depending on the backend I use. I know I'd have to set the cookie every time the session values change when using the CookieStore backend.

Replace chrono

Unfortunately chrono is still unpatched for a security advisory: chronotope/chrono#499 so it would be good to replace it, as this starts triggering folks from removing tide.

CookieStore doc says data is signed but it doesn't seem to be

This was already mentioned in #40 but I think it still applies. From looking at the code, it seems that the cookie is just the serialized Session instance and as such could easily be modified. Any signing has to be done externally, by middleware.

This means that the middleware has to be aware of the SessionStore implementation and whether the data needs to be protected or not. In the case of axum-sessions they always HMAC the cookie value, which is unnecessary given that the cookie value is just random data for most store implementations.

The docs should probably make it clear that there is no signing of the value in this crate. It would be possible for CookieStore to handle signing (and possibly encryption) of the cookie value though, which would (optionally) remove the responsibility from the various middleware implementations. I could try and put together a PR if this makes sense?

Remove Clone trait requirement from SessionStore

I am writing some web server using axum library where I use multiple traits and put them in request extensions by converting them to Arc so that I don't have to make every handler accept generic parameters. Unfortunately I can't do that for SessionStore (which I use in a middleware for checking authentication) since it requires implementor to also implement Clone, making it non object safe. Is there a possibility to remove Clone requirement in next major version?

Example with handlers accepting generic parameters:

fn configure<U, T, S>(user_service: U, transaction_service: T, session_store: S) -> Router
  where 
         U: UserService,
         T: TransactionService ,
         S: SessionStore
{
  Router::new()
          .route("/", handlers::index::<U>)
          .route("/user", handlers::user::overview::<U, T, S>)
          .layer(Extension(user_service))
          .layer(Extension(transaction_service))
          .layer(Extension(session_store))
}

// in handlers/index.rs
async fn index<U: UserService>(Extension(service): Extension<U>) -> impl IntoResponse {
//some stuff
}

// in handlers/user.rs
async fn overview<U: UserService, T: TransactionService, S: SessionStore>(
       Extension(user_service): Extension<U>,
       Extension(transaction_service): Extension<T>,
       Extension(session_store): Extension<S>,
) -> impl IntoResponse {
//some stuff
}

And new way which I would be able to do if SessionStore is object safe:

fn configure<U, T, S>(user_service: U, transaction_service: T, session_store: S) -> Router
  where 
         U: UserService,
         T: TransactionService ,
         S: SessionStore
{
  Router::new()
          .route("/", handlers::index)
          .route("/user", handlers::user::overview)
          .layer(Extension(Arc::new(user_service) as Arc<dyn UserService>))
          .layer(Extension(Arc::new(transaction_service) as Arc<dyn TransactionService>))
           .layer(Extension(Arc::new(session_store) as Arc<dyn SessionStore>)) // Not object safe, this will fail
}

// in handlers/index.rs
async fn index(Extension(service): Extension<Arc<dyn UserService>>) -> impl IntoResponse {
//some stuff
}

// in handlers/user.rs
async fn overview(
       Extension(user_service): Extension<Arc<dyn UserService>>,
       Extension(transaction_service): Extension<Arc<dyn TransactionService>>,
       Extension(session_store): Extension<Arc<dyn SessionStore>>,
) -> impl IntoResponse {
//some stuff
}

This will make function signature smaller when I start adding more traits.

Unused dependencies?

The sha2 and hmac dependencies look unused to me. Is there a reason for these dependencies?

async-session throwing method not found errors

I am using ONLY async-sessions in Axum with the exact example from the docs as follows which throws the errors listed below:

Is there ANY chance you could get the example in your docs working without all the errors below.

use async_session::{Session, SessionStore, MemoryStore};

let mut store = MemoryStore::new();
    // Create a new session.
    let mut session = Session::new();
    session.insert("user_id", 1)?;
    assert!(session.data_changed());
    // retrieve the cookie value to store in a session cookie
    let cookie_value = store.store_session(session).await.unwrap()?;
    // Retrieve the session using the cookie.
    let session = store.load_session(cookie_value).await.unwrap()?;
    assert_eq!(session.get::<usize>("user_id").unwrap(), 1);
    assert!(!session.data_changed());
error[E0599]: no method named `store_session` found for enum `Result` in the current scope
  --> src/main.rs:91:30
   |
91 |     let cookie_value = store.store_session(session).await;
   |                              ^^^^^^^^^^^^^ method not found in `Result<RedisSessionStore, redis::types::RedisError>`

error[E0599]: no method named `load_session` found for enum `Result` in the current scope
  --> src/main.rs:92:29
   |
92 |     let mut session = store.load_session("test-cookie".parse().unwrap()).await.unwrap();
   |                             ^^^^^^^^^^^^ method not found in `Result<RedisSessionStore, redis::types::RedisError>`

error[E0308]: mismatched types
   --> src/main.rs:111:38
    |
111 |     let session = store.load_session(cookie_value).await.unwrap();
    |                                      ^^^^^^^^^^^^ expected struct `std::string::String`, found enum `std::option::Option`
    |
    = note: expected struct `std::string::String`
                 found enum `std::option::Option<std::string::String>`

error[E0599]: no method named `get` found for enum `std::option::Option` in the current scope
   --> src/main.rs:112:24
    |
112 |     assert_eq!(session.get::<usize>("user_id").unwrap(), 1);
    |                        ^^^ method not found in `std::option::Option<Session>`

error[E0599]: no method named `data_changed` found for enum `std::option::Option` in the current scope
   --> src/main.rs:113:22
    |
113 |     assert!(!session.data_changed());
    |                      ^^^^^^^^^^^^ method not found in `std::option::Option<Session>`

error[E0283]: type annotations needed
   --> src/main.rs:106:13
    |
106 |     session.insert("user_id", 1);
    |             ^^^^^^ cannot infer type for type `{integer}`

What does calling destroy on Session do?

Reading the code i couldn't figure out what calling Session::destroy really does. The documentation currently reads:

mark this session for destruction. the actual session record is not destroyed until the end of this response cycle.

From my quick reading of the code I didn't find find any location in the code where the destroy flag is read and the Session is actually destroyed.

Question regarding Arc for Session

I wonder why wouldn't Session wrap around Arc, but part of its is Arc, such as data.

In some cases I need to pass session around and mut it.

Maybe there is a way that I haven't thought though, thanks.

Generic `Session`

A Session has a data field of type HashMap<String, String>. This forces a session to always use JSON for serialization/deserialization.

In my case I would prefer if it was a HashMap<String, Bytes> so that I can use more efficient serde methods (e.g.: bincode, which this crate already uses)

Would it be possible to change Session so that it becomes generic like Session<T> so that data becomes HashMap<String, T>?

Unable to access Tide's Jar to attach session information?

I've been diving into session management in Tide. It seems like it is still a WIP but it sounded like this library is the direction things are moving towards.

I am noticing that Tide's cookie middleware hides the CookieJar from the consumer, so it can't be used with these traits. I'm not sure whether Tide should allow access to the CookieJar or if this should be changed to take a Request/Response pair instead of a CookieJar.

Any thoughts?

Cookie store secure ?

Hello,

In documentation it is written that the data in the cookie is only signed, but not encrypted. I understand that it is signed because the cookie id is an hash of the cookie data, and attempting to alter only the data will fail...
But since there is no (external) signing key, what would prevent someone to forge a cookie with any data for a website ?
If I understand correctly (and maybe I don't), that would be a severe security issue ?!
Would it be possible to pass a server known only key to the CookieStore::new(a_secret_key) to sign all the cookies (and deactivate them all if the key is changed) ?

Thanks,

Store session creation date in session backends

I was debugging mongo and couldn't find the creation date in the session store. We should probably track this for all sessions; even if not tracked by UTC it does help with debugging. Perhaps the individual backends provide primitives for this as well that we can use.

Screenshot

I was trying to find from this screenshot which sessions were created today. It doesn't say, heh.

Screenshot 2020-07-28 13 59 21

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.