Living in the UK, it is almost impossible not to be tempted to try the new challenger banks such as Revolut, Starling and Monzo. I am currently using Revolut as my main bank account and felt the need to access it from my computer.
Alas, Revolut does not offer a web app and it does not seem to be in their pipeline, so I went ahead and started building a small web app for my personal use.
I quickly found that I could not hit their API in a browser, preflights requests were blocked due to a lack of CORS headers.
So to bypass it I started looking at ElectronJS, making the requests using NodeJS and bridging the results using Electron IPC mechanism.
It was too cumbersome, so I started checking at another way of making http requests from the renderer side without obeying CORS. One way would be to disable web securities in the chrome flags, but since the app would be to access my bank, it wouldn't be a good idea, so I opted to enable node integration, and used Axios with node's http adapter. It works seamlessly albeit not being able anymore to see requests in the devtools.
For security reasons, I wanted to use SSL certificate pinning but it turned out Axios does not provide this option out of the box so I submitted a PR to add it, this way NodeJS blocks outgoing http requests if the fingerprint of the certificate does not match our pinned fingerprint, preventing proxy eavesdropping and man-in-the-middle attack.
Later on I faced a common UI problem, since the list of my transactions was large, containing 2000+ items (hey please don't judge :p)
React was taking a long time rendering it all at once.
I did not want to use react-virtualized, mostly because I had poor experiences using it in the past and that it would break searching in the DOM for text, so I opted to manually delay the rendering of items in the list using a react hook, and to reduce memory footprint and improve scrolling performance, I chose to use the WebComponent
<virtual-scroller>
since Electron gives us the ability to enable experimental blink flags. The main drawback of using that WebComponent is that list items must be
display: block
and since I am a big fan of display: flex
everywhere, I had to style the old fashion way again ...For the navigation, I decided not to use react-router as it is a rather simple app. Electron does not show URL anyway, so I shouldn't have to deal with routes. Instead, I used a combination of localStorage and React Context API, and was satisfied of the outcome.
For animations, I used React-Lottie to have lightweight, high frame rate, JS/SVG animations.
Most of the application were made with React using Styled Components.
To render the cards, I had to absolute position text elements on a div with rounded corners and pick the same font as credit cards use: OCRA10. The end result is pretty close to what the mobile app displays.
I hope you fellow hackers enjoyed the tips and tricks to bypass CORS with Electron, be sure to check out the repository!