简体   繁体   中英

share user sessions between Node.js and Clojure

I am using Clojure / Friend , and I would like to hijack a session from a neighbouring node.js server :)

What I mean is that there is a node.js + Express 3 server that stores sessions into a redis database, using connect-redis . I have access to the node.js source code, and therefore to the secret passed to the express session used to generate the sid. I modified the connection section to look like this (the built-in in-memory store was used previously) :

  var session    = require('express-session')
  , RedisStore   = require('connect-redis')(session)
  , redis        = require('redis')
  , client       = redis.createClient();

    ...

app.use(session({
    secret: "super-secret-key",
    store: new RedisStore({client : client,
                           ttl    : 60*60*24,
                           prefix : 'sess:'})
}));

I can see the sessions stored in Redis :

// using redis-cli KEYS * 1) "sess:yNV3MQOOTZSEgzl0RH2lyWVW"

The login page is situated on the node.js side of the app. But the routes of the API are shared (via nginx) between Node.js and Clojure, so I receive the cookies in the incoming requests in my Compojure / Friend app.

I am struggling to get the Friend custom-credential function right :

(defn custom-credential [{:keys [username password] :as trial}]

  (let [cookie             (...)
        redis-session      (...)
        is-signature-valid (...)]
   ;; I can get all the above bindings just fine 
   ;; ie. I extract the cookie from the request
   ;; I read the cookie ID and fetch the cookie content from Redis
   ;; I extract the signature of the cookie and check it (I replicated [node-cookie-signature][8])

   (when is-signature-valid
      {:identity "cookie-id"})))


(defn secured-routes [unsecured-routes]
  (friend/authenticate
   unsecured-routes
   {:allow-anon? true
    :credential-fn custom-credential
    :workflows [(workflows/http-basic)]}))

I have several problems :

  • I am redirected to the login page even when my authentication function returns an {:identity ..} map

  • But I cannot figure out how to plug it into Friend so that the cookies work as well. Using the default memory-store then the cookie is replaced by a default ring-cookie (obviously not what I want). I tried writing a custom cookie-store using Redis as a backend, but I need to write JSON to keep the node compatibility, and I loose the ::user information.

Note : I am quite flexible at this point so if I should use something else than Friend or Compojure I would also accept that.

Sorry for the long post, I really hope someone can help.

How do I get the cookie contents on my validating function ?

The ring request will contain any cookies that the client sent, however it may not send those cookies if your Clojure server is on a different domain.

how do I validate the user from the content of the cookie ? Ie. how can I make sure the cookie has not been altered (ie. replicate what the connect-redis is doing with the secret) ?

Best practice is for the cookie to be a random number, and to store session details in redis. If that's how your Node server works then you can just lookup the details in Redis. Alternatively if the client provided an encrypted session cookie, then you will need to decrypt it in the same manner as Node does.

Alternatively, you might want to look at JWT auth tokens, which are designed to be shared and authenticated by many different servers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM