OS-1 : insecure UI websocket.
- notes on authentication of UI web socket connection.
- new classes: UiSessionToken, UiTokenService.
- UiExtensionManager now implements UiTokenService.
- UiWebSocket now expects an authentication event from the client
- websocket.js now sends authentication event as first event
- (fix websocket Jasmine test)

Change-Id: I4303c67f57fc618e911be244091f00bcc2823c91
diff --git a/web/gui/src/main/webapp/app/fw/mast/mast.js b/web/gui/src/main/webapp/app/fw/mast/mast.js
index 4d8b5fa..6483703 100644
--- a/web/gui/src/main/webapp/app/fw/mast/mast.js
+++ b/web/gui/src/main/webapp/app/fw/mast/mast.js
@@ -84,8 +84,8 @@
                 ns.toggleNav();
             };
 
-            // onosAuth is a global set via the index.html generated source
-            $scope.user = onosAuth || '(no one)';
+            // onosUser is a global set via the index.html generated source
+            $scope.user = onosUser || '(no one)';
             $scope.helpTip = 'Show help page for current view';
 
             $scope.directTo = function () {
diff --git a/web/gui/src/main/webapp/app/fw/remote/websocket.js b/web/gui/src/main/webapp/app/fw/remote/websocket.js
index 55c7b40..5922c60 100644
--- a/web/gui/src/main/webapp/app/fw/remote/websocket.js
+++ b/web/gui/src/main/webapp/app/fw/remote/websocket.js
@@ -38,10 +38,9 @@
         nextListenerId = 1,     // internal ID for open listeners
         loggedInUser = null;    // name of logged-in user
 
-    // =======================
-    // === Bootstrap Handler
-
+    // built-in handlers
     var builtinHandlers = {
+
         bootstrap: function (data) {
             $log.debug('bootstrap data', data);
             loggedInUser = data.user;
@@ -53,6 +52,18 @@
                     // TODO: add connect info to masthead somewhere
                 }
             });
+        },
+
+        error: function (data) {
+            var m = data.message || 'error from server';
+            $log.error(m, data);
+
+            // Unrecoverable error - throw up the veil...
+            vs && vs.show([
+                'Oops!',
+                'Server reports error...',
+                m
+            ]);
         }
     };
 
@@ -183,7 +194,7 @@
 
     // Currently supported opts:
     //   wsport: web socket port (other than default 8181)
-    // host: if defined, is the host address to use
+    //   host:   if defined, is the host address to use
     function createWebSocket(opts, _host_) {
         var wsport = (opts && opts.wsport) || null;
 
@@ -198,6 +209,8 @@
             ws.onopen = handleOpen;
             ws.onmessage = handleMessage;
             ws.onclose = handleClose;
+
+            sendEvent('authentication', {token: onosAuth});
         }
         // Note: Wsock logs an error if the new WebSocket call fails
         return url;
diff --git a/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js b/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js
index fc7aa09..69898ef 100644
--- a/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js
+++ b/web/gui/src/main/webapp/tests/app/fw/remote/websocket-spec.js
@@ -121,7 +121,10 @@
             payload: { mock: 'thing' }
         };
         wss.sendEvent(fakeEvent.event, fakeEvent.payload);
-        expect(mockWebSocket.send).not.toHaveBeenCalled();
+        // on opening the socket, a single authentication event should have
+        // been sent already...
+        expect(mockWebSocket.send.calls.count()).toEqual(1);
+
         wss.createWebSocket({ wsport: 1234 });
         mockWebSocket.onopen();
         expect(mockWebSocket.send).toHaveBeenCalledWith(JSON.stringify(fakeEvent));
diff --git a/web/gui/src/main/webapp/tests/server.mock.js b/web/gui/src/main/webapp/tests/server.mock.js
index 3ecdbdb..3d10b11 100644
--- a/web/gui/src/main/webapp/tests/server.mock.js
+++ b/web/gui/src/main/webapp/tests/server.mock.js
@@ -1,2 +1,3 @@
-onosAuth = '';
+onosUser = 'onos';
+onosAuth = 'foo';
 userPrefs = {};
\ No newline at end of file