Previously we defined our Mobile App Requirements, but first we will implement a Desktop Code Sample, since it is tricky, but has value for many companies.
Desktop OAuth Requirements
Let’s adapt our mobile requirements slightly for the Desktop case:
- Easy to deploy / manage in Corporate Environments
- Best Login Usability for End Users
- Short Lived Access Tokens with Silent Token Renewal
- Our solution must Pass Security Reviews
- We want to avoid writing any Complex Security Code
OAuth Desktop Apps Background
Identity Model have some good technical resources for desktop apps, and the below video is a good introduction to best practice:
The Desktop Code Sample will get the below components and endpoints talking to each other, in the same manner as for our earlier SPA Sample:
Desktop App Technology
The most important aspect is understanding what we want to code. Once we have clarified our requirements we could deliver them in any desktop technology, such as WPF Apps built in C#.
AppAuth Security Library
We will use the Google AppAuth-JS Library to implement security aspects. We would expect this library to evolve in future and get many new features for free.
Technically we will use the Authorization Code Flow with PKCE Handling, and we will look at what this involves later.
We will follow the same technical approach as the AppAuth-JS Basic Sample but will go further to implement a more complete Corporate Desktop App.
If you are using C# I would recommend the Certified OIDC Client 2 Library, which reduces Login and Token handling to a few lines of code:
Desktop App Corporate Theme
Our Desktop App will have exactly the same (trivially simple) functionality as our SPA, with navigation between two pages.
Runs on Multiple Platforms
Our Desktop App will run on Windows:
Our Desktop App will also run on Mac OS:
Our Desktop App can also be run on Linux if needed:
Many companies use a mix of Windows and Mac OS desktops these days, so supporting both may be what your customers prefer.
We’ll Avoid Web View Logins
A few years ago it was standard for Desktop Apps to do logins via a web view. For example, in a C# application you might write code like this:
The Login User Experience then used a popup window hosting a web view browser control, which looked integrated from a UX viewpoint:
The popup window would then capture the login response data from the web view using an ‘Out of Browser URL‘ such as urn:ietf:wg:oauth:2.0:oob.
Although the above code works, it always had usability problems, since in effect the web view runs a private browser session:
- Cookies that enable Single Sign On across apps are not remembered
- Browser features such as Password Autofill also do not work
We’ll Follow Security Best Practice
Part of the best practice for Native Apps is for the screen where credentials are handled (such as password values) to be external to the app.
Authorization Servers are recommended to look at the User Agent and block login requests from web views. Google logins already do this:
This Auth0 Article covers the current Desktop Apps best practice – in particular you must use the User’s System Browser to handle logins.
Which Authorization Response Handling Option?
If we look at the OAuth Standards for Native Apps, there are 3 potential redirect options for receiving the login result in a desktop app:
Usage is summarized below, and we will explore both options that work for a desktop app, to see which has fewest overall issues:
|Option||Example Redirect URI||Used By||Prerequisites|
|Private URI Scheme||com.mycompany:/desktopapp||Mobile or desktop apps||A custom URI scheme must be configured when the app is installed|
|Claimed HTTPS Scheme||https://web.mycompany.com/desktopapp||Mobile apps||iOS and Android have support for claiming HTTPS URLs and invoking a registered mobile app|
|Loopback Interface||http://127.0.0.1:8000||Desktop apps||End User PCs must be able to run a local web server and listen on a loopback URL|
The AppAuth Code Sample
We know we have to use the System Browser, so let’s see this working in the AppAuth Electron Sample. I used the following commands:
- git clone https://github.com/googlesamples/appauth-js-electron-sample
- cd appauth-js-electron-sample
- npm install
- npm run compile
- npm start
Note that on my Windows PC I had to edit the package.json start command as follows for this to work:
We then see a desktop app that looks like this, and we can click Sign In to invoke an OAuth login on the system browser:
When Sign In is clicked the System Browser is opened, in a new instance of the default browser (or a new tab if the browser is already running).
The user may already be logged in, perhaps for our SPA, but if not then the user will be prompted to login:
The Desktop App supplies a ‘loopback’ value of http://127.0.0.1:8000 as the OAuth Redirect URI, and the desktop app listens on this URL for a login result.
When the login completes, the browser returns to the below URL and the desktop app receives the response details. The desktop app then swaps the returned Authorization Code for tokens, after which it can call APIs.
This works OK from a technical viewpoint, but for most companies it may have a few problems, discussed next.
Potential Problems for Company Desktop Apps
Problem 1: If a busy user accidentally closes the Login Tab in the System Browser, we need to make sure the user can retry.
Problem 2: After login the display may not please Business + UX stakeholders, who are likely to want to show more polished output.
Problem 3: You need to ensure that listening on the loopback URL would not be blocked by Corporate IT Policies of your customers.
We will do some work to mitigate these risks, since for a Real Corporate App we would need to get past all blocking issues, satisfy QA and Business / UX stakeholders, and release to production.
Login UX Ideas from Third Party Apps
We will borrow some Login User Experience ideas from existing third party apps, which deal with some of the above problems.
The Instagram Desktop App appears to run in the browser but is a desktop app with additional access to the user’s file system:
During login the following screen is shown, so that the user can always retry if the login on the system browser is accidentally dismissed:
After login on the system browser, the user is left in the Instagram web app rather than on a blank browser page:
GitHub Desktop allows sign in via the System Browser:
It uses a Private URI Scheme so that the System Browser can invoke the Desktop App and send it the Authorization Code when a login completes:
The Private URI Scheme is registered by the GitHub install program, so that x-github-client maps to an executable path that the OS knows how to invoke.
On the usability side of things, the Private URI Scheme looks a little more integrated and automatically brings the desktop app to the foreground, though the user is left with a blank page after login.
Where Are We?
On the security side we know that we will do logins on the System Browser, using AppAuth-JS libraries and the Authorization Code Flow (PKCE).
We still have some open questions, but we will start with a Code Sample that uses the Loopback Interface, and aim to deliver good Reliability + Usability.