Skip to content
AtlasDocs
Sign inGet started
Updated Aug 04, 2026

Electron Example

Same SDK, running from the Electron main process. The renderer is sandboxed - contextIsolation: true, nodeIntegration: false, sandbox: true - and only sees the narrow IPC surface in preload.js.

Architecture

  • Main: Atlas lives here. Atlas.dll is loaded once at startup. Sensitive handlers all gate on atlas.Data.IsAuthenticated().
  • Preload: contextBridge exposes a handful of ipcRenderer.invoke wrappers to the renderer. The renderer cannot see Node, the filesystem, or the Atlas module.
  • Renderer: a normal web page that calls window.atlas.login(key). It can ask for a session card; it can't drive the SDK.

Main process

The binding probes process.resourcesPath first, so a packaged app finds Atlas.dll in resources/ with no configuration. In dev it falls back to the SDK folder. Set ATLAS_DLL_PATH only to override.

JavaScript
// main.js - the DLL loads once, when the module is required.
const atlas = require('@atlassecurity/auth');
atlas.API_KEY = process.env.ATLAS_KEY;
atlas.Startup();

Preload (the only IPC the renderer sees)

Four handlers are enough for the typical login → welcome flow. Add more as your features demand - but always map them through ipcMain.handle, never directly through webContents.

JavaScript
// preload.js - narrow IPC surface. nodeIntegration: false.
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('atlas', {
login: (key) => ipcRenderer.invoke('atlas:login', key),
logout: () => ipcRenderer.invoke('atlas:logout'),
recheck: () => ipcRenderer.invoke('atlas:recheck'),
data: () => ipcRenderer.invoke('atlas:data'),
});
JavaScript
// main.js - handlers re-check atlas.Data.IsAuthenticated() before
// touching the SDK. The renderer can ask; it cannot drive the SDK.
const { ipcMain } = require('electron');
ipcMain.handle('atlas:login', async (_evt, key) => {
if (!atlas.License.Login(key)) {
return { ok: false, error: atlas.Data.GetErrorMessage() };
}
return { ok: true };
});
ipcMain.handle('atlas:logout', async () => { atlas.Logout(); return true; });
ipcMain.handle('atlas:recheck', async () => atlas.Network.CheckAuthentication());
ipcMain.handle('atlas:data', async () => ({
license: atlas.Data.GetLicense(),
expiry: atlas.Data.GetExpiry(),
days: atlas.Data.GetDaysRemaining(),
user: atlas.Data.GetUsername(),
hwid: atlas.Data.GetHWID(),
ip: atlas.Data.GetIP(),
level: atlas.Data.GetLevel(),
authed: atlas.Data.IsAuthenticated(),
}));

Packaging with electron-packager

electron-packager produces the distributable. The script copies Atlas.dll into process.resourcesPath at build time so the runtime probe finds it without any extra config. koffi's native addon can't load from inside app.asar, so koffi and the SDK folder are unpacked with asar.unpackDir. The example installs the SDK under the alias atlas-authentication; name the unpacked folders after your own dependency names.

JSON
{
"scripts": {
"build:exe": "electron-packager . \"Atlas Auth Electron Example\" --platform=win32 --arch=x64 --out=\"../../../../- Builds\" --overwrite --asar.unpackDir=\"node_modules/{koffi,atlas-authentication}\" --extra-resource=\"../Atlas SDK/Atlas.dll\""
}
}
Text
Output layout
# Output from npm run build:exe
- Builds/
└── Atlas Auth Electron Example-win32-x64/
├── Atlas Auth Electron Example.exe ← whitelist THIS hash
└── resources/
├── Atlas.dll ← loaded via process.resourcesPath
├── app.asar ← your JavaScript, not covered by the exe hash
└── app.asar.unpacked/ ← koffi and the SDK, unpacked

After it builds

Whitelist the hash of the packaged Atlas Auth Electron Example.exe (your packaged exe), not Electron.exe or node.exe. See Executable Hash Whitelist.

Debugger caveat

Don't run the main process under an inspector: --inspect, VS Code JS debugger, or Chrome DevTools on main. Renderer DevTools are fine. An attached inspector counts as tampering and can queue a ban against the license or HWID.