# Open as a MockFlow board

> Add a Connect MockFlow button, then turn each user's roadmap into a board in their account.

Source: https://mockflow.com/developers/examples/oauth/open-as-board

A product roadmap tool wants an **Open as a MockFlow board** button, so its users can discuss and rearrange their roadmap on a visual board with their team. Each user connects their own MockFlow account once; after that, one click creates a board in their account with the milestones as a timeline and the initiatives as a kanban.

This is the most complete of the OAuth examples, and the best one to start from: it covers every step of the [OAuth flow](/developers/concepts/oauth-apps).

[**Download the code**](/developers/assets/examples/mockflow-open-as-board.zip) (Node.js 18 or later, no packages)

## What it does

- Shows **Connect MockFlow** to a user who has not connected, and the board button to one who has.
- Creates the board in the user's own account: a [timeline](/developers/reference/item-types/timeline) of milestones and a [kanban](/developers/reference/item-types/kanban) of initiatives by status.
- Refreshes the user's token when it is close to expiring, notices when they have disconnected the app in MockFlow, and revokes the tokens when they click **Disconnect** in your product.

## How it works

1. **Connect:** make a random `state` and a PKCE `code_verifier`, keep both in the user's session, and send the user to `https://mockflow.com/mcp-oauth/` with your client ID, redirect URI, the scopes `user:read boards:write` and the `code_challenge`.
2. **Callback:** check that `state` matches, then trade the `code` for tokens at `https://mockflow.com/mcp-oauth/token` with your secret and the verifier. The code lasts 10 minutes and works once.
3. **Store:** save the access token, the refresh token and when the access token expires, against your user. Read [`GET /me`](/developers/reference/me/get-me) to show who is connected.
4. **Call:** send the user's access token as a bearer token to [`POST /boards`](/developers/reference/boards/create-board) and a [batch](/developers/reference/items/batch-items) of items.
5. **Refresh:** access tokens last 24 hours. Before one runs out, trade the refresh token for a new pair and store both. An `invalid_grant` means the user disconnected: delete the tokens and show **Connect MockFlow** again.
6. **Disconnect:** post either token to `https://mockflow.com/mcp-oauth/revoke` and delete your copy.

## Run the example

Register an app in the **OAuth apps** tab of the [developer console](/developers/console/?tab=oauth) with the redirect URI `http://localhost:3000/oauth/callback` and the scopes `user:read` and `boards:write`. Then:

```bash
cp .env.example .env        # paste the client ID and secret into .env
node server.js              # open http://localhost:3000
```

While the app is in development, you and the people in your workspace can connect it. To let anyone connect, submit it for review in the console; a published app needs a description, a logo and an https redirect on your own domain.

## The key code

```javascript
// Connect
s.auth = newAuthRequest();   // state, verifier, challenge
redirect(res, authorizeUrl({ clientId, redirectUri, scope: 'user:read boards:write', state: s.auth.state, challenge: s.auth.challenge }));

// Callback
if (url.searchParams.get('state') !== s.auth.state) return html(res, 'Expired', 400);
const tokens = await exchangeCode({ clientId, clientSecret, redirectUri, code: url.searchParams.get('code'), verifier: s.auth.verifier });
store.set(s.userId, tokens);

// Call, refreshing first when needed
const token = await accessTokenFor(store, s.userId, app);   // null when the user disconnected
const board = await new MockFlow({ token }).post('/boards', { title: 'Q1 2027 roadmap' });
```

The OAuth helpers are in `lib/oauth.js` in the download, and are reused by every OAuth example.

## Adapt it

- **CRM:** "Plan this account" turns an account's open opportunities into a board.
- **Help desk:** "Map this issue" turns a ticket thread into a flowchart of what the customer tried.
- **Forms and surveys:** "Visualise results" turns answers into charts on a board.

## What you need

An OAuth app with the scopes `user:read` and `boards:write`. The board is created under the connecting user's plan, so a Basic account's three board limit applies to them; the example shows a link to upgrade when the API answers `402`.
