High or low exposure to risk

The dilemma – secure information requires low system exposure, and rich functionality requires high system exposure.

It is natural to be protective of your system. The system contains your intellectual property and also information that your users have collected or created.

Building rich clients almost always means that large parts of the system must reside close to the user. The thing is, we can never be sure that any given user will not try to reverse the application.

In the case of the reversed application, the user may find some intellectual property (IP) we would rather not give away.

The user may also try to mock the application calls to trick our server into believing that it is dealing with a legitimate application that is expected to behave fairly and respect the rules of access.

These concerns have driven many system producers back to browser-based applications rather than client-side frameworks.

The problem is that the rich client has been creeping back into the browser  - as javascript – executing locally, holding lots of IP knowledge, and thus, the key to mocking the server into believing that it is dealing with a well-behaving application.

This means that we now have languages less suited for complex systems due to their lack of compile-time type-checking used to implement the rules of the system in a very open environment in the users' browsers.

I have always felt that there must be a better way.

I am all for rich applications but I understand that the risk can often be considered unacceptable.

This is what I propose to address this dilemma.

The Streaming ViewModel

The ViewModel is a great way to section off perspective on information for a specific need. Doing this sectioning ensures that we do not reveal anything more than the bare necessities when exposing information to a client. There still may be issues with actions in the ViewModel needing logic to check and perform – logic we need to let the user know is there, but not necessarily want the user to see the implementation of.

To solve this, we only expose the names of the actions to the client. If the client wants to execute an action, it must ask the server to do so. The action will change the state in our system and likely that will show as a changed state of some attributes in our ViewModel. This means that the client must retrieve any resulting news from the server once the server is done.

In the normal non-ajax web page approach, the whole ViewModel is re-rendered on such an update. I propose to solve this by only streaming back the actual changes of the ViewModel and having client-side logic update the client-side ViewModel instance – triggering an update of the bound user interface as a consequence.

Further on: the user may change the clients' state by checking boxes and filling in strings etc. These changes in the local data might result in side effects like a list being filtered or a warning light being lit. These changes must be sent back to the server as they happen; the server must mix them in with the server-side state – this might trigger updates of ViewModel attributes that must go back to the client.

And we have a round trip - but a round trip that only sends different grams of changed data – not all data.

The Concept Test

I constructed a server-side generic streaming ViewModel that can receive and send changes. I also wrote a generic client-side ViewModel in typescript – that transforms into javascript. Both these generic ViewModels are controlled entirely from MDriven ViewModel definitions.

I have chosen to work with AngualarJS on the client side – as the way to bind user interface to data. That is just my choice – this strategy will work with any client-side framework.

Given this model:

01.png

In the simplified model above, I want one user interface to browse videos – but under no circumstances should this ability expose any way to change the Genre or check who viewed the film in the past.

Declaratively, I do this ViewModel and test it out in the prototyper:

02.png

In AngualarJS, I need to do a few things to use this ViewModel:

1. I define a controller:

phonecatControllers.controller('BrowseVideos', ['$scope',
  function ($scope) {
    var x = new StreamingViewModelClient("BrowseVideos", "$null$");
    $scope.root = x.Root();
    x.ExecuteAfterServerAppliedChanges = function () { $scope.$apply(); }
    $scope.$apply(function ($scope) {
      $scope.x.ConsumeServerMessage();
    });
  }]);

Here, I make use of the StreamingViewModelClient which will automatically handle all the messaging to the StreamingViewModelServer. It will also automatically make all the data in the ViewModel available on the client side as normal javascript objects.

2. I need to tell AngualarJS when to use this controller:

      when('/BrowseVideos', {
        templateUrl: 'partials/BrowseVideos.html',
        controller: 'BrowseVideos'
      }).

3. I need to construct a UI that uses AngualarJS to display the ViewModel now available in local memory:

<div class="container-fluid">
  <div class="row">
    <div class="col-md-10">
      <!--Body content-->

      <p>Filter videos:</p>
      <input type="text" name="input" ng-model="root.Filter">

      <ul >
        <li ng-repeat="video in root.AllVideo" class="thumbnail">
          <p> {{video.Name}} {{video.Length}} minutes  {{video.Genre}} </p>
        </li>
      </ul>

    </div>
  </div>
</div>


Using only information from the model – and using very much standard front-end AngualarJS programming, I have now done everything that is required to get this functionality:

03.png
04.png

What happens as the user writes in the filter box is this:

1. Local ViewModels property named Filter is updated

2. Changes are discovered by MDriven StreamingViewModelClient and posted to the server as an Attribute_Update_Message

3. Message is received by MDriven StreamingViewModelServer and the corresponding server ViewModel is updated

4. The server-side change triggers subscription changes on the OCL expressions that build up the ViewModel

5. The outdated dependencies are re-evaluated – in this case, the AllVideo expression is run.

6. The change of the AllVideo list on the server generates a few Collection_Remove_Object messages

7. The client receives the messages about the collection_remove object and removes it accordingly

8- Roundtrip is finished – all this is done with Ajax calls – so the user keeps on working

Summing It Up

I have only just started this concept work of using a streaming ViewModel that sends messages on changes back and forth – but I think it is the correct way to go. Not only for javascript but also for WPF. This way of isolating the client from all the IP contained in the model and all the possible attack vectors that may exist if we expose too much seems perfect.

It is also a good mix of keeping all the rule evaluations in a robust type-checked server environment instead of being left out of Javascript. At the same time, it enables me to build UI in javascript – with full databind - and thus, be able to execute on any client platform.

Do you have thoughts on the problems discussed here? Let me know – maybe we can help out.

This page was edited 69 days ago on 02/10/2024. What links here