We have Reviewed our SPA Solution against requirements. Before getting into Mobile Tech we will switch to an SSL / TLS local developer setup.
As part of this I also want to introduce some useful cross platform tools that can improve our troubleshooting capabilities.
X509 Certificate Pipeline
It is quite common for companies to have a Continuous Delivery pipeline something like the following, and to issue different types of SSL Certificate:
|Environment||Type of X509 Certificate|
|Development||None / Self Signed|
|Staging||Third Party Issued|
|Production||Third Party Issued|
Production Certificates are issued by a Root Authority such as Verisign, and cost money, so cheaper certificates may be used for Development and Test Environments.
The Self Signed option is usually the most practical option for developers, since it does not require money or a dependency on IT departments.
Why SSL for Developers?
Some Authorization Servers, such as Azure Active Directory, will require us to use HTTPS URLs for our SPA, so when working with OAuth technologies, SSL is part of the fabric.
More importantly though, we want to see real world traffic from browser and mobile clients to our API, so that we can identify any SSL issues early in the pipeline, in order to save costs.
SPA Code Sample with SSL
A 4th web sample that runs under SSL is available here, and can be cloned in a similar manner to previous samples:
- git clone https://github.com/garyarcher36/authguidance.websample4
Code Sample SSL Settings
The updated code sample now runs over an SSL port and defaults to 443, since my preference is to use the standard ‘firewall friendly’ port.
If required, change the configuration by just editing the config files. You can use a custom port such as https://api.mycompany.com:3000 if you prefer:
You will also need to change Okta URLs under Applications / Basic SPA and API / Trusted Origins to use an https value for the web domain:
Generated Certificate Files
The sample includes some Certificate Files that can be used directly, and also some scripts for regenerating them with different parameters if required:
We will use the below certificates on a Developer PC so that the setup is closer to a production setup (though obviously it is not secure to use self signed certificates like this for production servers).
|mycompany.ca.pem||Root Certificate Public Key|
|mycompany.ssl.pem||SSL Certificate Public Key|
|mycompany.ssl.key||SSL Certificate Private Key|
We have created our own Root Certification Authority, which is just used to issue our SSL certificate:
The SSL Certificate we have created is a ‘Wildcard Certificate‘ which will be used by our Node Server to handle both Web and API requests, so it is valid for both domains:
API Usage of our SSL Certificate
When the sample runs, the API reads the Certificate from disk and uses it to listen on an SSL connection. Reading files from disk seems to be standard NodeJS practice, since it does not use certificate stores:
Browser Trust of our SSL Root Certificate
In order to prevent browser warnings, our Root Certificate public key must be trusted. On Windows we do this by importing its PEM file to the Trusted Root Certification Authorities for the Local Computer store:
On Mac OS we need to import the PEM file into the Keychain Access application under System / Certificates, then set the certificate to the Always Trust level:
On my Fedora Linux system I use the Firefox browser and added the Root CA to the Firefox store, under Preferences/ Advanced / Certificates / View Certificates / Authorities / Import:
Running the Sample over SSL
We can now run our sample over SSL and verify that there are no browser errors or warnings with our SSL setup:
The Google Chrome browser has some useful SSL tools under Main Menu / More Tools / Developer Tools / Security which allows us to view SSL strength details:
Note that Chrome requires the browser’s exact domain name to be present in one of the SSL Certificate’s Subject Alternative Names.
SSL Debugging – Charles Settings
On Windows it is common to use the Fiddler tool to look at HTTPS Traffic. However, the Charles HTTP Debugger is Cross Platform and we will use it later for Mobile Development, so let’s take a closer look.
After installing Charles, export the Charles Root Certificate and then follow the above Browser Trust process again, so that you do not experience any browser warnings when debugging.
Next we need to tell Charles which SSL domains it should decrypt requests for, under the Proxy / SSL Proxying Settings menu item:
Operating System Proxy Settings
On Mac OS we need to edit the network connection in order to proxy requests via Charles, and we will use this for mobile HTTPS debugging later:
On my Fedora Linux system I needed to set Firefox Proxy details under Preferences / Network Proxy in order to capture browser requests:
For other types of request, such as those from APIs or desktop apps, I needed to browse to use Fedora’s (Gnome) Settings tool, then navigate to Network / Network Proxy:
Capturing our SSL Requests
Now that the Operating System setup is done, we can view OAuth messages used for our SPA’s Implicit Flow:
We can also capture requests from our API to Okta, if we start our API via npm run httpDebug. This sets an HTTPS_PROXY environment variable to http://127.0.0.1:8888, which is the address on which Charles listens.
However, we will find that we now run into SSL trust issues, since NodeJS will not use the Browser Trust we configured.
Disabling Root Certificate Checks
A quick and dirty hack to get API SSL debugging working is to completely disable SSL root checks by setting this environment variable:
- cross-env NODE_TLS_REJECT_UNAUTHORIZED=0
Although this will get SSL debugging working for API requests to Okta, it is clearly not a good solution.
Certificate Root Replacement
Tools such as Charles and Fiddler work by replacing the root of SSL addresses you browse to:
Some corporate networks will use a similar technique for Outbound SSL Firewall Filters:
Tools for Testing SSL Connections
I use the following two tools to troubleshoot SSL connections. Both of these are preinstalled on Mac OS and Linux, whereas for Windows you can download EXEs from the below links:
- curl allows us to easily send a standalone HTTPS request
- openssl allows us to easily troubleshoot SSL connects
The below commands are useful for troubleshooting SSL server trust issues from a client viewpoint:
- curl https://dev-843469.oktapreview.com/.well-known/openid-configuration
- openssl s_client -connect dev-843469.oktapreview.com:443
By default, when debugging API introspection requests you will get SSL trust warnings as below, due to self signed certificates in the trust chain:
White Listing Trusted Root CAs
On my work PC I created a Certificate Bundle File containing the following root certificate public keys:
- Our Company Root
- The Charles Debugger’s Root
- The Fiddler Debugger’s Root
- The Corporate Firewall Filter Root
I then saved these to a Certificate Bundle File that needs to be in the following PEM format:
If you use Windows tools to export certificates, they may be in DER format, in which case you will need to first translate to PEM format as follows:
- openssl x509 -inform der -in charlesRoot.ca.cer -out charlesRoot.ca.pem
Re-Testing our SSL Connections
We can now re-run our troubleshooting commands, specifying an additional Root CA file to trust, to fix the Certificate Trust problem:
- curl –cacert trusted.ca.pem https://dev-843469.oktapreview.com/.well-known/openid-configuration
- openssl s_client -CAfile trusted.ca.pem -connect dev-843469.oktapreview.com:443
In addition, we can capture requests in Charles / Fiddler by setting an HTTPS_PROXY environment variable if required:
Making the Whitelist Permanent
One option is to specify the path to trusted roots in the package.json file, using the NODE_EXTRA_CA_CERTS environment variable:
In this case however, a permanent Environment Variable for my development user worked better, so that it applies to all projects:
Note that on Mac OS and Linux, we set the environment variable in our .bash_profile file. When we run our API we then use sudo -E option to preserve the environment:
On Fedora Linux I configured root trust by copying our trusted.ca.pem file to /etc/pki/ca-trust/source/anchors, then running sudo update-ca-trust.
Final SSL Debugging
We now have a fully working SSL developer setup where we can capture both SPA and API requests. Our setup is production like and does not involve any code hacks:
Where Are We?
SSL issues can be a little painful but, if we take control of technical tools, we empower ourselves, resolve more infrastructure issues early and are less likely to run into unexpected production issues later.