Esempio n. 1
0
    def __init__(self,
                 secret,
                 max_age,
                 reissue_time=None,
                 include_ip=False,
                 cookie_name='AUTH_TKT'):
        """Initializes the ticket authentication mechanism.

        Args:
            secret: Byte sequence used to initialize the ticket factory.
            max_age: Integer representing the number of seconds to allow the
                ticket to remain valid for after being issued.
            reissue_time: Integer representing the number of seconds before
                a valid login will cause a ticket to be reissued. If this
                value is 0, a new ticket will be reissued on every request
                which requires authentication. If this value is None, no
                tickets will be reissued, and the max_age will always expire
                the ticket.
            include_ip: If true, requires the clients ip details when
                calculating the ticket hash
            cookie_name: Name to use to reference the ticket details.
        """
        self._ticket = TicketFactory(secret)
        self._max_age = max_age
        if (self._max_age is not None and reissue_time is not None
                and reissue_time < self._max_age):
            self._reissue_time = max_age - reissue_time
        else:
            self._reissue_time = None

        self._include_ip = include_ip
        self._cookie_name = cookie_name
Esempio n. 2
0
def make_auth_session(secret, user_id, cookie_name):
    from ticket_auth import TicketFactory
    import time
    json = {}
    tf = TicketFactory(secret)
    ticket = tf.new(user_id)
    json['created'] = int(time.time())
    json['session'] = { cookie_name: ticket }
    return json
Esempio n. 3
0
    def __init__(
            self,
            secret,
            max_age,
            reissue_time=None,
            include_ip=False,
            cookie_name='AUTH_TKT'):
        """Initializes the ticket authentication mechanism.

        Args:
            secret: Byte sequence used to initialize the ticket factory.
            max_age: Integer representing the number of seconds to allow the
                ticket to remain valid for after being issued.
            reissue_time: Integer representing the number of seconds before
                a valid login will cause a ticket to be reissued. If this
                value is 0, a new ticket will be reissued on every request
                which requires authentication. If this value is None, no
                tickets will be reissued, and the max_age will always expire
                the ticket.
            include_ip: If true, requires the clients ip details when
                calculating the ticket hash
            cookie_name: Name to use to reference the ticket details.
        """
        self._ticket = TicketFactory(secret)
        self._max_age = max_age
        if (self._max_age is not None and
            reissue_time is not None and
            reissue_time < self._max_age):
            self._reissue_time = max_age - reissue_time
        else:
            self._reissue_time = None

        self._include_ip = include_ip
        self._cookie_name = cookie_name
Esempio n. 4
0
    async def test_middleware_gets_auth_from_cookie(self):
        secret = b'01234567890abcdef'
        auth_ = auth.CookieTktAuthentication(secret, 15, 2, cookie_name='auth')
        middlewares = [auth_middleware(auth_)]

        session_data = TicketFactory(secret).new('some_user')
        request = await make_request('GET', '/', middlewares, \
            [(auth_.cookie_name, session_data)])

        user_id = await auth.get_auth(request)
        self.assertEqual(user_id, 'some_user')

        response = await make_response(request, middlewares)
        self.assertFalse(auth_.cookie_name in response.cookies)
Esempio n. 5
0
    async def test_middleware_reissues_ticket_auth(self):
        secret = b'01234567890abcdef'
        auth_ = auth.CookieTktAuthentication(secret, 15, 0, cookie_name='auth')
        middlewares = [auth_middleware(auth_)]

        valid_until = time.time() + 15
        session_data = TicketFactory(secret).new('some_user',
                                                 valid_until=valid_until)
        request = await make_request('GET', '/', middlewares, \
            [(auth_.cookie_name, session_data)])

        user_id = await auth.get_auth(request)
        self.assertEqual(user_id, 'some_user')

        response = await make_response(request, middlewares)
        self.assertTrue(auth_.cookie_name in response.cookies)
        self.assertNotEqual(response.cookies[auth_.cookie_name], session_data)
