Desktop Code Sample Overview

Background

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:

Components

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

We will use Cross Platform Javascript Technologies and implement an Electron App (note that Visual Studio Code itself is cross platform and built with Electron).

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.

Other Languages?

My samples use Javascript based technologies, but my main goal is guidance, and I hope you can easily understand concepts and implement them in any programming language.

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

As discussed in This Earlier Post, our app’s theme is meant to simulate use of Monetary Corporate Assets that need securing.

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 ReliabilityUsability.

Next Steps