Skip to content

v1.3.5 - Google Sign-In Works

Choose a tag to compare

@Thuong180702 Thuong180702 released this 09 Aug 16:21
· 3 commits to main since this release

🚀 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.0 instead of 537.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 shims Notification and 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.chrome is 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 resolve electron and a few builtins, so that threw module not found and 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 notihub

Method 2: npm (CLI companion)

npm install -g @thuong180702/notihub

Method 3: DMG Installer

  1. Download notihub-v1.3.5-mac.dmg below.
  2. Double click to open the DMG, then drag notihub.app into Applications.

Method 4: Direct Zip Download

  1. Download notihub-v1.3.5-mac.zip.
  2. Unzip and move notihub.app into /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.app

Updates Notihub installs itself are never quarantined, so this is only needed for a fresh manual install.