Esempio n. 6
0
class TktAuthentication(AbstractAuthentication):
    """Ticket authentication mechanism based on the ticket_auth library.

    This class is an abstract class that creates a ticket and validates it.
    Storage of the ticket data itself is abstracted to allow different
    implementations to store the cookie differently (encrypted, server side
    etc).
    """

    def __init__(
            self,
            secret,
            max_age,
            reissue_time=None,
            include_ip=False,
            cookie_name='AUTH_TKT'):
        """Initializes the ticket authentication mechanism.

        Args:
            secret: Byte sequence used to initialize the ticket factory.
            max_age: Integer representing the number of seconds to allow the
                ticket to remain valid for after being issued.
            reissue_time: Integer representing the number of seconds before
                a valid login will cause a ticket to be reissued. If this
                value is 0, a new ticket will be reissued on every request
                which requires authentication. If this value is None, no
                tickets will be reissued, and the max_age will always expire
                the ticket.
            include_ip: If true, requires the clients ip details when
                calculating the ticket hash
            cookie_name: Name to use to reference the ticket details.
        """
        self._ticket = TicketFactory(secret)
        self._max_age = max_age
        if (self._max_age is not None and
            reissue_time is not None and
            reissue_time < self._max_age):
            self._reissue_time = max_age - reissue_time
        else:
            self._reissue_time = None

        self._include_ip = include_ip
        self._cookie_name = cookie_name

    @property
    def cookie_name(self):
        """Returns the name of the cookie stored in the session"""
        return self._cookie_name

    async def remember(self, request, user_id):
        """Called to store the userid for a request.

        This function creates a ticket from the request and user_id, and calls
        the abstract function remember_ticket() to store the ticket.

        Args:
            request: aiohttp Request object.
            user_id: String representing the user_id to remember
        """
        ticket = self._new_ticket(request, user_id)
        await self.remember_ticket(request, ticket)

    async def forget(self, request):
        """Called to forget the userid for a request

        This function calls the forget_ticket() function to forget the ticket
        associated with this request.

        Args:
            request: aiohttp Request object
        """
        await self.forget_ticket(request)

    async def get(self, request):
        """Gets the user_id for the request.

        Gets the ticket for the request using the get_ticket() function, and
        authenticates the ticket.

        Args:
            request: aiohttp Request object.

        Returns:
            The userid for the request, or None if the ticket is not
            authenticated.
        """
        ticket = await self.get_ticket(request)
        if ticket is None:
            return None

        try:
            # Returns a tuple of (user_id, token, userdata, validuntil)
            now = time.time()
            fields = self._ticket.validate(ticket, self._get_ip(request), now)

            # Check if we need to reissue a ticket
            if (self._reissue_time is not None and
                now >= (fields.valid_until - self._reissue_time)):

                # Reissue our ticket, and save it in our request.
                request[_REISSUE_KEY] = self._new_ticket(request, fields.user_id)

            return fields.user_id

        except TicketError as e:
            return None

    async def process_response(self, request, response):
        """If a reissue was requested, only reiisue if the response was a
        valid 2xx response
        """
        if _REISSUE_KEY in request:
            if (response.started or
                not isinstance(response, web.Response) or
                response.status < 200 or response.status > 299):
                return

            await self.remember_ticket(request, request[_REISSUE_KEY])

    @abc.abstractmethod
    async def remember_ticket(self, request, ticket):
        """Abstract function called to store the ticket data for a request.

        Args:
            request: aiohttp Request object.
            ticket: String like object representing the ticket to be stored.
        """
        pass

    @abc.abstractmethod
    async def forget_ticket(self, request):
        """Abstract function called to forget the ticket data for a request.

        Args:
            request: aiohttp Request object.
        """
        pass

    @abc.abstractmethod
    async def get_ticket(self, request):
        """Abstract function called to return the ticket for a request.

        Args:
            request: aiohttp Request object.

        Returns:
            A ticket (string like) object, or None if no ticket is available
            for the passed request.
        """
        pass

    def _get_ip(self, request):
        ip = None
        if self._include_ip:
            peername = request.transport.get_extra_info('peername')
            if peername:
                ip = ip_address(peername[0])

        return ip

    def _new_ticket(self, request, user_id):
        ip = self._get_ip(request)
        valid_until = int(time.time()) + self._max_age
        return self._ticket.new(user_id, valid_until=valid_until, client_ip=ip)
