Offline auth with Electron + SQLite + React

Offline auth with Electron + SQLite + React
Photo by Caspar Camille Rubin / Unsplash

In an increasingly digital world, the need for secure and robust authentication systems is paramount. Whether you're building a desktop application, a mobile app, or a web platform, the ability to authenticate users reliably and securely is a fundamental requirement. While online authentication methods are well-established and widely adopted, there are situations where offline authentication becomes essential. This is particularly true for desktop applications, where internet connectivity is not always guaranteed.

In this article, we dive into the world of "Offline Authentication" and explore a powerful combination of technologies to achieve this goal: Electron, SQLite, and React. By leveraging the capabilities of Electron, a framework for building cross-platform desktop applications, and harnessing the flexibility of SQLite, a lightweight and embedded database engine, we'll create a robust offline authentication system. To top it off, we'll enhance the user experience by incorporating the user-friendly React library for building the application's front end.

Offline authentication isn't just about enabling access when the internet is down; it's about providing users with a seamless and secure experience, even when disconnected. Whether you're developing a stand-alone desktop application or a part of a broader software ecosystem, the techniques and principles we'll explore here will empower you to create reliable offline authentication solutions that protect user data and ensure a smooth user experience.

Let's embark on this journey to learn how to implement offline authentication with Electron, SQLite, and React, and unlock new possibilities for your desktop applications.

Login and Signup pages

First, we will use the last Electron post to start this new one. You can clone the repository on Github:

GitHub - tuliocll/electron-react-sqlite-todo: A TODO app with Auth built with Electron, ReactJS and SQLite
A TODO app with Auth built with Electron, ReactJS and SQLite - GitHub - tuliocll/electron-react-sqlite-todo: A TODO app with Auth built with Electron, ReactJS and SQLite

Let's start with our business rules for this new feature. We want to create a register and login pages and check if the user is authenticated before accessing some resources (pages).

Simple diagram

We need to create the users table on SQLite database, so open the database on your favorite tool to manage SQLite databases and create the new table:

CREATE TABLE "user" (
	"id"	INTEGER,
	"username"	TEXT,
	"password_hash"	TEXT,
	"status"	INTEGER,
	PRIMARY KEY("id" AUTOINCREMENT)
);

With the new table created it's time to create the Typescript types for this entity. Create a new folder called types in the src/ folder and create a User.d.ts file with this content:

declare type User = {
  id?: number;
  username: string;
  password_hash: Buffer;
  status: number;
};

declare type Auth = {
  username: string;
  password: string;
};

This declaration permits us to use it on both processes, main and render.

To help us with the security, let's use the safeStorage module from electron core. This package lets us encrypt and decrypt data and protects it from being accessed by other applications using the native OS resources (Keychain and password manager for example).

Create a new util inside utils folder on the main process side called encrypt.ts and put this code:

import { safeStorage } from 'electron';

export function hashText(text: string) {
  try {
    if (!safeStorage.isEncryptionAvailable()) {
      return false;
    }

    return safeStorage.encryptString(text);
  } catch (err) {
    return false;
  }
}

export function decriptText(text: Buffer) {
  try {
    if (!safeStorage.isEncryptionAvailable()) {
      return false;
    }

    return safeStorage.decryptString(text);
  } catch (err) {
    return false;
  }
}

This code verifies if the encryption is available and uses it.