Example #1
0
    def authenticateCredentials(self, credentials):
        """Authenticate a request that contains an OAuth2 bearer access token.

        Implementation of IAuthenticationPlugin that authenticates requests
        that contain a valid OAuth2 bearer access token.

        """
        # Ignore credentials that are not from our extractor
        extractor = credentials.get('extractor')
        if extractor != self.getId():
            # While RFC 6750 says that requests without authentication MUST
            # be answered with a WWW-Authenticate challenge, we can't do that
            # here, since OAuth2 isn't the only authentication mechanism we
            # need to support.
            # See: https://tools.ietf.org/html/rfc6750#section-3
            return None

        received_token = credentials['access_token']
        storage = CredentialStorage(self)

        # Reject unknown or revoked tokens
        if not storage.contains_access_token(received_token):
            # TODO: Should we send an 'invalid_token' error response here?
            return None

        stored_access_token = storage.get_access_token(received_token)

        # Reject expired tokens
        if self.is_expired(stored_access_token):
            # Token expired, send error response according to
            # https://tools.ietf.org/html/rfc6750#section-3.1
            response = getRequest().response
            body = json.dumps({
                'error': 'invalid_token',
                'error_description': 'Access token expired'
            })
            response.setBody(body, lock=True)
            response.setStatus(401, lock=True)

            # TODO: According to RFC 6750, we should also send a
            # WWW-Authenticate: Bearer realm="example"
            # here. Check whether we really want to send this challenge
            return None

        # Fetch service key that the token was tied to (by us)
        service_key = storage.get_service_key(stored_access_token['key_id'],
                                              unrestricted=True)

        ip_range = service_key['ip_range']
        if ip_range is not None:
            client_ip = self.REQUEST.getClientAddr()
            if not client_ip:
                # IP range limitations in place - require that we get a
                # client IP (trusted proxies need to be set up correctly)
                log.warn('Authentication attempt for key with IP range '
                         'restrictions, but failed to get client IP from '
                         'getClientAddr() - check trusted-proxy in zope.conf')
                return None

            if not permitted_ip(client_ip, ip_range):
                log.warn('Authentication attempt from '
                         'disallowed IP %s' % client_ip)
                return None

        # Fetch and verify the user associated with the stored access token
        user_id = stored_access_token['user_id']
        pas = self._getPAS()
        # This only works for users in Plone site, not Zope application root
        info = pas._verifyUser(pas.plugins, user_id=user_id)
        if info is None:
            return None

        mtool = getToolByName(getSite(), 'portal_membership')
        member = mtool.getMemberById(user_id)
        if member is None:
            return None

        return user_id, user_id
Example #2
0
 def test_disallowed_ip_in_multiple_ipv4_address_ranges(self):
     self.assertFalse(permitted_ip('192.168.0.7', '10.0.0.5, 192.168.0.1'))
Example #3
0
 def test_allowed_ip_in_multiple_ipv4_cidr_network_ranges(self):
     self.assertTrue(
         permitted_ip('192.168.5.5', '10.0.0.0/8, 192.168.0.0/16'))
     self.assertTrue(permitted_ip('10.1.5.20',
                                  '10.0.0.0/8, 192.168.0.0/16'))
Example #4
0
 def test_invalid_ip_range_is_rejected(self):
     self.assertFalse(permitted_ip('10.0.0.1', '500.500.0.0/33'))
Example #5
0
 def test_allowed_ip_in_multiple_ipv4_address_ranges(self):
     self.assertTrue(permitted_ip('10.0.0.5', '10.0.0.5, 192.168.0.1'))
     self.assertTrue(permitted_ip('192.168.0.1', '10.0.0.5, 192.168.0.1'))
Example #6
0
 def test_invalid_ip_address_is_rejected(self):
     with self.assertRaises(ValueError):
         permitted_ip('500.500.0.0', '192.168.0.0/16')
Example #7
0
 def test_disallowed_ip_in_single_ipv4_cidr_network_range(self):
     self.assertFalse(permitted_ip('10.0.0.0', '192.168.0.0/16'))
Example #8
0
 def test_allowed_ip_in_single_ipv4_cidr_network_range(self):
     self.assertTrue(permitted_ip('192.168.0.1', '192.168.0.0/16'))
Example #9
0
 def test_disallowed_ip_in_single_ipv4_address_range(self):
     self.assertFalse(permitted_ip('10.0.0.0', '192.168.0.1'))
Example #10
0
 def test_allowed_ip_in_single_ipv4_address_range(self):
     self.assertTrue(permitted_ip('192.168.0.1', '192.168.0.1'))