Skip to Content
Step-by-Step GuidesBuild a BFF Demo Store

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.com

What 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/products

Step 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-client

Add the BFF callback URL. Replace the gateway domain with your real one:

https://your-store.authgate.site/bff/callback

Use these scopes:

openid profile email

Step 2: Create the BFF gateway

Go to API Gateway > Create Gateway.

Use:

FieldValue
Gateway namebff-demo-store
Gateway typeBFF
Auth typeOAUTH2
OAuth2 clientbff-demo-store-client

After creation, AuthGate gives you the app entrypoint:

https://bff-demo-store.authgate.site

Step 3: Register the frontend app

Open the gateway and go to Frontend Apps.

Add the deployed frontend origin:

https://your-store-frontend.example.com

Users 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:

FieldValue
Service namedummyjson
Target URLhttps://dummyjson.com

Step 5: Create routes

Open Routes and add these routes.

Public product reads:

MethodPublic pathTarget pathSecurity
GET/api/products/productsPUBLIC
GET/api/products/{id}/products/{id}PUBLIC

Secure product writes:

MethodPublic pathTarget pathSecurity
POST/api/products/add/products/addSECURE
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} SECURE

Step 6: Test like a real user

Open the app as a guest

Open:

https://bff-demo-store.authgate.site

The frontend page should load from the gateway URL.

Test public reads

Open or call:

https://bff-demo-store.authgate.site/api/products

Expected 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/me

Expected 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 /profile

The backend API should use:

/api/products /api/products/1 /api/profile

This avoids a common mistake where /products/1 shows JSON instead of the product details page.

What to verify before calling it done

CheckExpected result
Open /products as guestFrontend product page loads.
Open /api/products as guestJSON product list returns.
Open /api/products/1 as guestJSON product detail returns.
Call secure route as guestUnauthorized.
Sign in through /bff/loginReturns to the gateway URL.
Call secure route after sign-inRequest succeeds.
Inspect browser storageNo access token in localStorage or sessionStorage.
Last updated on