diff --git a/internimsclient.py b/internimsclient.py
index fc10c17b2ca2a4f461145d5dcbf3d0a9e09f179b..1aad9f46420320f8f0a520dea971e3c2023e8abb 100755
--- a/internimsclient.py
+++ b/internimsclient.py
@@ -30,7 +30,7 @@ def update(db, api_uri, site_id, privkey, internims_url):
     signature = Crypto.Signature.PKCS1_v1_5.new(privkey).sign(h)
     headers = {'Authorization': base64.b64encode(signature)}
 
-    r = requests.post(url=internims_url, data=payload, headers=headers, verify=True)
+    r = requests.post(internims_url, data=payload, headers=headers)
     if r.status_code == 200:
         response = (json.loads(r.content))
         # update remotes entries
@@ -40,12 +40,12 @@ def update(db, api_uri, site_id, privkey, internims_url):
         log.debug('updating remotes: ' + ', '.join((r['_id'] for r in response['sites'])))
 
         # delete remotes from users, who no longer have remotes
-        db.users.update({'remotes': {'$exists':True}, 'uid': {'$nin': response['users'].keys()}}, {'$unset': {'remotes': ''}}, multi=True)
+        db.users.update({'remotes': {'$exists':True}, '_id': {'$nin': response['users'].keys()}}, {'$unset': {'remotes': ''}}, multi=True)
 
         # add remotes to users
         log.debug('users w/ remotes: ' + ', '.join(response['users']))
         for uid, remotes in response['users'].iteritems():
-            db.users.update({'uid': uid}, {'$set': {'remotes': remotes}})
+            db.users.update({'_id': uid}, {'$set': {'remotes': remotes}})
     else:
         # r.reason contains generic description for the specific error code
         # need the part of the error response body that contains the detailed explanation
diff --git a/nimsapi.py b/nimsapi.py
index f066d4f00aab4432648c4c250304c52f2d226d70..7131fd3a97add4c85705743f2f2f24c11eaf7d3a 100755
--- a/nimsapi.py
+++ b/nimsapi.py
@@ -33,7 +33,7 @@ class NIMSAPI(nimsapiutil.NIMSRequestHandler):
         """Return 200 OK."""
         self.response.set_status(200)
 
