def test_get_service_key(self): storage = CredentialStorage(self.plugin) service_key = create(Builder('service_key')) key_from_storage = storage.get_service_key(service_key['key_id']) self.assertIsInstance(key_from_storage, PersistentMapping) self.assertEqual(service_key, dict(key_from_storage))
class ViewUsageLogs(BrowserView): def __call__(self): acl_users = api.portal.get().acl_users plugin = acl_users['token_auth'] self.storage = CredentialStorage(plugin) self.request.set('disable_border', True) self.key_id = self.request.form['key_id'] key_title = self.get_key_title() options = { 'key_title': key_title, 'usage_log_retention_days': plugin.usage_log_retention_days, } return self.index(**options) def get_key_title(self): service_key = self.storage.get_service_key(self.key_id) return service_key['title'] def get_usage_logs(self): """Return usage logs in reverse order (most recent first). This is a much more natural order for display (most recent at the top), but it means we're sorting twice. That should be a negligible penalty though, and we'd much rather incur a performance hit when displaying usage logs than when writing them. (Standard lists are optimized for appending to the end - inserts at the beginning don't perform well. There's deques for that, but the persistent implementation in `persistent.ring._DequeRing` isn't considered public). """ entries = reversed(self.storage.get_usage_logs(self.key_id)) return entries
def get_key(self): key_id = self.request.form['key_id'] storage = CredentialStorage(self.get_plugin()) key = storage.get_service_key(key_id) return key
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