Integration
Integration Walkthrough
The full path from a blank workspace to a working app where users sign in and every piece of data they save is private to them — explained in plain language, step by step, whether you are building with an AI coding tool or writing the integration yourself.
On this page
- Before you start
- The mental model, briefly
- Step 1 — Create a workspace
- Step 2 — Register an application
- Step 3 — Understand the redirect URI
- Step 4 — Choose how you will build
- What actually happens when a user signs in
- Working with a user’s private data
- Signing out and expired sessions
- Common issues
- Verify it is working
- Where to go next
Before you start
You need one thing: a secureFlows account, which you get by signing in at the top of Workspace Management with a Google account. Everything else — the workspace, the application, the sign-in screen your users see — is created from there. There is nothing to install and nothing to deploy on secureFlows’ side; you are only ever connecting your app to a system that is already running.
You will make two decisions along the way: what to name your workspace, and whether an AI coding tool writes the integration code for you or you write it by hand. Both are covered below, and neither is permanent — you can rename things and change your approach later without losing anything.
The mental model, briefly
Four ideas carry the whole integration. If you want the longer, non-technical version of this, read What is secureFlows? first — here is just enough vocabulary to follow the rest of this page:
- Workspace — the account-level container for your product. Users, applications, and settings all live inside one.
- Application — one product or client inside your workspace. A workspace can hold several applications, each kept separate.
- Hosted login — the sign-in screen secureFlows shows your users. You link to it; you never build it.
- Session — what a signed-in user gets back: a token that identifies them, plus a private storage space only they can read or write.
1Create a workspace
Sign in at Workspace Management and create a workspace. Pick any name — it is how you will refer to this account when you connect an app later, not something your end users ever see.
At creation you will see two toggles worth understanding before you flip them:
- Open signup vs. invite-only. On means anyone who reaches your app’s sign-in screen can create an account. Off means only people you explicitly invite as workspace members can sign in — useful for internal tools or a closed beta. Most consumer-facing apps leave this on.
- Self-service dashboard. On gives your end users a page where they can see their own sessions and revoke access themselves, with no extra work from you. Off means that page is not available to them.
Both are settings you can change later — neither one is a one-way door.
2Register an application
Inside your workspace, register an application for the product you are building. You will set three things:
- An application ID — a short identifier you choose. You will reuse this exact value in your app’s code (or in the prompt you give an AI coding tool), so pick something you will remember.
- A display name — what users see on the sign-in screen ("Continue to <display name>?").
- A redirect URI — covered on its own below, since it is the single most common thing people get stuck on.
A workspace can hold more than one application — if you build a second product later, register a second application in the same workspace instead of starting over.
3Understand the redirect URI
After a user signs in, secureFlows has to send their browser back to your app. The redirect URI is the exact address you tell secureFlows it is allowed to send them to — and it is an allowlist for a real reason: without it, a stolen or manipulated login link could redirect a user to an attacker’s site instead of yours.
The default that works for most people
Use your app’s public web address plus /callback — for example https://my-app.com/callback. Add that under Redirect URIs when you register the application, and make sure your app has a page or route at that address (more on what that page needs to do further down).
Building on an AI app builder with a preview sandbox (Lovable, Base44, and similar tools)? The preview host often is not known until you try signing in once. If the default above does not work right away, follow Finding the correct redirect URL — it walks through discovering the exact preview and published URLs step by step.
4Choose how you will build
Both paths end at the same place: a working sign-in screen and private per-user storage. They differ in who writes the code.
Build with an AI coding tool
Tell your AI coding tool (Cursor, Claude Code, Lovable, Base44, and similar) to use secureFlows, and point it at the technical reference it needs:
Use secureFlows for auth and data storage (read https://www.secure-flows.com/ai/secureflows-integration/SKILL.md). Use: workspace = <your workspace>, appId = <your application ID>
That one instruction is usually enough — you do not need to describe the auth flow, the callback route, or the storage API yourself. The tool reads that reference and writes the sign-in screen, the callback handling, and the calls to secureFlows for you. Describe the rest of your app normally.
Write the integration yourself
If you are hand-coding it, you will implement three pieces: a link or button that sends users to hosted
login, a /callback route that stores the token secureFlows hands back, and calls to the
Session API using that token. The next two sections describe exactly what each piece does, in order.
The complete request-and-response reference (exact HTTP calls, headers, and JSON bodies) is in the Integration Quickstart — this page explains what is happening and why; that one shows the wire format.
What actually happens when a user signs in
Whichever path you chose, this is the sequence underneath it. Knowing it makes the rest of the integration — and any troubleshooting — much easier to reason about:
- Your app sends the user to hosted login with your workspace name, your application ID, and your redirect URI. This can be a link, a redirect, or a button — there is no popup and no embedded login form in your app.
- secureFlows shows its sign-in screen. The user signs in with an email/password or one of the configured providers. If their browser is already signed in from a previous visit, they see a confirmation prompt (“Continue as <email> to <your app’s display name>?”) rather than being signed in silently — this is why the display name you set in step 2 matters.
- The browser lands back on your redirect URI with a session token attached to the address. This is the one and only moment your app receives that token.
- Your app stores the token and uses it as proof of who’s signed in for every following request. Nothing about the user’s identity is ever passed in a request body — the token alone is what secureFlows checks.
Your app never sees a password, never stores one, and never talks to an identity provider directly — all of that happens on secureFlows’ side, behind the hosted screen.
Working with a user’s private data
Once your app has a session token, it can read and write that one user’s private storage. Storage is simple on purpose — a flat set of key/value pairs, scoped automatically to the signed-in user. There is no schema to design and no per-user filtering to write; asking for a key always returns only that user’s value for it, because the token itself is what determines whose data you are looking at.
| What you want to do | Call | Notes |
|---|---|---|
| Read everything the user has saved | GET /api/v1/sessions | Returns a flat object of every key/value pair; an empty session returns {}. |
| Read one value | GET /api/v1/sessions/get/<key> | A key that was never written returns 404 — treat that as “use a default,” not an error. |
| Save one value | POST /api/v1/sessions/set/<key> | Body is { "value": ... }; the value can be a string, number, boolean, array, or object. |
| Delete one value | DELETE /api/v1/sessions/delete/<key> | Returns true if something was deleted, false if the key was already gone. |
| Show the signed-in user’s email | GET /api/v1/sessions/identity | Use this for display purposes instead of trying to read the token yourself. |
Every one of these calls needs the session token from the callback step, sent as Authorization: Bearer <token>. A request without it is not a bug on secureFlows’ side — it is treated the same as a signed-out user.
Signing out and expired sessions
To sign a user out, call POST /api/v1/sessions/revoke with their token, then discard it on your
side and send them back to hosted login. Once revoked, that token stops working entirely — any further
request with it is rejected.
Separately, a token can simply expire after enough time has passed. This is not the same thing as losing data: the user’s stored information is untouched, and the fix is the same either way — send them back through hosted login. They get a fresh token for the same underlying session, and everything they saved is exactly where they left it.
Common issues
- Sign-in fails immediately with an error mentioning an unlisted redirect URI. The address your app is sending users back to is not on the allowlist for that application. Add the exact URL — see Finding the correct redirect URL if you are not sure what it should be yet.
-
The app seems stuck redirecting back and forth after sign-in.
Almost always a callback route that requires the user to already be signed in to view it. Your
/callbackpage has to be reachable before the token exists, since that is exactly where it arrives. -
Session calls fail right after sign-in even though it looked successful.
Check that the token from the callback address is actually being attached as
Authorization: Bearer <token>on every Session API call — a missing or empty header looks identical to a signed-out user from secureFlows’ side. - A user reports being signed out with no warning. Their token likely expired from time passing, not from anything going wrong. Send them back through hosted login — their data is intact and waiting under the same session.
- Reading a value that was definitely saved returns a “not found” error. For a single-key read, this means that exact key has never been written for this user — it is the normal response for a key that does not exist yet, not a failure. Handle it by falling back to a default value.
- Requests start failing with a “too many requests” style error. A usage limit was reached (session count, request rate, or storage size, depending on your plan). Show the user a plain “limit reached” message rather than retrying in a loop.
Verify it is working
Before calling the integration done, walk through this once yourself, in a private/incognito window so you are not relying on an already-signed-in session:
- Open your app and sign in as a brand-new user through hosted login.
- Save something — anything your app writes to storage.
- Sign out.
- Sign back in as that same user and confirm what you saved is still there.
- Sign in as a different user and confirm you do not see the first user’s data.
That last step is the one people skip and the one that matters most — it is the actual proof that per-user isolation is working, not just that sign-in works.
Where to go next
For the exact request and response format of every call on this page, see the Integration Quickstart. For the full technical reference an AI coding tool reads, see SKILL.md. For interactive API docs, see the OpenAPI hub. For the security model behind all of this, see Platform Architecture.