> ## Documentation Index
> Fetch the complete documentation index at: https://university.triggr-app.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Form authentication

> Choose who can open a Studio form, how Triggr matches the person to a client, and what your workflow learns about them.

Form Authentication decides who can open a form and whether your workflow learns which client the person works for. In the form designer, click **Form Authentication**, choose a type, then click **Save** at the bottom of the designer.

<Frame caption="Who can open a form: New starter request switched to Microsoft sign-in, matched to Acme Corp by its tenant ID, then tested as Jane Doe with Impersonate (1:26).">
  <video controls preload="none" playsInline className="w-full aspect-video rounded-xl" poster="/images/videos/studio-form-authentication.jpg" src="https://mintcdn.com/triggr/GxrCQFDFNLmEMyJ1/images/videos/studio-form-authentication.mp4?fit=max&auto=format&n=GxrCQFDFNLmEMyJ1&q=85&s=f1cca4b0b3289b7afe4c620bc3a609e3" data-path="images/videos/studio-form-authentication.mp4" />
</Frame>

| Type | Who can open the form | Workflow knows the client |
| - | - | - |
| None | Anyone with the link | No |
| Password | Anyone with the link and the form's password | No |
| Microsoft | Client staff whose Microsoft tenant ID is on the client | Yes |
| Google | Client staff whose Google Workspace domain is on the client | Yes |
| Internal | Your own Studio team | Only with Manually Set Client |

## Set up a client-facing form

