Expanding .NET desktop apps into the cloud – Security
Moving your desktop application to the hybrid environment (cloud connected) allow access to the power of cloud webservices and present some interesting challenges. This article targets this migration, or should I say, expansion.
For this article, let's use as an example a desktop application that will use one or more Forge API. You can think this application as an AutoCAD, Revit or Inventor plugin, for instance, but can also be a stand-alone Windows application. As most of Autodesk desktop plugins use .NET, this article will use this programming environment.
Security & Authorization
That's the key point we need to pay attention. On a pure desktop application, one of our biggest security concern is around subscription: how to make sure the users are authorized to use the app or the features inside the app. Of course, the application security against exploits is important, but the .NET runtime takes care of most of it. On the hybrid (or cloud connected) environment this is important as well, the but the overall security is the base foundation we need.
If you are not yet doing this, consider using something like ConfuserEx tool to protect against most of common disassemble and debug crackers. This is valid for both desktop and hybrid apps. As a pure cloud app runs in the cloud environment, this tool is not needed (but need to implement other features).
A hybrid application will use Forge and other cloud API providers. For example, get the address of a BIM 360 Docs project and check the weather conditions and forecast from another provider. Or get a bill of materials (BOM) for a Fusion Team assembly and request price from suppliers.
In any case we don’t want our app exposing unnecessary or private information to the client (or desktop app module). For instance, following the sample mentioned above, we can expose the project weather conditions, maybe the address, but not the list of contractors on the project site. Or, on the second example, expose the BOM for quotation, but not the overall design (3D model, for instance).
The Forge API have scopes to define the level of access, such as data:read, which allows read to everything the user has access in a 3-legged environment, which can be ok. In a 2-legged environment, as all buckets are defined for the application, it may leak information between end-users of the app if a user can read all buckets and read someone else’s bucket.
To ensure only the data we authorize is exposed, the best approach is to place a cloud app module in the middle, as shown on the architecture below. This will control what each user has access and return only the data that specific client requires/needs. As mentioned, the image shows ASP.NET on the cloud module, as a way to reuse your .NET expertise, but this can be developed in any language.
First, let’s investigate the scenario where your app will require your end-user to sign in with his/her Autodesk Account on your app so it can show his/her files on Autodesk (BIM 360 Team, BIM 360 Docs or Fusion Team). Here are the common steps:
- Your app shows the Autodesk sign in page
- The end-user types his/her user and password
- Autodesk authenticate and notify the app (via callback URL)
- Your app accesses the data, manipulates and shows it to the user
There a few common mistakes we need to avoid:
- Do not place your Forge Client ID and Secret on the desktop client, it MUST be securely stored on your cloud module. Even an encrypted desktop app can be decoded eventually. And this is not practical if you need to refresh or change the ID & Secret
- Your app should control the authentication, do not let the desktop client control it with callbacks coming to a local server. There are security problems if the access_token is on the client, but it may also get blocked by firewalls
- Avoid storing access_token on the client, that gives the client the ability to call any Forge API. You may consider that in a 3-legged environment that user will only be able to see his/her data, but it can also be used to perform Model Derivative or Design Automation calls (depending on the scope), which will bill to your application. Even only accessing his/her data, the action will be performed under your application authority
- Do not transfer sensitive information on URLs (querystring), always use header or body for that data and always under secure channels (HTTPS connections with SSL/TLS)
How to implement?
To implement that our solution will need an authorization database to store the users that are using and authorized to use our app. The cloud app module handles all the calls, from authentication to data requests.
In case of 3-legged authentication, your application will need a database to store the Autodesk credentials. The overall architecture is an expansion of the previous, here are the steps are:
- On a webcontrol, redirect the end-user to your cloud app sign in
- The cloud app sign should redirect to Autodesk authentication (using the Forge Client ID) and wait for the callback
- When called back, perform the following server-side operations:
- Receive the callback code
- Request the access/refresh token pair
- Store that on a database, which should generate a “session id”, which can be the database record unique ID, for instance
- Send that session ID (encrypted) to the desktop client
- At this point the client holds a session ID that uniquely identifies
- When the client requests a resource
- the client should provide the session ID on the request header
- the cloud app module asks the database for the respective access_token (refresh if needed)
- call the required Forge API
- filter/manipulate the results from Forge API
- send the results back to the client
The architecture is basically the same, just adding the database that will keep record of the access/refresh token pair for Forge and the respective session ID.
In a 2-legged environment, the above approach still applies, except there is no end-user authentication. Make sure all calls are passing through the cloud app, which will request the appropriate Forge access_token, make the call, filter/manipulate the results and send back to the client.