Brian
Brian

Reputation: 427

Twisted Session Cookie is Changing for Each Request

For some reason after logging in, every POST request afterwards the Twisted session cookie changes. Why does this happen? I would expect the session uid to be the same until the connection is lost, or the user logs out.

Here is my code that causes the session to be different for each request:

from twisted.web.server import Site, http
from twisted.internet import reactor
from twisted.web.resource import Resource

import json

class HttpResource(Resource):
    isLeaf = True

    def render_OPTIONS(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')
        return ""

    def render_GET(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')
        return "<html><body style='margin: 0; overflow: hidden;'><iframe style='width: 100%; height: 100%; border: none;' src='http://tsa-graphiql.herokuapp.com/'></iframe></body></html>"

    def render_POST(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')

        session_id = request.getSession().uid
        print "HttpResource session ID: {}".format(session_id)


class LoginResource(Resource):
    isLeaf = True

    def render_OPTIONS(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')
        return ""

    def render_GET(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')
        return "<html><body style='margin: 0; overflow: hidden;'><iframe style='width: 100%; height: 100%; border: none;' src='http://tsa-graphiql.herokuapp.com/'></iframe></body></html>"

    def render_POST(self, request):
        log("Login request")
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')

        req = request.content.read()

        session_id = request.getSession().uid

        try:
            jsQ = json.loads(req)
        except Exception as e:
            return e

        # User credentials
        username = jsQ['username']
        password = jsQ['password']

        # Authenticate the User
        if username == 'test' and password == 'test':
            # Create a new session
            print "Login session ID: {}".format(session_id)
        else:
            request.setResponseCode(401)
            return "Invalid username or password"


class RefreshResource(Resource):
    isLeaf = True

    def render_OPTIONS(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')
        return ""

    def render_GET(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')
        return "<html><body style='margin: 0; overflow: hidden;'><iframe style='width: 100%; height: 100%; border: none;' src='http://tsa-graphiql.herokuapp.com/'></iframe></body></html>"

    def render_POST(self, request):
        request.setHeader('Access-Control-Allow-Origin', '*')
        request.setHeader('Access-Control-Allow-Headers', 'Origin, Accept, content-type, authorization')
        print "Refresh session ID: {}".format(request.getSession().uid)


class HttpFactory(Site):

    def __init__(self, resource):
        http.HTTPFactory.__init__(self)
        self.resource = resource
        self.sessions = {}
        self.user_info = {}


if __name__ == '__main__':

    root = Resource()
    root.putChild("", HttpResource())
    root.putChild("login", LoginResource())
    root.putChild("refresh", RefreshResource())

    site = HttpFactory(root)
    reactor.listenTCP(8000, site)

    reactor.run()

Upvotes: 0

Views: 851

Answers (1)

Jean-Paul Calderone
Jean-Paul Calderone

Reputation: 48335

Twisted Web sessions are cookie based. For the session to remain active with a client, they must respect the server's Set-Cookie response (save the cookie and re-send it with future requests).

If your client is something like curl, then:

$ curl http://localhost:8000/

will drop the session cookie after running. If you run that command again, you'll get a new session because the client won't send the session cookie and the server has no way to know the request belongs to the previously-created session.

If you tell curl to handle cookies normally with a command like:

$ curl --cookie session-cookies --cookie-jar session-cookies http://localhost:8000/

Then curl will save the session cookie the server sets. If you run the command again, it will send the session cookie back to the server and you'll see the same session re-used.

Upvotes: 1

Related Questions