No-Code Integrations

Solving Common OAuth Problems in Bubble Apps

The OAuth problems Bubble builders hit most often, why they happen, and how to approach each one.

5 min read
On this page
  1. Two different OAuth needs
  2. Problem 1: The redirect URI doesn't match
  3. Problem 2: Tokens expire and calls start failing
  4. Problem 3: Tokens are exposed or shared
  5. Problem 4: The provider requires app verification
  6. Problem 5: Users disconnect and nothing happens
  7. Problem 6: Multiple providers multiply the work
  8. A checklist for OAuth in Bubble
  9. Where Pathfix fits
  10. Frequently asked questions

Bubble makes it possible to build full web applications visually, including integrations with external APIs through its API Connector. When those APIs need OAuth, for example to access a user's Google, Microsoft or CRM account, many Bubble builders run into the same set of problems.

This article covers those problems, why they happen and how to approach them. Bubble's features change over time, so check Bubble's own manual for current options.

Two different OAuth needs#

First, be clear which one you're solving.

Login. Users sign in to your Bubble app with an external account. Bubble supports social login options for this, configured through plugins and settings.

API access. Your app calls an external API on behalf of each user, such as reading their calendar. This needs delegated authorization: an access token per user, usually with a refresh token.

Many problems come from treating these as the same thing. Signing in with Google doesn't automatically give your app access to the user's Google Calendar.

Problem 1: The redirect URI doesn't match#

OAuth providers only redirect to URIs you've registered. Bubble apps have different URLs for development and live versions, and custom domains add more.

Fix: register every redirect URI you'll use, exactly as Bubble generates it, in the provider's developer console. Test both development and live versions.

Problem 2: Tokens expire and calls start failing#

Access tokens are short-lived. If the app doesn't refresh them, API calls fail after the token expires, often an hour after connecting.

Fix: confirm whether your OAuth setup obtains a refresh token (some providers need a specific parameter or scope) and whether refresh happens automatically. If it doesn't, you need a way to refresh tokens per user before calls fail.

