SitePoint Sponsor

User Tag List

Results 1 to 13 of 13

Hybrid View

  1. #1
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    >>> Page 96, Re: socket.io handshake fails

    Hi, Don. I can't get your socket.io handshake code to work. It keeps coming back with "info: handshake unauthorized". The MemoryStore contains an _id but not of the form we're trying to retrieve it. It looks like this:

    {"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"_id":"51107c6634378ae60a000001"}

    And we're trying to retrieve it with a sessionID that looks something like this "s:muBl0aDwYkvHR60dC4NdSn7+.Od8cUUasUucjWOEn3OKs6zp2dFq82oUC9Mduild9iG0".

    (See also http://cl.ly/image/190r1B3f3e2m)

    I'm stuck. Been playing around with this authorization handshake code for a while now. Can't figure out why it's not working. Also, where is MemoryStore's API documented? Googled it but got nothing useful.

    Please advise.

    My dependency versions:

    express: 3.0.6
    cookie: 0.0.5
    socket.io: 0.9.13

  2. #2
    SitePoint Author
    Join Date
    Nov 2012
    Posts
    48
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Are you accessing using http://localhost (as opposed to http://192.168.1.6 etc)?

  3. #3
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Don Nguyen View Post
    Are you accessing using http://localhost (as opposed to http://192.168.1.6 etc)?
    I'm accessing using http://localhost in chapter05/public/js/chat.js - as instructed on page 98. (Incidentally, our server is listening on port 3000. So, shouldn't this be http://localhost:3000? Tried with and without specifying the port, no difference to the outcome of the handshake - still "handshake unauthorized".)

    Please send url to the MemoryStore's API documentation that you read to learn about this feature of Express/Connect. Googled it but got nothing useful.

  4. #4
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's what I'm seeing:

    cookie["connect.sid"] = "s:95wlB0OWL+9baRJ1R4v3JMGK.ZVE6TBraqEFyl54qURXZsro1VULjyLs7xRVQNKedFck"
    sessionStore.sessions["95wlB0OWL+9baRJ1R4v3JMGK"] = {"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"_id":"51107c6634378ae60a000001"}

    It looks like what we're saving ("_id") in req.session at login is getting saved in sessionStore. That's good. But I see only one session in sessionStore and its key/id is "95wlB0OWL+9baRJ1R4v3JMGK", not "s:95wlB0OWL+9baRJ1R4v3JMGK.ZVE6TBraqEFyl54qURXZsro1VULjyLs7xRVQNKedFck", i.e. not connect.sid.

    But in the socket.io handshake code we're basically doing this:

    sessionStore.get("s:95wlB0OWL+9baRJ1R4v3JMGK.ZVE6TBraqEFyl54qURXZsro1VULjyLs7xRVQNKedFck", function (err, session) { ... });

    and what gets returned is an undefined session. I'm guessing because there is no session associated with "s:95wlB0OWL+9baRJ1R4v3JMGK.ZVE6TBraqEFyl54qURXZsro1VULjyLs7xRVQNKedFck" in sessionStore.

    Were we expecting express to store our session in sessionStore (MemoryStore) because we did this:

    app.use(express.session({
    secret: 'my_secret',
    store: nocklib.getSessionStore()
    }));

    It appears it did do that but it didn't use connect.sid as the session key/id. How do we retrieve our session from sessionStore if we don't know the key/id with which to retrieve it?

    I'm not sure how to proceed from here. Please advise.

  5. #5
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

  6. #6
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Don, I think I figured out what's going on ...


    These are the relevant values:

    req.session.id = seE9jI0dklxSgHXvyx7N4RER
    connect.sid = s:seE9jI0dklxSgHXvyx7N4RER.uHPngsFJ1azy3Nf7odcYfWw50progovXugadoSvExxQ


    Express stores our session in MemoryStore using req.session.id as the session key, like so:

    memoryStore.sessions["seE9jI0dklxSgHXvyx7N4RER"] = "{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"username":"Randie"}


    But later (during socket.io authorization handshake), we try to retrieve our session from MemoryStore using connect.sid as the session key, like so:

    memoryStore.get("s:seE9jI0dklxSgHXvyx7N4RER.uHPngsFJ1azy3Nf7odcYfWw50progovXugadoSvExxQ", function(err, session) {...});


    Since there is no session associated with "s%3AseE9jI0dklxSgHXvyx7N4RER.uHPngsFJ1azy3Nf7odcYfWw50progovXugadoSvExxQ" in MemoryStore, we get back undefined for session in our callback function, which ultimately results in "info: handshake unauthorized". See http://cl.ly/image/0c3P2T0S070N .

    This is a little tricky to fix because in the authorization handshake code, we don't have access to the request object, req. Specifically, we don't have access to req.session.id. But notice (in bold above) how req.session.id is embedded within connect.sid. How do we extract the req.session.id portion from connect.sid?

    Please advise.

  7. #7
    SitePoint Author
    Join Date
    Nov 2012
    Posts
    48
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    The hacky way is to use string split to transform connect.sid so that it is the same as connect.sid. The documentation you are looking for is here

    http://www.senchalabs.org/connect/session.html

    And the correct way is to store the req.session.id for later retrieval

    See

    https://github.com/spbooks/NODEJS1/b...lib/nocklib.js

    Code:
    handshakeData.sessionID = handshakeData.cookie['connect.sid'];
              sessionStore.get(handshakeData.sessionID, function (err, session) {
                if (err || !session) {
                  return callback(null, false);
                } else {
                  handshakeData.session = session;
                  console.log('session data', session);
                  return callback(null, true);
                }

  8. #8
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Don, you just gave me the exact same code that I explained in great detail above DOES NOT work and why. See http://cl.ly/image/034730033e3O .

    Again, this code:

    sessionStore.get(handshakeData.sessionID, function(err, session) {...});

    returns an undefined session in the callback function. Why? Because you're trying to retrieve the session from sessionStore using connect.sid but the session was stored using req.sessionID (aka req.session.id) and connect.sid != req.sessionID.

  9. #9
    SitePoint Author
    Join Date
    Nov 2012
    Posts
    48
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    I can't reproduce the error on my end they are exactly the same

    cookie: { 'connect.sid': 'R0B0jn40EUIkSL2MEu4P9CdP.fNYBLE+iFDrYZ34u+4ZzcDkauho8lDyqnY9rE1ykN3o'
    sessions: { 'R0B0jn40EUIkSL2MEu4P9CdP.fNYBLE+iFDrYZ34u+4ZzcDkauho8lDyqnY9rE1ykN3o'

    For now I would just use string manipulation to match them up and then on the second pass through I think time is best spent implementing using RedisStore rather than worrying too much about MemoryStore which is mainly appropriate for examples and prototypes

  10. #10
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's the solution: http://howtonode.org/socket-io-auth

    Basically, instead of this:

    handshakeData.sessionID = handshakeData.cookie['connect.sid'];

    it says to do this:

    handshakeData.sessionID = connect.utils.parseSignedCookie(handshakeData.cookie['connect.sid'], 'secret');

    which tries to unsign the session id cookie value using the same secret key used for signing it in the first place. If the cookie was indeed signed by our server then the reverse operation should give us the real session id.

  11. #11
    SitePoint Member randie's Avatar
    Join Date
    Oct 2008
    Posts
    17
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Here's the code that finally worked for me: http://cl.ly/image/2m0P463F1928

    With the following dependencies:

    express: 3.0.6
    connect: 2.7.2
    cookie: 0.0.5
    socket.io: 0.9.13

  12. #12
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    A note of summertime thanks for your wintertime solution

    Here in August let me say thanks very much for this in-depth work back in February.

    I was wondering why my console.log wasn't yielding up an "_id".

    Now having got in the 'connect' line that you document in your posted screengrab, it's working correctly, and the chat does get the username (for me, wasn't, before) ("Admin: user1 has joined").


    randie's code with line that fixed things:
    http://cl.ly/image/2m0P463F1928

    Code:
    handshakeData.sessionID = connect.utils.parseSignedCookie(handshakeData.cookie['connect.sid'], 'secret');
    - If you can't recall where 'secret' comes from (like me), it's here:
    Code:
    // Where is SECRET? nockmarket.js:
         // app.use(express.session({secret: 'secretpasswordforsessions', store: nocklib.getSessionStore()}));
    - Be sure to npm install the connect (I followed his version number connect: 2.7.2)
    - And of course the line in nocklib.js:
    var connect = require("connect");

    My package.json
    Code:
    {
        "name": "nockmarket"
      , "version": "0.0.1"
      , "private": true
      , "dependencies": {
        "clone" : "0.1.1"
        , "cookie": "0.0.4"
        , "mocha": "1.3.0"
        , "jquery": "1.7.3"
        , "should": "1.0.0"
        , "socket.io": "0.9.14"
        , "ejs" : "0.7.1"
        , "express" : "2.5.8"
    	, "connect" : "2.7.2"
        , "mongodb" : "1.0.2"
      }
    }
    Best,
    William R.

  13. #13
    SitePoint Member
    Join Date
    Jul 2013
    Posts
    6
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Question for randie: what IDE are you using?
    (As seen in your posted screenshot: http://cl.ly/image/190r1B3f3e2m)
    I've been considering Webstorm for use on my Mac; would be interested to learn what you're using there.
    Appreciated.
    William R.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •