privacyApril 20, 20267 min read

User-Owned OAuth: The Privacy Pattern Most AI Apps Skip

Why NovaKit doesn't ship developer OAuth client IDs for Google Drive or Dropbox sync — and why you should prefer apps that make you register your own OAuth credentials.

TL;DR

  • Most apps that "connect to Google Drive" bake in a single OAuth client ID the vendor registered. Every user authenticates against that one client, so the vendor appears in your Google account's list of connected apps and — depending on the integration — can route data through their servers.
  • NovaKit's BYOS sync inverts this. For Google Drive and Dropbox, you register your own OAuth app in your own developer console, paste the client ID into NovaKit, and authenticate against your own client. NovaKit never appears in your account's connected apps list.
  • Trade-off: ~5 minutes of one-time setup in exchange for a genuinely zero-trust integration.
  • Works for any BYOK-style product. If you care about minimizing the blast radius of a vendor compromise, prefer apps that support this pattern.

The default OAuth model

When you click "Connect Google Drive" in almost any SaaS app, this is what happens behind the scenes:

  1. The vendor (say, acme-ai.com) registered a Google OAuth client months or years ago. It has a client ID like 12345-abcde.apps.googleusercontent.com.
  2. You get redirected to accounts.google.com/o/oauth2/v2/auth with client_id=12345-abcde....
  3. Google shows the consent screen: "acme-ai.com wants access to your Google Drive."
  4. You approve, Google redirects back to acme-ai.com/api/oauth/google/callback with a code.
  5. acme-ai.com exchanges the code for an access token — usually on its own backend.

The access token now sits on acme-ai's servers. When you use the "sync to Drive" feature, acme-ai's backend makes the Drive API calls and either streams the results back to your browser or stores the synced file on its own infrastructure first.

This is the default because it's easiest to build. But it has two properties that matter for privacy:

  • You show up in Google as having authorized acme-ai.com. If acme-ai gets breached, the attacker inherits a fleet of Drive-authorized tokens. Google's "Third-party apps with account access" page lists the vendor, not a per-user app — so revoking access means breaking every user's integration at once.
  • The vendor's backend is in the data path. Depending on how the feature is implemented, the vendor may hold your refresh token, your access token, or — in the worst case — a cached copy of the data that passed through during sync.

None of this is malicious. It's just the default integration pattern.

What "user-owned OAuth" looks like

NovaKit's version of the flow for Google Drive or Dropbox looks like this:

  1. You go to Google Cloud Console, create a new OAuth client, and paste the client ID into NovaKit → Settings → Sync.
  2. NovaKit redirects you to accounts.google.com/o/oauth2/v2/auth with your own client_id.
  3. Google shows: "your-personal-novakit-app wants access to your Google Drive." (The app name is whatever you chose in your own Google project.)
  4. You approve, Google redirects back to NovaKit's callback route. NovaKit exchanges the code for an access token — still on the client side, using PKCE.
  5. The access token is stored on your device, encrypted with your vault passphrase.

The Drive API calls during sync then happen directly from your browser to Google's servers. NovaKit's backend is not in the loop at all.

A few properties fall out of this:

  • Your Google "Third-party apps" page lists your own OAuth client, not NovaKit. If a future NovaKit release ever got compromised, you would revoke your client — scoped to just your own authorization — not a shared client that every NovaKit user depends on.
  • The only place your access token exists is in your browser, encrypted. There's no vendor server that can be breached to drop a token cache.
  • The Drive API calls are subject to your Google account's rate limits, not a shared quota across every user of a SaaS vendor.

It's the same end-user experience (click "Connect Google Drive," see a consent screen, start syncing), but the trust boundary moves from "the vendor's backend" to "your own browser."

Why most apps don't do this