AAAWgmp1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAABZcanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46YzJwYTpmNTQ1MGVmMS1kMGM1LTQ2ODYtYjlhOC00ZmY4YmQwOGFjYWUAAAADl2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAALxqdW1iAAAARGp1bWRjYm9yABEAEIAAAKoAOJtxE2MycGEuaW5ncmVkaWVudC52MwAAAAAYYzJzaKmKN0sFgfVO8/yVz9EfOwMAAABwY2JvcqNpZGM6Zm9ybWF0bWltYWdlL3N2Zyt4bWxqaW5zdGFuY2VJRHgseG1wOmlpZDowZmZkNjBhYi1mMTY2LTRiYzctYTkxZS0wNjA4NDUxMWUzOGRscmVsYXRpb25zaGlwaHBhcmVudE9mAAAB4mp1bWIAAABBanVtZGNib3IAEQAQgAAAqgA4m3ETYzJwYS5hY3Rpb25zLnYyAAAAABhjMnNoygqGeo6uDUtXNZa7CXf8AgAAAZljYm9yomdhY3Rpb25zgqJmYWN0aW9ua2MycGEub3BlbmVkanBhcmFtZXRlcnOha2luZ3JlZGllbnRzgaJjdXJseC1zZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmluZ3JlZGllbnQudjNkaGFzaFggSjoE4+qb15gBVkDaCk4IR4W5h6/NAmBr0SBVAheclkOkZmFjdGlvbngdY29tLmFudGhyb3BpYy5jbGF1ZGUucHJvdmlkZWRqcGFyYW1ldGVyc6F4H2NvbS5hbnRocm9waWMub3JpZ2luLWNvbmZpZGVuY2VndW5rbm93bmtkZXNjcmlwdGlvbnhmQ2xhdWRlIHByb3ZpZGVkIHRoaXMgZmlsZSBhdCB0aGUgcmVxdWVzdCBvZiBhIHVzZXIgYW5kIG1heSBoYXZlIGNyZWF0ZWQgb3IgbW9kaWZpZWQgdGhlIGZpbGUgY29udGVudHMubXNvZnR3YXJlQWdlbnShZG5hbWVmQ2xhdWRlcmFsbEFjdGlvbnNJbmNsdWRlZPUAAADIanVtYgAAAEBqdW1kY2JvcgARABCAAACqADibcRNjMnBhLmhhc2guZGF0YQAAAAAYYzJzaGuCha/NlDzZtwXNCT/QdJ8AAACAY2JvcqVjYWxnZnNoYTI1NmNwYWRNAAAAAAAAAAAAAAAAAGRoYXNoWCDYDIhFBAF19nQwJ4VrJnAc/DDdCVQguyikEyAeDZdKUWRuYW1lbmp1bWJmIG1hbmlmZXN0amV4Y2x1c2lvbnOBomVzdGFydBjCZmxlbmd0aBkeBAAAAj5qdW1iAAAAJ2p1bWRjMmNsABEAEIAAAKoAOJtxA2MycGEuY2xhaW0udjIAAAACD2Nib3KlY2FsZ2ZzaGEyNTZpc2lnbmF0dXJleE1zZWxmI2p1bWJmPS9jMnBhL3VybjpjMnBhOmY1NDUwZWYxLWQwYzUtNDY4Ni1iOWE4LTRmZjhiZDA4YWNhZS9jMnBhLnNpZ25hdHVyZWppbnN0YW5jZUlEeCx4bXA6aWlkOjczNjcyMmE1LTY1NGUtNGQxNS04NzdlLWRjZjcyNTc4YzU1NnJjcmVhdGVkX2Fzc2VydGlvbnODomN1cmx4LXNlbGYjanVtYmY9YzJwYS5hc3NlcnRpb25zL2MycGEuaW5ncmVkaWVudC52M2RoYXNoWCBKOgTj6pvXmAFWQNoKTghHhbmHr80CYGvRIFUCF5yWQ6JjdXJseCpzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnMudjJkaGFzaFggp3m0k5tBnWgRP1/oWOZ0P6DeeSW77KjNCVRNOdoEAdaiY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFgghe9qgVtpkITGgJIyLrg8zk34j+862Q+2QL87f7NpWU90Y2xhaW1fZ2VuZXJhdG9yX2luZm+jZG5hbWVvQW50aHJvcGljIEZpbGVzZ3ZlcnNpb25lMS4wLjBrc3BlY1ZlcnNpb25lMi40LjAAABA4anVtYgAAAChqdW1kYzJjcwARABCAAACqADibcQNjMnBhLnNpZ25hdHVyZQAAABAIY2JvctKEWQISogEmGCFZAgowggIGMIIBjaADAgECAhRA5aAK7sI50L64g/oGQgU9Z1UTADAKBggqhkjOPQQDAzBJMRcwFQYDVQQKEw5BbnRocm9waWMsIFBCQzEuMCwGA1UEAxMlQW50aHJvcGljIENvbnRlbnQgQ3JlZGVudGlhbHMgUm9vdCBDQTAeFw0yNjA4MDcxODQzNTZaFw0yODA4MDYxOTQzNTZaMEQxFzAVBgNVBAoTDkFudGhyb3BpYywgUEJDMSkwJwYDVQQDEyBBbnRocm9waWMgQ2xhdWRlIENvbnRlbnQgU2lnbmluZzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJh6CmvLUBgFFNU0vUKlOVtE6djd17L5SuwX0LemFisBM3dkd/3cyjxFA3Qo5S46fX0/ihY0VZ7mfb9KF703t5OjWDBWMA4GA1UdDwEB/wQEAwIHgDAVBgNVHSUEDjAMBgorBgEEAYPoXgIBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUzlHiBIFOZFsj+OPEz5o+nMHXXMIwCgYIKoZIzj0EAwMDZwAwZAIwMXMdFJ4BetLLVY7ORuE9noqbbAZOZn/aArXyTwFAZfKrPzxF2vPoJNf1+UCdg1XGAjBwX1zd9WGqYkqmL5SFqw1QySjr1zJfpJM9+1rdDwSPLMOPOjKuiXjoU/pUUeG9RwmhY3BhZFkNngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZYQCIUg4MMQLPkCILqGpIAUXylFCITMmpUTn4R1BjglS+I634cSy0/6BY+JoRLL7Uz1RNY9OuJDEhTKM5uQXyo2M0=OAuth token lifecycleConnected, access token valid, token expires, refresh requested, new token issued, connected again. If the refresh is rejected, the connection branches to refresh rejected and then reauthorization required.ConnectedAccess tokenvalidTokenexpiresRefreshrequestedNew tokenissuedConnectedif rejectedRefreshrejectedReauthorization required
Without refresh, every connection breaks shortly after it's made.

