v1.3.5 - Google Sign-In Works
🚀 Notihub v1.3.5
Release Title: v1.3.5 - Google Sign-In Works
🎯 What this fixes
Signing in with Google works again. If Gmail — or any service you sign into with a Google account — answered with "Couldn't sign you in / This browser or app may not be secure", this release fixes it.
🔍 It was never the User-Agent
Every previous attempt at this was aimed at the User-Agent. v1.3.1 stripped the app's name from it, v1.3.2 corrected the tokens, and v1.3.3 established the UA was not what sent sign-ins to the browser. All of that was necessary. None of it was sufficient, and this release explains why.
The block turns out to be reproducible without an account at all: it never fires on page load, only on submitting the identifier. That made it testable, so each theory was measured instead of argued:
| Configuration | Result |
|---|---|
| Correct Chrome UA, no Electron token | 🚫 blocked |
…plus Sec-CH-UA client hints matching the UA |
🚫 blocked |
…plus navigator.userAgentData listing "Google Chrome" |
🚫 blocked |
…plus a populated window.chrome |
✅ signs in |
Electron leaves window.chrome an empty object. A real Chrome exposes chrome.app, chrome.runtime, chrome.csi and chrome.loadTimes on it, and that is what Google's sign-in reads. Nothing about the User-Agent was ever going to change that answer.
Re-run to be sure: window.chrome alone is both necessary and sufficient — the client hints contribute nothing and were removed rather than shipped as decoration.
Checked and ruled out along the way:
- The Ferdium bug. The largest app in this position merged a fix for a UA generated as
AppleWebKit/537.36.0instead of537.36. Notihub's UA was already correct. - An outdated Chrome version. Chrome stable is 151; Notihub advertises 150. One major behind is what a great many real users run.
🛠️ What changed
src/chrome-surface.js holds the object, injected into the page's main world before its own scripts run, from two places:
- the sign-in popup, via a new
popup-preload.js— deliberately not the main preload, which shimsNotificationand polls the title; doing either in the window Google is inspecting would add back a difference from a stock Chrome - the service view, because adding Gmail redirects the view itself to
accounts.google.com
✅ How this was verified
- A credential-free reproduction. Submitting any address triggers the verdict, so the whole matrix ran on
test@example.com. No account and no password were involved in finding or fixing this. - End to end, with the shipped files under the real sandbox: without the preload,
window.chromeis empty and Google refuses; with it, the keys are present and sign-in proceeds. - A regression this caught in itself. The first attempt had the preloads
require()the shared module. Sandboxed preloads only resolveelectronand a few builtins, so that threwmodule not foundand killed the entire preload — silently disabling the Notification shim, the app's whole purpose. Each preload now inlines the string, and a test asserts the copies match byte for byte. npm test: 80 reported checks.
⚠️ Honest limits
This works by filling in a gap Electron leaves, not by hiding what the app is — the User-Agent still claims nothing untrue. But the check it satisfies is Google's embedded-webview policy, which exists because an embedded browser can read a password field. Two consequences worth stating plainly:
- This can break again if Google changes what it inspects. The reproduction is credential-free and takes a minute, so diagnosing the next round will be fast.
- The durable answer for a notification hub is not to embed a Google sign-in at all: OAuth through the system browser plus the Gmail API would tell the app about new mail without a password ever meeting an embedded page. That is a larger change, and Google's own guidance offers no desktop equivalent today.
📦 Download Assets & Checksums
| Asset File | Format | SHA-256 Checksum |
|---|---|---|
notihub-v1.3.5-mac.dmg |
Native macOS DMG Installer | 6f020b4e00018c20fe745fd509c3e3019febc98500d7b889a2e2bf70b86128d3 |
notihub-v1.3.5-mac.zip |
Portable Zip Archive | aa8acdb572e146090e5bd7a03d2ddd548acad88bc37f3e2e2af2a5f657c6283f |
These match what GitHub publishes as the digest field on each asset — the same value src/updater.js verifies the download against before installing.
📥 Installation Options
Method 1: Homebrew (Recommended)
brew tap thuong180702/notihub
brew install --cask notihubMethod 2: npm (CLI companion)
npm install -g @thuong180702/notihubMethod 3: DMG Installer
- Download
notihub-v1.3.5-mac.dmgbelow. - Double click to open the DMG, then drag
notihub.appintoApplications.
Method 4: Direct Zip Download
- Download
notihub-v1.3.5-mac.zip. - Unzip and move
notihub.appinto/Applications.
⬆️ Upgrading
Use Settings → Download & Install. No bundle identifier or data-directory change, so existing logins and notification permissions stay intact.
⚠️ Gatekeeper Notice
Notihub is signed ad-hoc, not notarized by Apple, so macOS will refuse a manual install with "notihub is damaged and can't be opened". This isn't corruption — it's Gatekeeper rejecting an unnotarized app. Clear the quarantine flag once:
xattr -dr com.apple.quarantine /Applications/notihub.appUpdates Notihub installs itself are never quarantined, so this is only needed for a fresh manual install.