Step 1: Add Domains to your PC
First go to the hosts file on your local PC, which will exist at one of these locations:
|Mac OS / Linux||/etc/hosts|
Add entries as follows to represent our domains:
- 127.0.0.1 web.mycompany.com
- 127.0.0.1 api.mycompany.com
Step 2: Use Okta as an Authorization Server
Go to https://developer.okta.com and sign up to get a developer account, after which you will receive an email to activate your account.
You will then get your own Authorization Server, which you can log into at an Admin URL such as this: https://dev-843469-admin.oktapreview.com.
Once logged in, browse to API / Authorization Servers and view the default item that has been automatically created:
The above URL is what we will use in our Code Sample, and in my case the value is https://dev-843469.oktapreview.com/oauth2/default.
Step 3: Register OAuth Applications
In Okta we must add trust entries so that our applications can act as OAuth Clients and call the Authorization Server.
First register a Service Application for our API and note that the key OAuth settings are the client_id and client_secret:
Next register a Native Application and note that the key OAuth settings are the client_id and the redirect_uris:
About Loopback Redirect URIs
According to OAuth Standards for Native Apps, Authorization Servers should allow a Single Loopback URL such as http://127.0.0.1 to be registered, then accept redirect URLs from any port at runtime.
At the time of writing this seems to be a Future Okta Backlog Item so I had to register all possible URLs that we will use for our Desktop Code Sample.
Step 4: Configure Session Times
In Okta, go to API / Authorization Servers / Default / Access Policies / Default Policy Rule / Edit and set details as follows:
- The user session is represented by the refresh token
- Refresh tokens last for 12 hours
- Access tokens are short lived and expire every 30 minutes
- The refresh token will be used to silently renew access tokens
Step 5: Download Code from GitHub
The project is available here, consisting of a UI and API component. It can be downloaded / cloned to your local PC with this command:
- git clone https://github.com/garyarcher36/authguidance.desktopsample1
Step 6: View Code in an IDE
I use Visual Studio Code on Windows, Mac OS and Fedora Linux, since it is cross platform and lightweight.
Select ‘Open Folder’ and browse to the AuthGuidance.DesktopSample1 folder, to view the code for both UI and API with syntax coloring:
Step 7: Update Configuration
Both the Desktop App and API have configuration files. In a real world app these would typically be delivered by your Continuous Delivery process.
For the Desktop App you will need to update the configuration to match your Authorization Server’s Base URL and OAuth Client Id:
Note that our Desktop Sample specifies the following details that differ from that of our SPA:
|Loopback Port Range||Corresponds to our Okta registered URIs|
|Login Success Page||Where to send the browser after a successful login|
|Login Error Page||Where to send the browser after a failed login|
|Offline Access Scope||A scope needed to get refresh tokens|
For the API you will need to update the configuration to match your OAuth Server Base URL and the API’s Client Id + Client Secret:
Step 8: Install Node JS if Required
Go to the Node JS Web Site and run the installer for your operating system.
Step 9: Install Desktop and API Dependencies
From both the desktopapp and api folders run ‘npm install’, which will download dependencies, including Electron:
Step 10: Configure SSL for the Code Sample
Next install the below root certificate used by the API to your operating system, as described in Root Certificate Deployment.
Step 11: Start the API
From the basicapi folder run ‘npm start’ to run the API, which will listen on port 443. If other system components are listening on port 443, such as IIS or Apache, stop them temporarily.
Note that on Windows you may need to use an administrator user and on Mac OS or Linux you will need to run this command:
- sudo -E npm start
Browse to the following URL to get data and verify that you get an Unauthorized response:
In production you would run your API as a low privilege user, and there are various ways to enable this. Our objective though is just to enable real world HTTPS traffic on a developer PC.
Use Alternative Ports if you prefer
My preference is to use the Standard SSL Port 443 allowed by company firewalls. If you prefer to use an alternative port such as 3000, change the host names in Okta and the above configuration files:
Step 12: Build the Desktop App
From the desktopapp folder run ‘npm run build’ to build the Electron App:
Step 13: Run the Desktop App
From the desktopapp folder run ‘npm start’ to run the Electron App:
This will invoke the Electron executable due to the following command in the package.json file:
About Electron Executables
When running ‘npm start‘ we can use operating system tools to see that a couple of instances of the Electron executable are running, which point to our application files on disk:
We would build the Electron app into an executable before deploying to real users and we can do this with ‘npm run pack‘:
You can then run the type of deployed executable that would be delivered to your end users:
Step 14. Get Node JS SSL Working
You are likely to receive SSL errors when the Desktop App calls the API, due to untrusted root certificates. As a quick fix you can edit package.json for the API and Desktop App to disable Node SSL errors:
- cross-env NODE_TLS_REJECT_UNAUTHORIZED=0
The API’s package.json will then look like this:
The Desktop App’s package.json will then look like this:
Once you are up and running, a less hacky option is to Add Root Certificates to Node JS via the NODE_EXTRA_CA_CERTS environment variable.
Step 15: Run a Desktop App Login
The first Electron screen we will see is the login screen. We need to show this every time we redirect the user to the system browser to log in:
When Sign In is clicked we give the user some visual progress in the Desktop App:
The System Browser is invoked and the user prompted to login to Okta. Note that browser features such as Password Autofill work nicely:
However, rather than logging in, close the browser on the first attempt. We will ensure that our Desktop App copes with this resiliently.
Next click Sign In again, and login to the second browser instance. After login the System Browser is redirected to a custom company web page:
The Electron App then receives the login result, gets tokens and can securely interact with its API and render the resulting data.
Step 16: Run a User Session
We can then use the UI to simulate session related events that may occur in your desktop apps. We will drill into these operations in the next blog post:
- Access token expiry
- Refresh token expiry
- Explicit user logout
Note that our Desktop App now has a Long Lived Credential and we need to think about how our UI will securely deal with it.
At the time of writing the Desktop App only stores tokens in memory, so that if we use the Electron reload options in the default menu, tokens are lost and the user has to log in again:
Where Are We?
We have used our existing SPA to quickly build a Desktop App using Electron, which runs on all the main platforms.
We used the AppAuth-JS library to implement the Recommended OAuth Flow for a Desktop App – and zero changes were needed to our API’s code.
For the next post we will drill into OAuth messages for the Desktop Sample, which includes use of Refresh Tokens and PKCE Handling.