Problem 3: Tokens are exposed or shared#

Storing tokens in fields readable by the client, or calling APIs from the browser with a user's token visible, risks exposing credentials. A misconfigured setup can also cause one user's token to be used for another user's requests.

Fix: keep tokens private, use Bubble's privacy rules to restrict access to any stored credentials, make API calls from backend workflows or server-side API Connector calls where possible, and always associate tokens with the specific user who authorized them.

Problem 4: The provider requires app verification#

Some providers require verification before public users can authorize apps that request sensitive scopes. Google, for example, reviews apps that use sensitive or restricted scopes. Until verified, users may see warnings or be limited.

Fix: request only the scopes you need, configure the consent screen completely, and start the verification process early.

Problem 5: Users disconnect and nothing happens#

When a user revokes access at the provider, calls fail, but the app may not know why.

Fix: detect authorization failures, mark the connection as broken, and show the user a clear "Reconnect" option.

Problem 6: Multiple providers multiply the work#

Each provider has its own endpoints, scopes, token rules and quirks. Supporting several in Bubble means configuring and maintaining each separately.

Fix: decide early whether to handle OAuth per provider in Bubble, or use a plugin or service that manages the authorization layer so your Bubble app only makes the API calls.

A checklist for OAuth in Bubble#

  • Login and API access treated as separate concerns.
  • All redirect URIs registered, for every app version and domain.
  • Refresh tokens obtained and refreshed automatically.
  • Tokens stored privately and tied to the correct user.
  • Minimum scopes requested; verification started where required.
  • Broken connections detected and surfaced to users.
  • Disconnect option that stops further use of the token.

Where Pathfix fits#

Pathfix has a set of Bubble plugins built for exactly these problems.

The Pathfix OAuth Connector is the primary plugin. It connects your Bubble app to your Pathfix account and renders the Connect buttons for the providers you've configured. Pathfix then runs the OAuth flow, stores each user's tokens and refreshes them, which takes care of problems 2, 3 and 6 above. You configure each provider in Pathfix with the App ID and App Secret from that provider's developer console, so users authorize your own OAuth app.

Provider plugins add preconfigured API calls for specific providers as Bubble workflow actions and data calls. They require the OAuth Connector to be installed first. Pathfix publishes 17 plugins in the Bubble plugin store:

PluginCovers
Pathfix OAuth ConnectorPrimary plugin: Connect buttons, OAuth flow and token management
SSO Login (Multiple Providers)Sign-in with several identity providers
Google Calendar (OAuth)Calendar API calls
GMail (OAuth)Gmail API calls
Microsoft Calendar (OAuth)Microsoft calendar API calls
Slack (OAuth)Slack API calls
Quickbooks (Customer + Invoice)QuickBooks customers and invoices
Quickbooks (Vendor + Payments)QuickBooks vendors and payments
Xero - Customer + Invoice (OAuth)Xero customers and invoices
Mailchimp (OAuth)Mailchimp API calls
LinkedIn API (OAuth)LinkedIn API calls
Instagram Graph API (OAuth)Instagram Graph API calls
Facebook API (Pathfix OAuth)Facebook API calls
Twitter (OAuth)Twitter API calls
Twitter V2 API (OAuth)Twitter v2 API calls
Twilio (User Auth)Twilio API calls
Spotify Search API (With OAuth)Spotify search

See all Pathfix plugins on Bubble for the current list.

For providers without a dedicated plugin, users still authorize through the OAuth Connector, and you make any API call you need with Bubble's API Connector.

The Pathfix Bubble documentation covers setup, custom OAuth buttons, multiple connections per user, custom redirect domains and error codes. See the list of no-code plugins for current provider plugins.

For a worked example, see How to Connect Google Calendar to a Bubble App.

Frequently asked questions#

Does Bubble's Google login give me calendar access?#

Not by itself. Login and API access usually need different scopes and handling.

Do I need a separate plugin for each provider?#

With Pathfix, the OAuth Connector handles authorization for every provider you configure. Provider plugins are optional and add preconfigured API calls; without one, you call the provider's API through Bubble's API Connector.

Why does my integration stop working after an hour?#

The access token has probably expired and isn't being refreshed.

Can I call OAuth APIs from the browser?#

Avoid it for user tokens. Server-side calls keep credentials out of the browser.