Skip to content

Google Workspace Account Request Workflow

A step-by-step guide to creating a self-service workflow that lets users request a Google Workspace account through the request catalog, routes it for approval, and automatically provisions the account and links it to the requestor's Floh identity.

This guide is also a useful end-to-end example workflow that exercises most of Floh's workflow-authoring features: request catalog publication, submitter interpolation, connector steps with design-time validation, transform-step sandboxing, approval routing, identity linking, and notifications.

Prerequisites

  1. A Google Workspace connector configured and passing the test connection — see Configuring a Google Workspace Connector.
  2. A group named google-account-approvers (or similar) with at least one member. Create it under Groups in the admin sidebar.
  3. The workflow:manage permission on your admin account.
  4. At least one organizational unit (OU) in Google Admin Console you want new accounts to land in — note its full path (for example, /TEST). If you're unsure, leave the default / for now; the designer typeahead (Step 3.4) will list the valid options.

Overview

Portal Submit
Start
Derive Account Details (transform)
Approval Gate (group: google-account-approvers)
    ├── approved ──► Create Google Account (connector)
    │                    │
    │                    ▼
    │                Link Google Identity (identity_link)
    │                    │
    │                    ▼
    │                Notify — Account Created (notification)
    │                    │
    │                    ▼
    │                  End
    └── rejected ──► Notify — Rejected (notification) ──► End

Step 1 — Create the workflow

  1. Navigate to Workflows and click New Workflow.
  2. Fill in:
Field Value
Name Google Workspace Account Request
Description Self-service request for a new Google Workspace account
Category User Self-Service
Subject Variable targetUser (auto-populated by the category)
Error Strategy stop
Trigger manual

The User Self-Service category is the preferred way to author portal-submitted workflows that target the requesting user: the designer automatically creates a targetUser variable (a user-type variable flagged as self-service) and wires it as the subject variable. You don't need to add it manually. The category also handles admin submit-on-behalf-of flows — onBehalfOfUserId rebinds targetUser while {{submitter.*}} continues to reflect the real caller, so there is no need to switch categories for that case. The plain User category is only for workflows whose subject is not the self-service targetUser (e.g. an approval workflow targeting a user different from the submitter where the submitter picks the target explicitly). See docs/workflows/user-self-service.md for details.

  1. Assign the workflow to your project.

Step 2 — Define variables

Open the Variables tab. The User Self-Service category has already seeded a locked targetUser row for you; add the rest:

Name Type Required Default Value Description
targetUser Target User yes — (auto-provided) The requesting user (auto-filled from session)
firstName String yes {{submitter.firstName}} First name for the Google account
lastName String yes {{submitter.lastName}} Last name for the Google account
justification String no Business justification (shown to approvers)