Esempio n. 7
0
class TktAuthentication(AbstractAuthentication):
    """Ticket authentication mechanism based on the ticket_auth library.

    This class is an abstract class that creates a ticket and validates it.
    Storage of the ticket data itself is abstracted to allow different
    implementations to store the cookie differently (encrypted, server side
    etc).
    """
    def __init__(self,
                 secret,
                 max_age,
                 reissue_time=None,
                 include_ip=False,
                 cookie_name='AUTH_TKT'):
        """Initializes the ticket authentication mechanism.

        Args:
            secret: Byte sequence used to initialize the ticket factory.
            max_age: Integer representing the number of seconds to allow the
                ticket to remain valid for after being issued.
            reissue_time: Integer representing the number of seconds before
                a valid login will cause a ticket to be reissued. If this
                value is 0, a new ticket will be reissued on every request
                which requires authentication. If this value is None, no
                tickets will be reissued, and the max_age will always expire
                the ticket.
            include_ip: If true, requires the clients ip details when
                calculating the ticket hash
            cookie_name: Name to use to reference the ticket details.
        """
        self._ticket = TicketFactory(secret)
        self._max_age = max_age
        if (self._max_age is not None and reissue_time is not None
                and reissue_time < self._max_age):
            self._reissue_time = max_age - reissue_time
        else:
            self._reissue_time = None

        self._include_ip = include_ip
        self._cookie_name = cookie_name

    @property
    def cookie_name(self):
        """Returns the name of the cookie stored in the session"""
        return self._cookie_name

    async def remember(self, request, user_id):
        """Called to store the userid for a request.

        This function creates a ticket from the request and user_id, and calls
        the abstract function remember_ticket() to store the ticket.

        Args:
            request: aiohttp Request object.
            user_id: String representing the user_id to remember
        """
        ticket = self._new_ticket(request, user_id)
        await self.remember_ticket(request, ticket)

    async def forget(self, request):
        """Called to forget the userid for a request

        This function calls the forget_ticket() function to forget the ticket
        associated with this request.

        Args:
            request: aiohttp Request object
        """
        await self.forget_ticket(request)

    async def get(self, request):
        """Gets the user_id for the request.

        Gets the ticket for the request using the get_ticket() function, and
        authenticates the ticket.

        Args:
            request: aiohttp Request object.

        Returns:
            The userid for the request, or None if the ticket is not
            authenticated.
        """
        ticket = await self.get_ticket(request)
        if ticket is None:
            return None

        try:
            # Returns a tuple of (user_id, token, userdata, validuntil)
            now = time.time()
            fields = self._ticket.validate(ticket, self._get_ip(request), now)

            # Check if we need to reissue a ticket
            if (self._reissue_time is not None and now >=
                (fields.valid_until - self._reissue_time)):

                # Reissue our ticket, and save it in our request.
                request[_REISSUE_KEY] = self._new_ticket(
                    request, fields.user_id)

            return fields.user_id

        except TicketError as e:
            return None

    async def process_response(self, request, response):
        """If a reissue was requested, only reiisue if the response was a
        valid 2xx response
        """
        if _REISSUE_KEY in request:
            if (response.started or not isinstance(response, web.Response)
                    or response.status < 200 or response.status > 299):
                return

            await self.remember_ticket(request, request[_REISSUE_KEY])

    @abc.abstractmethod
    async def remember_ticket(self, request, ticket):
        """Abstract function called to store the ticket data for a request.

        Args:
            request: aiohttp Request object.
            ticket: String like object representing the ticket to be stored.
        """
        pass

    @abc.abstractmethod
    async def forget_ticket(self, request):
        """Abstract function called to forget the ticket data for a request.

        Args:
            request: aiohttp Request object.
        """
        pass

    @abc.abstractmethod
    async def get_ticket(self, request):
        """Abstract function called to return the ticket for a request.

        Args:
            request: aiohttp Request object.

        Returns:
            A ticket (string like) object, or None if no ticket is available
            for the passed request.
        """
        pass

    def _get_ip(self, request):
        ip = None
        if self._include_ip:
            peername = request.transport.get_extra_info('peername')
            if peername:
                ip = ip_address(peername[0])

        return ip

    def _new_ticket(self, request, user_id):
        ip = self._get_ip(request)
        valid_until = int(time.time()) + self._max_age
        return self._ticket.new(user_id, valid_until=valid_until, client_ip=ip)