Previously we discussed our Final Desktop Sample, and showed how Private URI Schemes and Token Storage worked.
Next we will look at some code for our final Electron Desktop App, which is not too different to the First Desktop Sample’s Code.
If you are coding in C# there is an Identity Model Code Sample here that uses a Private URI Scheme:
Electron Main and Renderer Processes
Electron apps consist of two main areas:
- The Main Process is responsible for setting up our HTML application
- The Renderer Process runs our HTML application’s logic
The main process will be just an entry point, since its code is difficult to debug. All real OAuth processing will occur within our application logic.
Private URI Scheme Registration
In our main process we register our Private URI Scheme at application startup. This writes to User Specific areas of the operating system and does NOT require administrator privileges:
OS Response Notifications
The operating system sends the Authorization Response URL to our Electron App’s Main Process from which we immediately forward it to the Renderer Process.
On Windows, the OS sends us a startup command that includes the Response URL as a parameter. We avoid starting a new instance of our desktop app and instead notify the running instance:
Note that restricting the app to a single instance may not be possible in environments where you are not the host. An example might be an app that is invoked from Microsoft Excel and implemented as a plugin.
On Mac OS we receive an Open URL event instead:
Desktop App Response Notifications
Our desktop app receives the above message using the Electron RPC mechanism. I put this code into a small LoginNotifier class:
The role of this class is just to unpack response query parameters and resume the authorization flow:
Once done, all other code is pretty much identical to our first sample, though of course there is no longer a need for a loopback web server.
Resuming Logins Reliably
For our previous sample we discussed Reentrancy and Correlation and we have the same concerns when using Private URI Schemes.
Our Login Notifier class uses a Login State Map to reliably resume logins. Again we keep this code separated from main OAuth processing.
Productive Developer Setup
Electron has an annoying limitation that OS notifications for Private URI Schemes only work against a packaged application, which limits developer productivity and debugging.
The approach I would use for a productive local setup would be to support both types of login, and use the loopback option during local development:
Provide a facade for OAuth processing, so that the rest of your app does not need to be aware of details. You can then swap out the implementation based on runtime conditions – we’ll look at further examples in later posts.
Secure Token Storage
I created a very simple Token Storage class that uses the Node keytar component to load / save / delete tokens against the Account Name with which the user is logged onto their desktop PC:
Our Authenticator class calls the Token Storage class after the following events:
- When the Desktop App Starts, to load tokens
- After the Authorization Code Grant, to save tokens
- After the Refresh Token Grant, to update tokens
- When the user Logs Out, to remove tokens
Where Are We?
The main benefit of a Private URI Scheme is around deployment and administration concerns, and it is the desktop option I prefer.
Our Cross Platform Desktop App has also been updated to use Secure Token Storage for the platforms we deploy to.