-    def get(self):
+    def get(self, *args):
         """Return API documentation"""
         resources = """
             Resource                                            | Description
@@ -100,6 +100,15 @@ class NIMSAPI(nimsapiutil.NIMSRequestHandler):
         self.response.write('</body>\n')
         self.response.write('</html>\n')
 
+    def login(self):
+        """Return details for the current User."""
+        log.info(self.uid + ' has logged in')
+        return self.app.db.users.find_and_modify({'_id': self.uid}, {'$inc': {'logins': 1}}, fields=['firstname', 'lastname', 'superuser'])
+
+    def remotes(self):
+        """Return the list of all remote sites."""
+        return [r['_id'] for r in self.app.db.remotes.find()]
+
     def upload(self):
         # TODO add security: either authenticated user or machine-to-machine CRAM
         if 'Content-MD5' not in self.request.headers:
@@ -129,29 +138,22 @@ class NIMSAPI(nimsapiutil.NIMSRequestHandler):
             paths += _idpaths
             symlinks += _idsymlinks
 
-    def remotes(self):
-        """Return the list of all remote sites."""
-        return list(self.app.db.remotes.find(None, []))
-
     def log(self):
         """Return logs."""
         try:
             logs = open(app.config['log_path']).readlines()
         except IOError as e:
-            log.debug(e)
             if 'Permission denied' in e:
-                # specify body format to print details separate from comment
                 body_template = '${explanation}<br /><br />${detail}<br /><br />${comment}'
                 comment = 'To fix permissions, run the following command: chmod o+r ' + logfile
                 self.abort(500, detail=str(e), comment=comment, body_template=body_template)
             else:
-                # file does not exist
-                self.abort(500, e)
+                self.abort(500, e) # file does not exist
         try:
             n = int(self.request.get('n', 10000))
         except:
             self.abort(400, 'n must be an integer')
-        return [line for line in reversed(logs) if re.match('[\d\s:-]{17}[\s]+nimsapi:[.]*', line)][:n]
+        return [line.strip() for line in reversed(logs) if re.match('[-:0-9 ]{18} +nimsapi:(?!.*[/a-z]*/log )', line)][:n]
 
 
 class Users(nimsapiutil.NIMSRequestHandler):
@@ -252,13 +254,6 @@ class User(nimsapiutil.NIMSRequestHandler):
         'required': ['_id'],
     }
 
-    def current(self):
-        """Return details for the current User."""
-        if self.request.method == 'GET':
-            return self.get(self.uid)
-        elif self.request.method == 'PUT':
-            return self.put(self.uid)
-
     def get(self, uid):
         """Return User details."""
         projection = []
@@ -266,14 +261,11 @@ class User(nimsapiutil.NIMSRequestHandler):
             projection += ['remotes']
         if self.request.get('status') in ('1', 'true'):
             projection += ['status']
-        if self.request.get('login') in ('1', 'true'):
-            projection += ['firstname', 'lastname', 'superuser']
-            self.app.db.users.update({'uid': uid}, {'$inc': {'logins': 1}})
-        return self.app.db.users.find_one({'uid': uid}, projection or None)
+        return self.app.db.users.find_one({'_id': uid}, projection or None)
 
     def put(self, uid):
         """Update an existing User."""
-        user = self.app.db.users.find_one({'uid': uid})
+        user = self.app.db.users.find_one({'_id': uid})
         if not user:
             self.abort(404)
         if uid == self.uid or self.user_is_superuser: # users can only update their own info
@@ -288,7 +280,7 @@ class User(nimsapiutil.NIMSRequestHandler):
                         updates['$set'][k] = False # superuser is tri-state: False indicates granted, but disabled, superuser privileges
                     elif v.lower() not in ('1', 'true'):
                         updates['$unset'][k] = ''
-            self.app.db.users.update({'uid': uid}, updates)
+            self.app.db.users.update({'_id': uid}, updates)
         else:
             self.abort(403)
 
@@ -396,17 +388,16 @@ class Group(nimsapiutil.NIMSRequestHandler):
 
 
 routes = [
-    webapp2.Route(r'/nimsapi',                                      NIMSAPI),
     webapp2_extras.routes.PathPrefixRoute(r'/nimsapi', [
-        webapp2.Route(r'/download',                                 NIMSAPI, handler_method='download', methods=['GET']),
-        webapp2.Route(r'/upload',                                   NIMSAPI, handler_method='upload', methods=['PUT']),
+        webapp2.Route(r'/login',                                    NIMSAPI, handler_method='login', methods=['GET', 'POST']),
         webapp2.Route(r'/remotes',                                  NIMSAPI, handler_method='remotes', methods=['GET']),
+        webapp2.Route(r'/upload',                                   NIMSAPI, handler_method='upload', methods=['PUT']),
+        webapp2.Route(r'/download',                                 NIMSAPI, handler_method='download', methods=['GET']),
         webapp2.Route(r'/log',                                      NIMSAPI, handler_method='log', methods=['GET']),
         webapp2.Route(r'/users',                                    Users),
         webapp2.Route(r'/users/count',                              Users, handler_method='count', methods=['GET']),
         webapp2.Route(r'/users/listschema',                         Users, handler_method='schema', methods=['GET']),
         webapp2.Route(r'/users/schema',                             User, handler_method='schema', methods=['GET']),
-        webapp2.Route(r'/users/current',                            User, handler_method='current', methods=['GET', 'PUT']),
         webapp2.Route(r'/users/<uid>',                              User),
         webapp2.Route(r'/groups',                                   Groups),
         webapp2.Route(r'/groups/count',                             Groups, handler_method='count', methods=['GET']),
@@ -437,16 +428,18 @@ routes = [
         webapp2.Route(r'/collections/<cid:[0-9a-f]{24}>/sessions',  collections_.Sessions),
         webapp2.Route(r'/collections/<cid:[0-9a-f]{24}>/epochs',    collections_.Epochs),
     ]),
+    webapp2.Route(r'/nimsapi',                                      NIMSAPI),
+    webapp2.Route(r'/nimsapi/<:.*>',                                NIMSAPI),
 ]
 
 def dispatcher(router, request, response):
     rv = router.default_dispatcher(request, response)
     if rv is not None:
-        return webapp2.Response(json.dumps(rv, default=bson.json_util.default))
+        return response.write(json.dumps(rv, default=bson.json_util.default))
 
 app = webapp2.WSGIApplication(routes, debug=True)
 app.router.set_dispatcher(dispatcher)
-app.config = dict(stage_path='', site_id=None, ssl_key=None, insecure=False, log_path='')
+app.config = dict(stage_path='', site_id='local', ssl_key=None, insecure=False, log_path='')
 
 
 if __name__ == '__main__':
@@ -482,9 +475,9 @@ if __name__ == '__main__':
     else:
         log.warning('private SSL key not specified, internims functionality disabled')
 
-    app.config['site_id'] = args.site_id or 'local'
+    app.config['site_id'] = args.site_id or app.config['site_id']
     app.config['stage_path'] = args.stage_path or config.get('nims', 'stage_path')
-    app.config['log_path'] = args.log_path
+    app.config['log_path'] = args.log_path or app.config['log_path']
     app.config['oauth2_id_endpoint'] = args.oauth2_id_endpoint or config.get('oauth2', 'id_endpoint')
     app.config['insecure'] = config.getboolean('nims', 'insecure')
 
diff --git a/nimsapiutil.py b/nimsapiutil.py
index fd4ffa32e7e519d896e483072768e16f4e9ed02e..f00747e8b76defca46158618d9cca3633a1df8f6 100644
--- a/nimsapiutil.py
+++ b/nimsapiutil.py
@@ -61,13 +61,13 @@ class NIMSRequestHandler(webapp2.RequestHandler):
         self.access_token = self.request.headers.get('Authorization', None)
 
         # CORS header
-        self.response.headers.add('Access-Control-Allow-Origin', self.request.headers.get('origin', '*'))
+        if 'Origin' in self.request.headers and self.request.headers['Origin'].startswith('https://'):
+            self.response.headers['Access-Control-Allow-Origin'] = self.request.headers['Origin']
 
         if self.access_token and self.app.config['oauth2_id_endpoint']:
-            r = requests.request(method='GET', url=self.app.config['oauth2_id_endpoint'], headers={'Authorization': 'Bearer ' + self.access_token})
+            r = requests.get(self.app.config['oauth2_id_endpoint'], headers={'Authorization': 'Bearer ' + self.access_token})
             if r.status_code == 200:
                 self.uid = json.loads(r.content)['email']
-                log.debug('oauth user: ' + self.uid)
             else:
                 # TODO: add handlers for bad tokens
                 # inform app of expired token, app will try to get new token, or ask user to log in again
@@ -79,11 +79,11 @@ class NIMSRequestHandler(webapp2.RequestHandler):
             self.user_is_superuser = False
 
         if self.uid != '@public':
-            user = self.app.db.users.find_one({'_id': self.uid})
+            user = self.app.db.users.find_one({'_id': self.uid}, ['superuser'])
             if user:
                 self.user_is_superuser = user.get('superuser', None)
             else:
-                self.abort(403, 'user: ' + self.uid + ' does not exist')
+                self.abort(403, 'user ' + self.uid + ' does not exist')
 
         if self.target_id not in [None, self.app.config['site_id']]:
             self.rtype = 'to_remote'
@@ -95,8 +95,7 @@ class NIMSRequestHandler(webapp2.RequestHandler):
 
             target = self.app.db.remotes.find_one({'_id': self.target_id}, {'_id': False, 'api_uri': True})
             if not target:
-                log.debug('remote host ' + self.target_id + ' is not an authorized remote.')
-                self.abort(403, 'remote host ' + self.target_id + ' is not an authorized remote.')
+                self.abort(402, 'remote host ' + self.target_id + ' is not an authorized remote')
 
             # adjust headers
             self.headers = self.request.headers
@@ -118,7 +117,7 @@ class NIMSRequestHandler(webapp2.RequestHandler):
             self.headers['X-Signature'] = base64.b64encode(signature)
 
             # prepare delegated request URI
-            self.target_api = target['api_uri'] + self.request.path.split('/nimsapi')[1]
+            self.target_uri = target['api_uri'] + self.request.path.split('/nimsapi')[1]
 
         elif self.request.user_agent.startswith('NIMS Instance'):
             self.rtype = 'from_remote'
@@ -127,35 +126,41 @@ class NIMSRequestHandler(webapp2.RequestHandler):
             self.user_is_superuser = False
 
             remote_instance = self.request.user_agent.replace('NIMS Instance', '').strip()
-            requester = self.app.db.remotes.find_one({'_id':remote_instance})
+            requester = self.app.db.remotes.find_one({'_id': remote_instance})
             if not requester:
-                log.debug('remote host ' + remote_instance + ' not in auth list. DENIED')
-                self.abort(403, remote_instance + ' is not authorized')
+                self.abort(402, remote_instance + ' is not authorized')
 
-            # assemble msg, hash, and verify recieved signature
+            # assemble msg, hash, and verify received signature
             signature = base64.b64decode(self.request.headers.get('X-Signature'))
             msg = self.request.method + self.request.path + str(self.request.params.mixed()) + self.request.body + self.request.headers.get('Date')
             verifier = Crypto.Signature.PKCS1_v1_5.new(Crypto.PublicKey.RSA.importKey(requester['pubkey']))
             if not verifier.verify(Crypto.Hash.SHA.new(msg), signature):
-                log.debug('remote message/signature is not authentic')
-                self.abort(403, 'remote message/signature is not authentic')
+                self.abort(402, 'remote message/signature is not authentic')
         else:
             self.rtype = 'local'
 
-        # TODO: question: okay to move this logging block into dispatch?
-        if not self.request.path.endswith('/nimsapi/log'):
-            log.info(self.rtype + ' ' + self.request.method + ' ' + self.request.path + ' ' + str(self.request.params.mixed()))
-
     def dispatch(self):
         """dispatching and request forwarding"""
+        log.info(self.rtype + ' ' + self.uid + ' ' + self.request.method + ' ' + self.request.path + ' ' + str(self.request.params.mixed()))
         if self.rtype in ['local', 'from_remote']:
             return super(NIMSRequestHandler, self).dispatch()
         else:
-            r = requests.request(method=self.request.method, data=self.request.body, url=self.target_api, params=self.params, headers=self.headers, verify=False)
+            r = requests.request(self.request.method, self.target_uri, params=self.params, data=self.request.body, headers=self.headers, verify=False)
             if not r.status_code == 200:
                 self.abort(r.status_code, 'internims p2p err: ' + r.reason)
             self.response.write(r.content)
 
+    def abort(self, code, *args, **kwargs):
+        log.debug(str(code) + ' ' + '; '.join(args))
+        if 'Access-Control-Allow-Origin' in self.response.headers:
+            headers = kwargs.setdefault('headers', {})
+            headers['Access-Control-Allow-Origin'] = self.response.headers['Access-Control-Allow-Origin']
+        webapp2.abort(code, *args, **kwargs)
+
+    def options(self, *args, **kwargs):
+        self.response.headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE, OPTIONS'
+        self.response.headers['Access-Control-Allow-Headers'] = 'Authorization'
+
     def schema(self):
         return self.json_schema