mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-04-17 22:24:34 +08:00
require Origin: header for password-based auth, and check Origin: header against session token
This commit is contained in:
@@ -45,6 +45,7 @@ import jsontokens
|
||||
import subprocess
|
||||
import platform
|
||||
import shutil
|
||||
import urlparse
|
||||
from jsonschema import ValidationError
|
||||
from schemas import *
|
||||
import client as bsk_client
|
||||
@@ -62,7 +63,7 @@ import backend.drivers as backend_drivers
|
||||
import proxy
|
||||
from proxy import json_is_error, json_is_exception
|
||||
|
||||
from .constants import BLOCKSTACK_DEBUG, BLOCKSTACK_TEST, RPC_MAX_ZONEFILE_LEN, CONFIG_PATH, WALLET_FILENAME, TX_MIN_CONFIRMATIONS, DEFAULT_API_PORT, SERIES_VERSION, TX_MAX_FEE
|
||||
from .constants import BLOCKSTACK_DEBUG, BLOCKSTACK_TEST, RPC_MAX_ZONEFILE_LEN, CONFIG_PATH, WALLET_FILENAME, TX_MIN_CONFIRMATIONS, DEFAULT_API_PORT, SERIES_VERSION, TX_MAX_FEE, DEFAULT_UI_PORT
|
||||
from .method_parser import parse_methods
|
||||
from .wallet import make_wallet
|
||||
import app
|
||||
@@ -285,6 +286,30 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
|
||||
return ret
|
||||
|
||||
|
||||
def verify_origin(self, allowed):
|
||||
"""
|
||||
Verify that the Origin: header is present and listed
|
||||
in our list of allowed origins
|
||||
Return True if so
|
||||
Return False if not
|
||||
"""
|
||||
allowed_urlparse = [urlparse.urlparse(a) for a in allowed]
|
||||
for a in allowed_urlparse:
|
||||
assert a.netloc, "Invalid origin {}".format(a)
|
||||
|
||||
allowed_origins = dict([(a.netloc, a) for a in allowed_urlparse])
|
||||
|
||||
origin_header = self.headers.get('origin', None)
|
||||
if origin_header is not None:
|
||||
origin_info = urlparse.urlparse(origin_header)
|
||||
if origin_info.netloc in allowed_origins.keys():
|
||||
allowed_origin = allowed_origins[origin_info.netloc]
|
||||
if origin_info.scheme == allowed_origin.scheme and origin_info.netloc == allowed_origin.netloc:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def verify_session(self, qs_values):
|
||||
"""
|
||||
Verify and return the application's session.
|
||||
@@ -453,6 +478,7 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
|
||||
if decode_err:
|
||||
log.error('Current decode error:')
|
||||
log.exception(decode_err)
|
||||
|
||||
log.error('Legacy decode error:')
|
||||
log.exception(ve)
|
||||
return self._reply_json({'error': 'Invalid authRequest token: does not match any known request schemas'}, status_code=401)
|
||||
@@ -3490,7 +3516,14 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
LOCALHOST = [
|
||||
'http://localhost:{}'.format(DEFAULT_UI_PORT),
|
||||
'http://{}:{}'.format(socket.gethostname(), DEFAULT_UI_PORT),
|
||||
'http://127.0.0.1:{}'.format(DEFAULT_UI_PORT),
|
||||
'http://::1:{}'.format(DEFAULT_UI_PORT)
|
||||
]
|
||||
|
||||
path_info = self.get_path_and_qs()
|
||||
if 'error' in path_info:
|
||||
self._send_headers(status_code=401, content_type='text/plain')
|
||||
@@ -3514,12 +3547,27 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
|
||||
use_session = whitelist_info['auth_session']
|
||||
use_password = whitelist_info['auth_pass']
|
||||
|
||||
log.debug("\nfull path: {}\nmethod: {}\npath: {}\nqs: {}\nheaders:\n {}\n".format(self.path, method_name, path_info['path'], qs_values, '\n'.join( '{}: {}'.format(k, v) for (k, v) in self.headers.items() )))
|
||||
log.debug("\nfull path: {}\nmethod: {}\npath: {}\nqs: {}\nheaders:\n{}\n".format(self.path, method_name, path_info['path'], qs_values, '\n'.join( '{}: {}'.format(k, v) for (k, v) in self.headers.items() )))
|
||||
|
||||
have_password = False
|
||||
session = self.verify_session(qs_values)
|
||||
if not session:
|
||||
have_password = self.verify_password()
|
||||
# password authentication
|
||||
# don't even try to authenticate with the password unless the Origin is set appropriately
|
||||
if self.verify_origin(LOCALHOST):
|
||||
# can authenticate
|
||||
have_password = self.verify_password()
|
||||
else:
|
||||
log.warning("Origin is absent or not local")
|
||||
|
||||
else:
|
||||
# got a session.
|
||||
# check origin.
|
||||
app_domain = session['app_domain']
|
||||
if not self.verify_origin([app_domain]):
|
||||
# invalid session
|
||||
log.warning("Invalid session: app domain '{}' does not match Origin '{}'".format(app_domain, self.headers.get('origin', '')))
|
||||
session = None
|
||||
|
||||
authorized = False
|
||||
|
||||
@@ -3800,6 +3848,7 @@ class BlockstackAPIEndpointClient(object):
|
||||
elif self.session:
|
||||
headers['Authorization'] = 'bearer {}'.format(self.session)
|
||||
|
||||
headers['Origin'] = 'http://localhost:{}'.format(DEFAULT_UI_PORT)
|
||||
return headers
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user