JSON Web Tokens enable stateless authentication for Bubble apps accessed by external clients like mobile apps or third-party services. This tutorial covers generating JWTs in backend workflows, validating incoming tokens, and securing API endpoints with token-based authentication.
Overview: JWT Authentication in Bubble
JWT (JSON Web Token) authentication is essential when external applications — mobile apps, third-party services, or other web apps — need to authenticate with your Bubble backend. Unlike Bubble's built-in cookie-based sessions, JWTs are stateless tokens that can be passed in API headers.
Prerequisites
- A Bubble app on Starter plan or above
- The Toolbox plugin installed (for JavaScript operations)
- Basic understanding of backend API workflows
- Familiarity with how REST APIs work
Step-by-step guide
Understand when to use JWT in Bubble
Understand when to use JWT in Bubble
Bubble's built-in authentication uses browser cookies, which works for web apps but not for mobile apps, IoT devices, or third-party API consumers. JWT solves this by providing a token that the client stores and sends with every request. Use JWT when: external apps need to call your Bubble API, you are building a mobile app that talks to your Bubble backend, or you need stateless authentication for webhooks.
Expected result: You understand when JWT is needed versus Bubble's built-in auth.
Set up a JWT generation backend workflow
Set up a JWT generation backend workflow
Create a backend API workflow called generate-token. Add parameters: user_id (text) and email (text). Use the Toolbox plugin's Server Script action (or a JWT plugin) to create the token. The JWT payload should include the user_id, email, issued_at timestamp, and expiration time. Sign it with a secret key stored in your app's settings or a private API key. Return the token using Return data from API.
1// JWT payload structure2{3 "sub": "user_unique_id_here",4 "email": "user@example.com",5 "iat": 1711612800,6 "exp": 1711699200,7 "iss": "your-bubble-app"8}Pro tip: Store your JWT signing secret as a private key in the API Connector or a backend workflow parameter — never expose it in frontend code.
Expected result: A backend workflow that generates signed JWTs for authenticated users.
Create a login endpoint that returns a JWT
Create a login endpoint that returns a JWT
Create a backend API workflow called login that accepts email and password parameters. Use the Log the user in action to verify credentials. If successful, call the generate-token workflow with the user's ID and email. Return the JWT token in the API response. External apps call this endpoint, receive the token, and include it in subsequent requests.
Expected result: External apps can authenticate by calling the login endpoint and receiving a JWT.
Validate incoming JWTs on protected endpoints
Validate incoming JWTs on protected endpoints
On your protected backend API workflows, add a parameter called token (text). At the start of the workflow, use a Server Script or JWT plugin to decode and verify the token. Check that: the signature is valid (matches your secret), the token has not expired (exp > current timestamp), and the issuer matches (iss = your app). If validation fails, return an error response.
Expected result: Protected API endpoints reject invalid or expired tokens and only process requests with valid JWTs.
Build a token refresh mechanism
Build a token refresh mechanism
JWTs should have short expiration times (1-24 hours) for security. Create a refresh-token endpoint that accepts a valid (non-expired) JWT and returns a new one with a fresh expiration. The client stores the new token and uses it for subsequent requests. This prevents users from being forced to re-login frequently.
Expected result: Clients can refresh their JWT before it expires without re-authenticating.
Complete working example
1JWT AUTHENTICATION SUMMARY2===========================34ENDPOINTS:5 POST /api/1.1/wf/login6 Params: email, password7 Returns: { token: "eyJhbGciOiJIUzI1NiI..." }89 POST /api/1.1/wf/refresh-token10 Params: token (current valid JWT)11 Returns: { token: "eyJhbGciOiJIUzI1NiI..." (new) }1213 POST /api/1.1/wf/protected-action14 Params: token, ...other params15 Validates token before processing1617JWT STRUCTURE:18 Header: { "alg": "HS256", "typ": "JWT" }19 Payload: { "sub": "user_id", "email": "...", "iat": timestamp, "exp": timestamp, "iss": "app-name" }20 Signature: HMACSHA256(header + payload, secret)2122VALIDATION FLOW:23 1. Decode token header and payload (base64)24 2. Verify signature matches using secret25 3. Check exp > current timestamp26 4. Check iss matches expected value27 5. Find user by sub (user_id) in database28 6. If all pass → proceed with workflow29 7. If any fail → return error response3031SECURITY:32 - Secret key: stored server-side only33 - Token expiry: 1-24 hours34 - Refresh: issue new token before expiry35 - Never log or expose tokens in error messagesCommon mistakes when authenticating users in a Bubble.io application using JWT (JSON Web Tokens)
Why it's a problem: Using a weak or hardcoded JWT secret
How to avoid: Use a long, random secret (32+ characters) stored securely in your app settings, never in frontend code
Why it's a problem: Setting very long token expiration times
How to avoid: Set expiration to 1-24 hours and implement a token refresh mechanism
Why it's a problem: Not validating the token signature on every request
How to avoid: Always verify the JWT signature using your secret before trusting the payload data
Best practices
- Store the JWT signing secret server-side only, never in frontend code
- Set short token expiration times (1-24 hours) and implement refresh
- Validate the signature, expiration, and issuer on every protected request
- Include minimal claims in the JWT payload — do not store sensitive data
- Use HTTPS for all API endpoints to prevent token interception
- Log authentication events for security monitoring
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I need to add JWT authentication to my Bubble.io app so a mobile app can authenticate with my backend API. Can you walk me through generating JWTs in backend workflows, validating them on protected endpoints, and implementing token refresh?
Add JWT authentication to my app. I need a login endpoint that returns a JWT, protected API endpoints that validate the token, and a refresh mechanism. Set up the backend workflows.
Frequently asked questions
When should I use JWT instead of Bubble's built-in auth?
Use JWT when external apps (mobile, IoT, third-party services) need to authenticate with your Bubble API. For standard web app users, Bubble's built-in cookie-based authentication is simpler and sufficient.
Can I use JWT for Bubble web app users?
You can, but it adds unnecessary complexity. Bubble's built-in auth handles web sessions automatically. JWT is primarily for external API consumers.
Is there a JWT plugin for Bubble?
Yes. Several plugins handle JWT generation and validation. Alternatively, use the Toolbox plugin's Server Script with a JavaScript JWT library.
How do I store the JWT on the client side?
Mobile apps typically store JWTs in secure storage (Keychain on iOS, EncryptedSharedPreferences on Android). Web apps can use localStorage or httpOnly cookies.
What happens when a JWT expires?
The client receives a 401 Unauthorized response. It should then call the refresh-token endpoint to get a new token, or redirect the user to re-authenticate.
Can RapidDev help with complex authentication systems?
Yes. RapidDev has built enterprise authentication systems including JWT, OAuth2, SSO, and multi-factor authentication in Bubble for apps serving thousands of users.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation