def process_request(self, req, resp): # http basic auth if self.config['server'].get('enable_basic_auth'): hdr_auth = req.get_header('AUTHORIZATION') if not hdr_auth: raise falcon.HTTPUnauthorized('Access denied', 'No auth header', []) auth = re.sub('^Basic ', '', hdr_auth) usr, pwd = decodestring(auth).split(':') if not equals(self.basic_auth.get(usr, ''), pwd): logger.warning('basic auth failure: %s', usr) raise falcon.HTTPUnauthorized('Access denied', 'Basic auth failure', []) segments = req.path.strip('/').split('/') if segments[0] == 'api': if len(segments) >= 3: # twilio validation if segments[2] == 'twilio': sig = req.get_header('X_TWILIO_SIGNATURE') if sig is None: logger.warning("no twilio signature found!") raise falcon.HTTPUnauthorized('Access denied', 'No Twilio signature', []) uri = [ req.protocol, '://', req.get_header('HOST'), self.config['server'].get('lb_routing_path', ''), req.path ] if req.query_string: uri.append('?') uri.append(req.query_string) post_body = req.context['body'] expected_sigs = [ compute_signature(t, ''.join(uri), post_body) for t in self.twilio_auth_token ] if sig not in expected_sigs: logger.warning( 'twilio validation failure: %s not in possible sigs: %s', sig, expected_sigs) raise falcon.HTTPUnauthorized('Access denied', 'Twilio auth failure', []) return elif segments[2] == 'gmail' or segments[ 2] == 'gmail-oneclick' or segments[2] == 'slack': return elif len(segments) == 1: if segments[0] == 'health' or segments[0] == 'healthcheck': return elif segments[0] == self.config['gmail'].get('verification_code'): return raise falcon.HTTPUnauthorized('Access denied', 'Authentication failed', [])
def process_request(self, req, resp): if self.debug: return # CORS Pre-flight if req.method == 'OPTIONS': resp.status = falcon.HTTP_204 return # http basic auth if self.config['server'].get('enable_basic_auth'): hdr_auth = req.get_header('AUTHORIZATION') if not hdr_auth: raise falcon.HTTPUnauthorized('Access denied', 'No auth header', []) auth = re.sub('^Basic ', '', hdr_auth) usr, pwd = decodestring(auth).split(':') if not equals(self.basic_auth.get(usr, ''), pwd): logger.warning('basic auth failure: %s', usr) raise falcon.HTTPUnauthorized('Access denied', 'Basic auth failure', []) segments = req.path.strip('/').split('/') if segments[0] == 'api': if len(segments) >= 3: # twilio validation if segments[2] == 'twilio': sig = req.get_header('X_TWILIO_SIGNATURE') if sig is None: logger.warning("no twilio signature found!") raise falcon.HTTPUnauthorized('Access denied', 'No Twilio signature', []) uri = [ req.protocol, '://', req.get_header('HOST'), self.config['server'].get('lb_routing_path', ''), req.path ] if req.query_string: uri.append('?') uri.append(req.query_string) post_body = req.context['body'] expected_sigs = [ compute_signature(t, ''.join(uri), post_body) for t in self.twilio_auth_token ] sig = sig.encode('utf8') if sig not in expected_sigs: logger.warning( 'twilio validation failure: %s not in possible sigs: %s', sig, expected_sigs) raise falcon.HTTPUnauthorized('Access denied', 'Twilio auth failure', []) return elif self.mobile and (segments[2] == 'mobile' or segments[2] == 'oncall'): # Only allow refresh tokens for /refresh, only access for all else table = 'refresh_token' if segments[ 3] == 'refresh' else 'access_token' key_query = '''SELECT `key`, `target`.`name` FROM `%s` JOIN `target` ON `user_id` = `target`.`id` WHERE `%s`.`id` = %%s AND `expiration` > %%s''' % (table, table) method = req.method auth = req.get_header('Authorization', required=True) items = urllib2.parse_http_list(auth) parts = urllib2.parse_keqv_list(items) if 'signature' not in parts or 'keyId' not in parts or 'timestamp' not in parts: raise falcon.HTTPUnauthorized( 'Authentication failure: invalid header') try: window = int(parts['timestamp']) time_diff = abs(time.time() - window) except ValueError: raise falcon.HTTPUnauthorized( 'Authentication failure: invalid header') client_digest = parts['signature'] key_id = parts['keyId'] body = req.context['body'].decode('utf8') path = req.env['PATH_INFO'] qs = req.env['QUERY_STRING'] if qs: path = path + '?' + qs text = '%s %s %s %s' % (window, method, path, body) text = text.encode('utf8') conn = db.connect() cursor = conn.cursor() cursor.execute(key_query, (key_id, time.time())) row = cursor.fetchone() conn.close() # make sure that there exists a row for the corresponding username if row is None: raise falcon.HTTPUnauthorized( 'Authentication failure: server') key = self.fernet.decrypt(str(row[0]).encode('utf8')) key = key req.context['user'] = row[1] HMAC = hmac.new(key, text, hashlib.sha512) digest = urlsafe_b64encode(HMAC.digest()) if hmac.compare_digest( client_digest.encode('utf8'), digest) and time_diff < self.time_window: return else: raise falcon.HTTPUnauthorized( 'Authentication failure: server') elif segments[2] == 'gmail' or segments[ 2] == 'gmail-oneclick' or segments[ 2] == 'slack' or segments[2] == 'ical': return elif len(segments) == 1: if segments[0] == 'health' or segments[0] == 'healthcheck': return elif segments[0] == self.config.get('gmail', {}).get('verification_code'): return elif segments[0] == 'saml': return raise falcon.HTTPUnauthorized('Access denied', 'Authentication failed', [])