Build a BFF Demo Store
This guide shows how to configure a BFF gateway for a normal ecommerce-style website.
The behavior should feel familiar:
- guests can view products
- guests cannot perform protected actions
- signed-in users can call secure routes
- the browser never receives an access token
You can use a free test backend such as DummyJSON:
https://dummyjson.comWhat you will build
User opens:
https://your-store.authgate.site/products
Frontend calls:
GET /api/products
GET /api/products/1
POST /api/products/add
PATCH /api/products/1
DELETE /api/products/1
AuthGate forwards to:
https://dummyjson.com/productsStep 1: Create or choose an IAM client
Go to IAM > Clients and create an OAuth2 client for the store.
Example client ID:
bff-demo-store-clientAdd the BFF callback URL. Replace the gateway domain with your real one:
https://your-store.authgate.site/bff/callbackUse these scopes:
openid profile emailStep 2: Create the BFF gateway
Go to API Gateway > Create Gateway.
Use:
| Field | Value |
|---|---|
| Gateway name | bff-demo-store |
| Gateway type | BFF |
| Auth type | OAUTH2 |
| OAuth2 client | bff-demo-store-client |
After creation, AuthGate gives you the app entrypoint:
https://bff-demo-store.authgate.siteStep 3: Register the frontend app
Open the gateway and go to Frontend Apps.
Add the deployed frontend origin:
https://your-store-frontend.example.comUsers should browse through the AuthGate gateway entrypoint. The frontend origin is the upstream app AuthGate proxies, while /bff/* and /api/* stay on the same browser origin.
Step 4: Register the backend service
Open Services, then add:
| Field | Value |
|---|---|
| Service name | dummyjson |
| Target URL | https://dummyjson.com |
Step 5: Create routes
Open Routes and add these routes.
Public product reads:
| Method | Public path | Target path | Security |
|---|---|---|---|
GET | /api/products | /products | PUBLIC |
GET | /api/products/{id} | /products/{id} | PUBLIC |
Secure product writes:
| Method | Public path | Target path | Security |
|---|---|---|---|
POST | /api/products/add | /products/add | SECURE |
PUT | /api/products/{id} | /products/{id} | SECURE |
PATCH | /api/products/{id} | /products/{id} | SECURE |
DELETE | /api/products/{id} | /products/{id} | SECURE |
Same routes as a checklist:
GET /api/products -> /products PUBLIC
GET /api/products/{id} -> /products/{id} PUBLIC
POST /api/products/add -> /products/add SECURE
PUT /api/products/{id} -> /products/{id} SECURE
PATCH /api/products/{id} -> /products/{id} SECURE
DELETE /api/products/{id} -> /products/{id} SECUREStep 6: Test like a real user
Open the app as a guest
Open:
https://bff-demo-store.authgate.siteThe frontend page should load from the gateway URL.
Test public reads
Open or call:
https://bff-demo-store.authgate.site/api/productsExpected result: product JSON returns without login.
Test a secure write before login
Call a secure route from the app or browser dev tools:
await fetch('/api/products/add', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: 'AuthGate Test Product'
})
})Expected result before login: unauthorized. In production you should usually see a message like Missing BFF session cookie.
Sign in
Use:
/bff/login?return_to=/After login, AuthGate should return you to the gateway URL and set the AUTHGATE_BFF_SESSION cookie.
Check the BFF session
Open:
/bff/meExpected result after login: session JSON returns. If you are not signed in, this endpoint returns unauthorized with a message like Missing BFF session cookie.
Test the secure write again
Run the same POST request again.
Expected result after login: the gateway accepts the BFF session and forwards the request.
Why route paths use /api/...
The frontend page can use:
/products
/products/1
/profileThe backend API should use:
/api/products
/api/products/1
/api/profileThis avoids a common mistake where /products/1 shows JSON instead of the product details page.
What to verify before calling it done
| Check | Expected result |
|---|---|
Open /products as guest | Frontend product page loads. |
Open /api/products as guest | JSON product list returns. |
Open /api/products/1 as guest | JSON product detail returns. |
| Call secure route as guest | Unauthorized. |
Sign in through /bff/login | Returns to the gateway URL. |
| Call secure route after sign-in | Request succeeds. |
| Inspect browser storage | No access token in localStorage or sessionStorage. |