Skip to main content

App Registration

Every FlowForger CLI command that talks to Microsoft 365 or Power Automate (--auth, init, pull, push, diff, activate, runs, run-show) and the VS Code extension's data-source features sign in through an app registration in your own Microsoft Entra ID tenant. FlowForger is open source and ships no built-in client ID, so you register one yourself, once, and point the CLI at it in flowforger.config.json.

You need permission to create an app registration (any user can, unless your tenant restricts it). Granting admin consent needs a Global Administrator, Privileged Role Administrator, or Cloud Application Administrator; if that is not you, hand the permission table below to an admin.

1. Create the registration​

  1. Azure Portal → Microsoft Entra ID → App registrations → New registration
  2. Name: FlowForger CLI (anything you like)
  3. Supported account types: Accounts in this organizational directory only
  4. Redirect URI: leave blank
  5. Register, then copy the Application (client) ID

2. Enable public client flows​

Authentication → Advanced settings → Allow public client flows → Yes → Save.

The CLI is a public client: no secret, your identity comes from a device-code browser sign-in.

3. Add delegated permissions​

API permissions → Add a permission. Everything is Delegated. Microsoft Graph is the first tab; SharePoint, Dynamics CRM, and Microsoft Flow Service are under APIs my organization uses, searchable by name or App ID.

The CLI requests only what a flow actually uses, so add the rows for the connectors you need, or all of them for a registration that covers every flow. After installing the CLI you can ask it directly:

flowforger scopes my-flow.ff.ts   # this flow's permissions
flowforger scopes --all # everything any connector can request
ConnectorAPIDelegated permissions
AlwaysMicrosoft GraphUser.Read
Dataverse, init, pull, push, diff, activate, runs, run-show, env-var resolutionDynamics CRM (00000007-0000-0000-c000-000000000000)user_impersonation
SharePointSharePoint (00000003-0000-0ff1-ce00-000000000000)AllSites.Write
Office 365 OutlookMicrosoft GraphMail.Read, Mail.ReadWrite, Mail.Send, Calendars.Read, Calendars.ReadWrite, Contacts.Read, Contacts.ReadWrite
Office 365 UsersMicrosoft GraphUser.Read.All, User.ReadWrite, People.Read, Sites.Read.All
Office 365 GroupsMicrosoft GraphGroup.Read.All, Group.ReadWrite.All, GroupMember.Read.All, GroupMember.ReadWrite.All
Microsoft TeamsMicrosoft GraphTeam.ReadBasic.All, Team.Create, TeamMember.ReadWrite.All, Channel.ReadBasic.All, Channel.Create, ChannelMessage.Read.All, ChannelMessage.Send, Chat.Create, Chat.Read, Chat.ReadWrite, ChatMember.Read, TeamsActivity.Send, TeamworkTag.ReadWrite, OnlineMeetings.ReadWrite, Calendars.ReadWrite, User.Read.All
Word Online, Excel Online, OneDrive for BusinessMicrosoft GraphFiles.ReadWrite
runs, run-show, run --replay-run, listCallbackUrl() in a flowMicrosoft Flow Service (7df0a125-d3be-4c96-aa54-591f83ff541c)User

Two things people get wrong:

  • SharePoint means the SharePoint API, not Graph. The connector calls the SharePoint REST API, which rejects Graph tokens. Graph's Sites.* permissions do not help; you need AllSites.Write from the SharePoint entry.
  • Add both Read and ReadWrite where both are listed. Entra ID consent is per permission, and a read-only flow requests the narrower one.

flowforger scopes <flow> lists the Flow Service permission only when the flow uses listCallbackUrl(). Add it anyway if you will inspect or replay cloud runs with runs, run-show or run --replay-run.

HttpRequest actions calling Graph directly are not scanned. Add what they need here and list it under auth.additionalScopes.graph in the config.

Finish with Grant admin consent for <tenant>. Without it the first sign-in fails with AADSTS65001.

4. Write the config​

flowforger init --url https://contoso.crm.dynamics.com --client-id <client-id> --sp-url https://contoso.sharepoint.com

init discovers the tenant ID from the Dataverse URL, does the one-time device-code sign-in, maps the environment's connection references, and writes flowforger.config.json. The auth part looks like this:

{
"auth": {
"clientId": "<client-id>",
"tenantId": "<tenant-id>",
"resources": {
"dataverse": "https://contoso.crm.dynamics.com",
"sharepoint": "https://contoso.sharepoint.com"
}
}
}

The token cache​

From here on, --auth on any command is silent: refresh tokens are cached at ~/.flowforger/token-cache.encrypted.json, encrypted for the current OS user with a key kept in the OS credential store (Windows Credential Manager, macOS Keychain, Secret Service on Linux). Anything running as your user can read the cache, the same as with the Azure CLI; copied elsewhere it is unreadable. Delete the file or revoke the user's sessions in Entra ID to invalidate it.

  • Lifetime. A refresh token stays valid for about 90 days of inactivity. After that, the next --auth command shows a device-code prompt again and refreshes the cache.

  • Several tenants. One cache file serves every config. Sign-ins to other tenants are kept side by side, and the CLI tries the configured tenant's account first.

  • Older versions. Up to 0.5.2 the cache was ~/.flowforger/token-cache.json, which later versions cannot read. The first --auth command after an upgrade deletes it and shows a device-code prompt once.

  • Linux keyring. The cache key is stored by the Secret Service (GNOME Keyring, KWallet or KeePassXC). If the keyring is locked, the desktop shows an unlock dialog (under WSL it appears on the Windows desktop); after 3 seconds the CLI prints a hint to answer it, and after 120 seconds it gives up with an error. On a machine with no desktop session to show that dialog (SSH, CI, containers), or with no Secret Service running, opt into an unencrypted cache file instead:

    export FLOWFORGER_TOKEN_CACHE=file

    The cache is then ~/.flowforger/token-cache.plaintext.json, readable only by you (mode 0600). The refresh token is unencrypted on disk, so use this only where the keyring cannot work.

  • VS Code. The VS Code extension keeps its own cache, ~/.flowforger/vscode-token-cache.json, so signing in from the CLI does not sign in the extension, and the other way round.

  • MCP server. flowforger mcp --auth only reads the cache and never prompts. Run any --auth command in a terminal once first.

Troubleshooting​

ErrorFix
AADSTS65001 not consentedGrant admin consent (step 3), or a permission is missing: run flowforger scopes <flow>
AADSTS7000218 client_secret requiredEnable Allow public client flows (step 2)
AADSTS700016 application not foundclientId and tenantId in the config do not belong together
SharePoint 401 after a successful sign-inRegistration has Graph Sites.* instead of SharePoint AllSites.Write
Dataverse 403Your user needs a security role in the environment (for example System Customizer)
--auth requires a config fileRun from the directory containing flowforger.config.json, or pass --config
The system keyring did not respond within 120sAnswer the keyring unlock dialog, or on a headless machine set FLOWFORGER_TOKEN_CACHE=file (token cache)
The encrypted token cache used by --auth could not be loaded (Linux)No Secret Service is running: start a keyring daemon (GNOME Keyring, KWallet, KeePassXC), or set FLOWFORGER_TOKEN_CACHE=file
runs/run-show: The flow-service token was refusedAdd the Microsoft Flow Service User permission (step 3) and grant consent; the flow must also be visible to you

Next: Quick Start to write and run a first flow, or the CLI reference.