# Who can use a form

Public, Verified (sign in with Microsoft, no accounts) or Protected (your form users and roles) — and how your workflow knows who it's talking to.

## Three access levels

| Level | Who gets in | Accounts to manage | Good for |
| --- | --- | --- | --- |
| **Public** | Anyone with the page | None | Contact forms, sign-ups, quote requests |
| **Verified** | Anyone who signs in with a trusted provider (Microsoft today), optionally only from certain email domains | None — the provider vouches for them | Client portals, partner intake, "staff at acme.com only" tools, spam-free public forms |
| **Protected** | Form users you create, by role or individually | Yes, on the Form Users page | Business apps where you decide exactly who has access |

Pick the level from the access menu in the form editor's toolbar (it shows the current level: **Public**, **Verified** or **Protected**). **Manage Access** in the same menu holds the settings for the chosen level. Every data call — onload, submit, buttons and row actions — is checked on the server, not just hidden in the page.

## Verified: sign in with Microsoft

Visitors see **Continue with Microsoft**. Their browser goes to Microsoft and comes straight back to the same page, signed in. They don't create an account with you, and you have no passwords to manage. Your workflows receive who they are, as confirmed by Microsoft:

n8n receives (onload, submit, fetch):

```
{
  "endUserId": "microsoft:72f988bf-…:a1b2c3…",
  "endUser": {
    "id": "microsoft:72f988bf-…:a1b2c3…",
    "email": "jane@contoso.com",
    "emailVerified": true,
    "name": "Jane Doe",
    "verified": true,
    "provider": "microsoft",
    "tenantId": "72f988bf-…"
  },
  "data": { … }
}
```

`endUserId` is stable for that person, so use it as the key for their records. Button and row-action webhooks get the same identity in the `X-F2WF-User-Id`, `X-F2WF-User-Email` and `X-F2WF-User-Provider` headers. A sign-in lasts 8 hours, then the visitor signs in again (usually one click).

### Verified settings (Manage Access)

-   **Sign in with:** the providers this form offers. None ticked = every provider your organization has set up.
-   **Email domains:** only people whose _provider-verified_ email is at one of these domains (or their subdomains) get in, e.g. `contoso.com`. Leave empty to accept any account.

**Embedding a Verified form?** List the websites that embed it under the form's **Settings > Allowed domains**. A sign-in only ever returns to the form's hosted page or to an allowed domain, so another site can't start a sign-in and collect your visitors' identity.

### Set up Microsoft sign-in (about 5 minutes)

Your organization uses its own Microsoft app registration, so the Microsoft sign-in screen shows your app's name and logo.

1.  In the dashboard, open **Settings > Sign-in Providers** and copy the **Redirect URI**.
2.  In the [Microsoft Entra admin center](https://entra.microsoft.com), go to **App registrations > New registration**. Give it your organization's name. Under _Supported account types_, pick who may sign in (any Microsoft account is the most common). Under _Redirect URI_, choose **Web** and paste the URI.
3.  On the app's **Overview**, copy the **Application (client) ID**.
4.  Under **Certificates & secrets > New client secret**, create a secret and copy its **Value** (not the Secret ID). It's only shown once.
5.  Back in Sign-in Providers, paste the client ID and secret, choose **Who can sign in** to match step 2, and save.
6.  On a form, choose **Verified** in the access menu and save.

**Who can sign in** options: any Microsoft account (work, school or personal), work or school accounts only, personal accounts only, or **one organization only** — enter a Directory (tenant) ID or domain, and only that company's accounts can sign in. That last option is the strongest way to build a tool for one client's staff.

Client secrets expire (6–24 months, set when you create them). Put a reminder in your calendar; when you make a new one, paste it into Sign-in Providers. Leave the secret field blank when saving other changes to keep the current one.

### Which emails count as verified

Personal Microsoft accounts (Outlook, Hotmail) are verified by Microsoft. For work and school accounts, form2wf uses the account's sign-in name, whose domain the company has proven it owns. The free-text "email" field of a work account is _not_ trusted on its own, because a company's admin can set it to anything. So `emailVerified` and the email-domain list can't be fooled by a made-up address.

## Protected: your form users

**Form users** are people who sign in with an email and password you give them. They are separate from dashboard team members and can't open the dashboard. Admins create them on the **Form Users** page (`/dashboard/form-users`) or with the `create_form_user` MCP tool. Access is granted to individual form users, or to **roles** — named groups you manage under **Roles**.

1.  In the form editor toolbar, open the access menu and choose **Protected**.
2.  From the same menu, open **Manage Access** and choose the roles and form users allowed in.

Signed-out visitors see a _Sign in to access this form_ button. After signing in, allowed users see the form with a "Signed in as …" bar; others see an access-denied message. The session lasts 7 days and is shared by every form2wf form on the same website.

n8n receives:

```
{
  "endUserId": "9a0b…",
  "endUser": { "id": "9a0b…", "email": "client@acme.com", "name": "Acme Ops" },
  "data": { "request": "Please reset our router" },
  "metadata": { … }
}
```

Dashboard team members can sign in to a protected form and view it, but its submit endpoint only accepts form users. Create a form user account for anyone who needs to submit, including staff.

## From an AI agent (MCP)

MCP: set_form_access:

```
{ "form_id": "3f1c…", "access_mode": "verified",
  "verified_config": { "providers": ["microsoft"], "emailDomains": ["contoso.com"] } }

{ "form_id": "3f1c…", "access_mode": "protected", "role_ids": ["…"], "user_ids": [] }
```

Sign-in providers themselves are set up by an admin in the dashboard; their secrets are never available over the API.

## Patterns

-   **Client portal without accounts:** Verified, email domain = the client's company. The onload webhook returns that person's tickets, keyed by `endUserId`.
-   **Internal tools:** Verified with your own domain (or "one organization only" in the provider settings) — your staff use their work Microsoft accounts.
-   **Fine-grained business apps:** Protected, with roles per team.

---
Source: https://form2wf.com/docs/access — Form2Workflow documentation (Publishing)