<Steps>
  <Step title="Give each client its tenant ID">
    Add a `microsoftTenantId` variable to each client, as in [Clients and variables](/studio/clients/clients-and-variables#give-it-variables). Clients connected through [GDAP](/integrations/microsoft-graph/gdap-service-account) or [SAM](/integrations/microsoft-graph/sam) already have it.

    <Frame>
      <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/clients/new-client-variable.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=77ee44d88703ab47287ba8c1d96b3842" width="512" alt="The New Variable dialog with Key microsoftTenantId and Value 11111111-2222-3333-4444-555555555555, and Cancel and Create Variable buttons." data-path="images/studio/clients/new-client-variable.png" />
    </Frame>
  </Step>

  <Step title="Require Microsoft sign-in">
    Click **Form Authentication**, choose **Microsoft** and click **Save** at the bottom of the designer.

    <Frame>
      <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/form-authentication.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=ac6c40a14653b865eb67a5b6202bb282" alt="The Form Authentication panel with Authentication Type options None, Password, Microsoft, Google and Internal, Microsoft selected, and Visibility toggles List on Homepage, Restrict to usernames, Restrict to groups and Restrict to group names, all off." width="640" height="1340" data-path="images/studio/forms/form-authentication.png" />
    </Frame>
  </Step>

  <Step title="Set the client in your workflow">
    In the workflow designer, drag **Set Client From Form** (under Client) onto the canvas straight after the Trigger. Later steps act for the submitter's client and can read its variables, such as `{{ ctx.client.name }}`.

    <Frame>
      <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/set-client-from-form.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=5629c0bb832e01bcac03be7f6d769d50" width="288" alt="The Components panel with Set Client From Form typed in the search box and the Client group showing one result, Set Client From Form." data-path="images/studio/forms/set-client-from-form.png" />
    </Frame>
  </Step>

  <Step title="Test as a client user">
    Save the form first: the test opens the saved version. Click **Share Form > Impersonate**, choose a Client and a Microsoft user, and click **Open as this user**. The form opens as that person for 30 minutes; submitting runs the workflow for real, with `ctx.metadata.custom.impersonatedByEmail` set to your email.

    <Frame>
      <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/share-form-impersonate.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=ba7e965e3c2619f8373fb304e6000cbe" width="512" alt="The Share Form dialog on the Impersonate tab with Client set to Acme Corp, a Microsoft user search box, Jane Doe selected from a list of users with their email addresses, and an Open as this user button." data-path="images/studio/forms/share-form-impersonate.png" />
    </Frame>
  </Step>

  <Step title="Share the link">
    In Share Form, click **Copy** next to Public Form URL and send it to the client. Their staff see this:

    <Frame>
      <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/authentication-sign-in.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=b8390d3c93b2caa7706dd94ed595b82f" alt="A public form's sign-in card under the name Your MSP, headed Docs sample – authentication, with the line This form requires Microsoft authentication and a Sign in with Microsoft button." width="1568" height="866" data-path="images/studio/forms/authentication-sign-in.png" />
    </Frame>
  </Step>
</Steps>

## How each type works

### None and Password

None opens straight away. Password asks for the form's password (“This form requires a password to access”); the eye icon in the panel reveals it, and changing it locks out anyone who has the form open. Neither type gives the workflow a person or a client.

<Frame>
  <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/authentication-password.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=c91f9632209d8f42bf62eb7834933fec" width="318" alt="The Form Authentication panel with Password selected, List on Homepage off, a masked Password field with an eye icon, and Preview Before Submit off under Submission." data-path="images/studio/forms/authentication-password.png" />
</Frame>

### Microsoft

Visitors click Sign in with Microsoft and pick their work account (personal accounts such as outlook.com can't get in). Triggr matches the sign-in's tenant ID to a client's `microsoftTenantId`, ignoring case and spaces; with no match they see “you do not have permission to access this form”. Keep each tenant ID on one client.

Without restrictions, anyone in a matched tenant can open the form. Turn on one or more to narrow it; a person who matches any one gets in.

| Option | Lets in |
| - | - |
| Restrict to usernames | People listed under Allowed Usernames, by sign-in name (UPN) or email, ignoring case |
| Restrict to groups | Members of the Entra group object IDs under Universal group IDs (any client) or, after + Add override, under a client's Per-client overrides. With overrides only, clients without one are refused |
| Restrict to group names | Members of a group with this display name in their own tenant, found through your Microsoft integration, so the client must be connected; group changes take up to 15 minutes to apply |

Nested groups count. A blank row in any list saves but matches no one.

Optional Authorization adds a database check: choose an **Authorization Database** (from Data > Databases) and enter **Authorization SQL** that counts rows for the person, who gets in only if it returns more than 0. Each `{{ctx.metadata.microsoftUser.…}}` value is passed as a parameter. Apply Default fills in:

```sql theme={null}
SELECT COUNT(*) AS count FROM users WHERE email = '{{ctx.metadata.microsoftUser.upn}}'
```

<Frame>
  <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/authentication-microsoft.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=7814b6685e12cd8844eb3df031df4573" width="318" alt="The Visibility and Optional Authorization part of the Form Authentication panel for a Microsoft form: List on Homepage off; Restrict to usernames on with alex.morgan@acme.com; Restrict to groups on with one universal group ID and no per-client overrides; Restrict to group names on with Managers; and Authorization Database set to None (disabled)." data-path="images/studio/forms/authentication-microsoft.png" />
</Frame>

### Google

Visitors click Sign in with Google and pick their work account. Triggr matches the Workspace domain to the client whose `googleWorkspaceDomain` variable lists it (separate several with commas: `acme.com,acme.co.uk`). A personal account sees “a Google Workspace account is required to access this form”; a domain on no client, or on two, sees “you do not have permission to access this form”.

Restrict to emails and Restrict to Workspace domains narrow the form; a person who matches either gets in. Optional Authorization works as for Microsoft, with `{{ctx.metadata.googleUser.email}}` and so on.

<Frame>
  <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/authentication-google.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=4efd1ca22340e74deb870fd30e953fe0" width="318" alt="The Visibility and Optional Authorization part of the Form Authentication panel for a Google form: List on Homepage off, a note that visitors need a Google Workspace account matching a client's googleWorkspaceDomain variable, Restrict to emails on with alex.morgan@acme.com, Restrict to Workspace domains on with acme.com, and Authorization Database set to None (disabled)." data-path="images/studio/forms/authentication-google.png" />
</Frame>

### Internal

Your team opens the form from Complete Form in the designer or Complete on Forms; anyone else sees “This form is for internal use — sign in with your staff account to continue”. Internal forms have no Share Form dialog or List on Homepage option. Turn on **Manually Set Client** so your team picks a client and clicks Next before the form opens; without it, the workflow gets no client.

<Frame>
  <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/forms/authentication-internal.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=e319cbce431533fb50157ff177a877d3" width="318" alt="The Form Authentication panel with Internal selected, Manually Set Client on under Internal Forms, and Preview Before Submit off under Submission." data-path="images/studio/forms/authentication-internal.png" />
</Frame>

Preview Before Submit, under Submission for every type, shows the person their answers before they submit.

## What the workflow gets

Every run a form starts has `ctx.metadata.source` (`form_submission`), `ctx.metadata.formId` and `ctx.metadata.submissionId`. Signed-in types add the person and, with Set Client From Form, the client:

| Type | Person | Client |
| - | - | - |
| Microsoft | `ctx.metadata.microsoftUser`: `oid`, `email`, `name`, `givenName`, `familyName`, `tenantId`, `preferredUsername`, `upn`, `roles`, `groups` | The client whose `microsoftTenantId` matches `tenantId` |
| Google | `ctx.metadata.googleUser`: `sub`, `email`, `name`, `givenName`, `familyName`, `domain`, `picture`. The client's ID is also in `ctx.metadata.tenantId` | The client matched at sign-in |
| Internal | `ctx.metadata.internalUser`: `id`, `email`, `name`, `firstName`, `lastName`, `username`. The chosen client's ID is in `ctx.metadata.internalFormTenantId` | The client chosen under Manually Set Client |
| None, Password | Nothing | None |

For example, send the confirmation to `{{ ctx.metadata.microsoftUser.email }}`; if the account has no email address, `email` holds its sign-in name.

## Microsoft sign-in and admin consent

Sign-in uses Triggr's multi-tenant Microsoft Entra app (application ID `75bd83ba-fbd3-47da-b68f-4adab663015f`), which asks only for `openid`, `profile`, `email` and the delegated Microsoft Graph permission `User.Read`. Each person accepts this the first time they sign in. If the tenant [restricts user consent](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-user-consent), an admin there (Cloud Application Administrator or above) [grants consent for the organisation](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/grant-admin-consent) once, for example by signing in to the form and ticking **Consent on behalf of your organization**.

## Your homepage and forms domain

Set these up in [Branding and client portal](/studio/settings/branding-and-portal).

* A Custom Forms Domain changes form links to `https://forms.yourmsp.com/forms/<org-id>/<form-id>` and gives you a homepage at `https://forms.yourmsp.com`; sign-in works on it with no extra setup.
* List on Homepage shows a form on that homepage to anyone; each form still asks for its own sign-in.
* Authenticate on Telescope homepage (Settings > Branding > Telescope Authentication) makes visitors sign in with Microsoft first and shows them only the None forms and the Microsoft forms they'd be let into.

## FAQ

<AccordionGroup>
  <Accordion title="Can guest (B2B) users open a Microsoft form?">
    Guests sign in as their home organisation, so Triggr matches the client whose `microsoftTenantId` is their home tenant, not the tenant they're a guest in.
  </Accordion>

  <Accordion title="Someone works for two clients. Which client does the form use?">
    The client of the account they sign in with. To switch, they click Logout at the top of the form, open the link again and pick the other account.
  </Accordion>

  <Accordion title="How do I let only managers submit?">
    Turn on **Restrict to group names** and add the group each client uses, such as `Managers`. For a handful of people, use Restrict to usernames.
  </Accordion>

  <Accordion title="My technicians need to submit for a client. What should I use?">
    An Internal form with Manually Set Client: they choose the client before the form opens, and Set Client From Form picks it up.
  </Accordion>

  <Accordion title="Why does Preview ask me to sign in?">
    Preview uses the form's own sign-in and never submits. To try a Microsoft or Google form as a client user, use Share Form > Impersonate.
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="“you do not have permission to access this form”">
    Microsoft: no client has the person's tenant as `microsoftTenantId`, they fail a restriction or the Authorization SQL, or a restriction list has a blank row. Google: their domain is on no client or on two, or they fail a restriction.
  </Accordion>

  <Accordion title="“a Google Workspace account is required to access this form”">
    The person signed in with a personal Google account. They need their work Google Workspace account.
  </Accordion>

  <Accordion title="“Invalid password”">
    The password is wrong, or it changed after the person opened the form. They reload the form and enter the current one.
  </Accordion>

  <Accordion title="“MicrosoftAuthorization header is required” when submitting">
    The Microsoft sign-in lasts about an hour in that tab and has expired. Reload the form, sign in again and re-enter the answers.
  </Accordion>

  <Accordion title="Sign in does nothing, “Sign in with Google to submit this form” or “sign-in expired, please try again”">
    The browser blocked the sign-in pop-up, or it was closed or left open for over 10 minutes. Allow pop-ups for your forms domain and try again.
  </Accordion>

  <Accordion title="The sign-in window says “invalid or unrecognised forms origin”">
    The form was opened on a domain that isn't your current Custom Forms Domain. Send the link from Share Form again.
  </Accordion>

  <Accordion title="“Error saving form - … requires at least one username” (or group name, email or domain)">
    A restriction is on with an empty list. Add an entry or turn it off. A Google domain needs a dot and no `@`, and a Password form's password can't be empty.
  </Accordion>

  <Accordion title="Set Client From Form fails with “no tenant ID found in context”">
    The form doesn't identify a client: it's None, Password, or Internal without Manually Set Client. If it fails with “no tenant found with microsoftTenantId variable equal to …”, add that tenant ID to the client's `microsoftTenantId` variable.
  </Accordion>

  <Accordion title="“Failed to load available clients” on an Internal form">
    The person isn't signed in to Studio. Open the form from Complete while signed in.
  </Accordion>

  <Accordion title="“this client has no microsoftTenantId configured” or “Failed to load Microsoft users for this client.” when impersonating">
    Add the client's `microsoftTenantId` variable and connect the client through your Microsoft integration, which Impersonate uses to list its users. For Google, type the user's email; its domain must be in the client's `googleWorkspaceDomain`.
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.