Three reasons, in descending order of importance:

  1. Friction. Users hate one-time setup steps. "Go register your own OAuth app" is a dropout moment on signup flows. Vendors optimize for conversion, not for the 5% of users who care deeply about token hygiene.
  2. Cost of support. "My OAuth isn't working" is suddenly a user problem, and the vendor can't debug with their own client ID. Support tickets multiply.
  3. Feature lock-in. If the vendor's backend proxies Drive API calls, they can cache, batch, enrich, and bill per-request. User-owned OAuth means the vendor can't touch the traffic.

For a BYOK-first product like NovaKit, these aren't reasons to avoid user-owned OAuth — they're reasons to embrace it. The kind of user who brings their own API keys and pays providers directly is exactly the kind of user who will register their own OAuth client to keep vendors out of the data path.

How to register your own OAuth client (5-minute version)

Google Drive

  1. Go to console.cloud.google.com/apis/credentials.
  2. Create or select a project. Name it whatever you want — "My NovaKit" is fine.
  3. Enable the Google Drive API for the project.
  4. Click Create Credentials → OAuth client ID.
  5. Application type: Web application.
  6. Authorized JavaScript origins: https://novakit.ai (and http://localhost:3000 if you're running locally).
  7. Authorized redirect URI: https://novakit.ai/api/oauth/google/callback (use your origin if you self-host).
  8. Copy the client ID. Paste it into NovaKit → Settings → Sync → Google Drive → "Your OAuth client ID."

Dropbox

  1. Go to dropbox.com/developers/apps.
  2. Click Create app. Scoped access, App folder (recommended for syncing just a NovaKit folder rather than your whole Dropbox).
  3. Under OAuth 2, add a redirect URI: https://novakit.ai/api/oauth/dropbox/callback.
  4. Under Permissions, grant files.content.write and files.content.read (and files.metadata.read for browsing).
  5. Copy the App key. Paste it into NovaKit → Settings → Sync → Dropbox → "Your app key."

That's it. You now have a personal OAuth integration that lives entirely in your Google or Dropbox account — no shared vendor client in the middle.

Who should care?

If you're using NovaKit (or any AI app) for personal note-taking, hobby projects, or prompts that don't involve sensitive data, the default vendor-owned OAuth pattern is probably fine. The risk is low.

If any of the following apply, user-owned OAuth is a meaningful upgrade:

  • You work with client data, medical records, legal work, or other regulated information.
  • You're a security-conscious developer who wants to keep your vendor dependency surface small.
  • You're in a jurisdiction where data residency matters (your OAuth client IDs and tokens stay where you put them, not wherever the vendor decided to deploy).
  • You just don't like the idea of every SaaS vendor you connect to having permanent Drive access.

The broader pattern

User-owned OAuth is part of a family of "bring your own infrastructure" patterns that AI apps should increasingly support:

  • BYOK (bring your own API keys) for AI providers — you pay OpenAI / Anthropic directly, not the AI app.
  • BYOS (bring your own storage) for sync — your Drive, your WebDAV server, your NAS.
  • BYOOA (bring your own OAuth apps) for third-party integrations — you register, you control.

The connective tissue is that the vendor provides an interface and the user provides the infrastructure. It's harder to build and harder to monetize, but it produces products that don't have a "rug-pull" failure mode — if the vendor pivots, gets acquired, or shuts down, you keep running on your own keys, your own storage, and your own OAuth clients.

Try it in NovaKit

User-owned OAuth for Google Drive and Dropbox is live in NovaKit today (the adapter interface; the PKCE flow and provider API calls are the remaining stubs). WebDAV and local-folder sync are fully implemented. Open Settings → Sync to set it up.

More details in the Phase 2 ship notes and the privacy policy.

NovaKit workspace

Stop reading about AI tools. Use the one you own.

NovaKit is a BYOK AI workspace — chat across providers, compare model costs live, and keep conversations on your device. No markup on tokens, no lock-in.

  • Bring your own keys
  • Private by default
  • All models, one workspace

Keep exploring

All posts