Notes:

  • The Target User row is auto-provided because you picked the User Self-Service category. The designer locks it (you can't rename or re-type it) so the engine's implicit synthesis doesn't fall out of sync. Under the hood it's a user-typed variable with selfService: true. In scripts and templates you can reference its attributes via {{targetUser.id}}, {{targetUser.email}}, {{targetUser.displayName}}, etc.
  • On catalog submit the portal form hides self-service variables and the server binds them to the authenticated submitter (or to the on-behalf-of target for admins holding the workflow:submit_on_behalf_of permission — see the user-self-service doc for details). Any caller-supplied value is ignored.
  • On String variables the Default Value field accepts literal text, a {{submitter.*}} expression, or a mix of the two. Supported attributes: {{submitter.firstName}}, {{submitter.lastName}}, {{submitter.email}}, {{submitter.displayName}}, {{submitter.id}}. {{submitter.*}} always reflects the real authenticated caller — even when an admin submits on behalf of another user — so audit trails and notification bodies can't be spoofed via the on-behalf-of override.
  • The same pre-fill applies in the admin Test Run dialog (Step 6), so you can test the workflow exactly the way a requestor will experience it.

Step 3 — Add the workflow steps

3.1 — Start

Type: start. Entry point.

3.2 — Derive Account Details

Type: transform.

Config Field Value
Script See below
Outputs primaryEmail, initialPassword

Script:

const targetUser = floh.variables.targetUser;
const firstName = floh.variables.firstName;
const lastName = floh.variables.lastName;

// Derive the primary email from the target user's existing email local-part so
// there's no collision with an existing Google user. Replace the domain with
// your Google Workspace primary domain.
const localPart = targetUser.email.split("@")[0];
const primaryEmail = `${localPart}@your-workspace-domain.com`;

// Generate a 24-character initial password. Google rejects passwords shorter
// than 8 chars; we include at least one char from each class for safety.
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%";
let initialPassword = "";
for (let i = 0; i < 24; i++) {
  initialPassword += charset.charAt(Math.floor(Math.random() * charset.length));
}

return { primaryEmail, initialPassword };

Replace your-workspace-domain.com with your actual primary Google Workspace domain.

Tip — test the script before saving: expand the Test Script panel under the transform step. The Mock Variables (JSON) textarea is prepopulated from your workflow variables (including the targetUser object, the submitter snapshot, and resolved {{submitter.*}} defaults), so you can run the script against realistic inputs and inspect the primaryEmail/initialPassword output without leaving the designer. Click Load sample to regenerate the mock if you change variable definitions.

3.3 — Approval Gate

Type: approval.

Config Field Value
Approvers group:google-account-approvers

The designer shows a hint under the field resolving the group UUID to its friendly name (e.g., Resolves to: group:google-account-approvers) so you don't need to memorize UUIDs.

Transitions:

  • success → Create Google Account
  • error → Notify — Rejected

3.4 — Create Google Account

Type: connector.

Config Field Value
Connector your Google Workspace connector instance
Command createUser
primaryEmail {{primaryEmail}}
firstName {{firstName}}
lastName {{lastName}}
password {{initialPassword}}
orgUnitPath a literal path (e.g. /TEST) — see below
Output Key provisionAccount

The orgUnitPath field has a typeahead dropdown backed by the connector's listOrgUnits command. Click into the field to see the live list of organizational units from your Google Admin domain; pick one to avoid INVALID_OU_ID at runtime. If you type a literal path, the designer validates it on Save using getOrgUnit and surfaces an explicit error like Create Google Account — orgUnitPath: The organizational unit "/DoesNotExist" was not found. Invalid values block publish; the check is skipped for {{…}} expressions (those are validated at runtime).

Google automatically sets changePasswordAtNextLogin: true, so the provisioned user must change their password on first sign-in.

The step produces three output variables (promoted flat into the workflow namespace): created, userId, primaryEmail. Because we set Output Key to provisionAccount, the raw API result is also available under {{provisionAccount}} if you need it.

Type: identity_link.

Config Field Value
User ID {{targetUser.id}}
Connector your Google Workspace connector instance
External ID {{userId}}
External Email {{primaryEmail}}
External Display Name {{firstName}} {{lastName}}

identity_link writes a row to the user_external_identity table, formally linking the Floh user ({{targetUser.id}}) to their account in the connector-managed external system. Once linked, the connector's sync passes will recognize the same account and keep downstream profile attributes (department, orgUnitPath, etc.) in sync.

Common pitfall: User ID must be the Floh user UUID ({{targetUser.id}}), and External ID must be the Google user ID from the previous step ({{userId}}). Swapping them produces a foreign-key violation. The designer's autocomplete lists both correctly from the resolved step outputs.

3.6 — Notify — Account Created

Type: notification.

Config Field Value
Recipient Type internal
Recipient User {{targetUser.id}}
Subject Override Your Google Workspace account has been created
Custom Body Your Google Workspace account has been provisioned at {{primaryEmail}}. You will be prompted to set your password on first sign-in. Justification: {{justification}}

3.7 — Notify — Rejected

Type: notification.

Config Field Value
Recipient Type internal
Recipient User {{targetUser.id}}
Subject Override Google Workspace account request not approved
Custom Body Your request for a Google Workspace account was not approved. Contact your manager or IT for more information.

3.8 — End

Type: end. Exit point.

Step 4 — Wire the graph

In the Graph tab, draw these transitions:

  1. Start → Derive Account Details
  2. Derive Account Details → Approval Gate
  3. Approval Gatesuccess → Create Google Account
  4. Approval Gateerror → Notify — Rejected
  5. Create Google Account → Link Google Identity
  6. Link Google Identity → Notify — Account Created
  7. Notify — Account Created → End
  8. Notify — Rejected → End

Step 5 — Save and validate

Click Save. The designer runs two validation passes:

  1. Static validation — unreachable steps, duplicate output keys, missing required fields on every step type (including identity_link's required User ID, Connector, and External ID).
  2. Connector field validation — any literal step-config value that references a connector-managed resource (like orgUnitPath) is validated against the connector in-place. Errors appear in the banner as <step> — <param>: <error> and block publish until resolved.

Fix any errors and save again.

Step 6 — Test Run before publishing

You can exercise the workflow end-to-end from the admin UI without publishing it:

  1. On the workflow detail page, click Test Run.
  2. A dialog lists the workflow's input variables. The targetUser variable is hidden (it's auto-filled from your session), and firstName/lastName are pre-filled from the {{submitter.*}} defaults. Fill in justification if required.
  3. Click Start Run.
  4. Watch the run progress in the Runs tab. Approve the pending task from your task inbox, then confirm the Google account was created (check Google Admin Console) and that the new link shows up under Users → {targetUser.displayName} → External Identities (also exposed at GET /users/{targetUser.id}/external-identities).

If any step fails, expand its variables in the run viewer and inspect the error. Common fixes:

Symptom Fix
Create Google Account fails with INVALID_OU_ID The literal orgUnitPath doesn't exist. Use the typeahead or run the listOrgUnits command on the connector's Commands tab to see valid paths.
Save fails with orgUnitPath: Google API error (403): insufficientPermissions The connector's Domain-wide Delegation entry is missing the admin.directory.orgunit.readonly scope. Add it in Google Admin Console → Security → API controls → Manage Domain-wide Delegation, save, and retry. See Google Workspace setup → Grant Domain-Wide Delegation.
Create Google Account fails with Entity already exists A Google user with that primary email already exists. Google retains deleted accounts for several days — pick a different local-part or wait.
Link Google Identity fails with a foreign-key violation User ID is the Google numeric ID instead of the Floh UUID. Change it to {{targetUser.id}}.
Link Google Identity fails with "Connector not found" The Connector value is a name that doesn't match. Pick the connector from the dropdown or paste its UUID.
Approval never transitions The approvers group is empty. Confirm google-account-approvers has at least one member, or let the configured approval-fallback rule route to the system admin group.

Step 7 — Publish and add to the catalog

  1. Click Publish to activate the workflow.
  2. Open the Catalog tab on the workflow detail page.
  3. Configure:
Field Value
Published checked
Icon person_add
Description Request a new Google Workspace account. Requires approval from IT.
Tags google, account, provisioning
Submission Groups leave empty (all authenticated users), or restrict to specific groups

Changes auto-save after a short debounce — no separate Save click is required on this tab.

What users see

When a user opens the Request Catalog in the portal:

  1. They see the "Google Workspace Account Request" card.
  2. They click Submit Request.
  3. A form appears with:
  4. firstName (pre-filled from {{submitter.firstName}})
  5. lastName (pre-filled from {{submitter.lastName}})
  6. justification (optional)
  7. The targetUser field is invisible — it is auto-populated with their user ID on submission.
  8. After submission, the request appears in the google-account-approvers group's task inbox.
  9. Once approved, the target user receives the "account created" notification with their new primaryEmail and sign-in instructions.

Identity linking (how it works)

The identity_link step writes a row to the user_external_identity table with the Floh user ID, connector ID, and the Google user ID as external_id. This is the canonical way to link a Floh user to an account in a connector-managed external system; it supersedes the older pattern of stashing the Google ID as a profile custom attribute.

Two complementary linking paths keep the graph accurate:

  1. OIDC sign-in — when the user first signs in via Google (https://accounts.google.com as the OIDC issuer), Floh's auth callback sets upstream_issuer and upstream_id from the ID token claims on the user record itself.
  2. Connector sync — if user sync is configured on the Google Workspace connector with the Email or Email + Issuer match strategy, each sync pass re-confirms (or creates) the user_external_identity row. Provisioning workflows that use identity_link are already compatible with this path.

What's next