When a client submits a new-employee onboarding form, your techs need to know which Microsoft 365 license to assign and which groups to add the user to. Today that usually means a free-text box, a guess, or a back-and-forth email.
This guide shows how to make those questions dropdowns that list the actual licenses and groups in that client's tenant, kept current automatically. One master onboarding form, tenant-specific choices in every company.
This is not a built-in feature. It combines three things CloudRadial already supports: tokens, comma-separated dropdown options, and the API. A small script (attached to this article) connects them to Microsoft Graph.
How it works
- Dropdown questions in a catalog item accept a comma-separated list of options.
Test A, Test B, Test Cbecomes three choices. - That options field can be a token, for example
@M365Licenses. Tokens resolve company-first, then partner-level, so the same form shows different options in each company. - The CloudRadial API has a
POST /v2/tokenendpoint that creates or updates a token's value. - The attached PowerShell script reads licenses and groups from a Microsoft 365 tenant through Microsoft Graph, formats them as a comma-separated list, and writes them to the token. Schedule it and the dropdowns stay current.
Prerequisites
- Partner admin access to CloudRadial
- Global admin (or Application Administrator) access to the Microsoft 365 tenant you are reading from
- A Windows machine with PowerShell 5.1 or later to run the script (no modules required)
- The script file:
Sync-M365ToCloudRadialTokens.ps1(attached)
Plan on 30 to 45 minutes for first-time setup.
Step 1 - Create the tokens in CloudRadial
For a single-tenant test, create partner-level tokens:
- Go to Partner > Settings > Tokens.
- Add a token named
M365Licenses, type String, with a placeholder value such asLicense A, License B. - Add a second token named
M365Groups, type String, with a placeholder value.
For a real client, create the same two tokens at the company level instead (open the company under Partner > Clients, then Tokens). Company tokens override partner tokens, so each client gets its own list while the form stays shared.
Token names are case-sensitive. The script writes to whatever name you configure, so the name in CloudRadial and the name in the script must match exactly.
Step 2 - Use the tokens in a form
- Open the onboarding catalog item (or any problem report or service request).
- Add or edit a Dropdown question, for example "Which license should this user receive?"
- In the options field, enter
@M365Licensesand nothing else. - Add a second dropdown for groups with options
@M365Groups. - Save, then open the form as a client user. You should see the placeholder values you entered in Step 1 as separate choices.
If you see the literal text @M365Licenses instead of choices, check the token name and capitalization.
Step 3 - Create a CloudRadial API key
- Go to Partner > Settings > Integrations > API.
- Click + Add API Key and name it, for example
M365 Token Sync. - Copy the Public Key and Private Key. The private key is shown once.
Treat this key like an admin password. API keys currently have full read and write access to your portal's API. Store it somewhere secure and never paste it into tickets, chat, or email.
Step 4 - Create an app registration in Microsoft 365
The script needs its own identity to read from the tenant. CloudRadial's existing Microsoft 365 connection cannot be reused for this.
- Sign in to the Microsoft Entra admin center as a global admin.
- Go to Identity > Applications > App registrations > New registration.
- Name it
CloudRadial Token Sync. Under Supported account types, keep the default Single tenant only - [your tenant name]- Note that older portals label this "Accounts in this organizational directory only".
- Leave Redirect URI empty.
- Click Register.
- On the Overview page, copy the Application (client) ID and Directory (tenant) ID from the Essentials section.
- Still on Overview, click Add a certificate or secret next to Client credentials (or expand Manage in the left menu and choose Certificates & secrets).
- On the Client secrets tab, click New client secret.
- In the panel, enter a Description such as
Token Syncand set Expires to 730 days (24 months), then click Add. - The new row in the table has two columns that both look like credentials: Value and Secret ID. The script needs the Value column. Despite the name, the Secret ID is not the secret; it is just a label for it and will not authenticate anything. The Value is a long random string (it often starts with letters like
GG_orabc8Q~); the Secret ID is a GUID with dashes like every other ID in Entra. Click the copy icon next to the Value and paste it somewhere safe right away. It is shown once. If you navigate away before copying it, delete the secret and create another.- If the script later fails with
AADSTS7000215, this is what went wrong.
- If the script later fails with
- In the left-hand menu of the app, click Manage to expand it (it is collapsed by default), then choose API permissions. Do not use the Azure search bar at the top of the page; it searches all of Azure and will not find this. Click Add a permission, then select Microsoft Graph.
- You are asked "What type of permissions does your application require?" with two boxes. Choose Application permissions (the second box, described as "runs as a background service or daemon without a signed-in user"). Do not choose Delegated permissions; the script runs on its own with nobody signed in, and Delegated will fail.
- A searchable list of permissions appears. Type
Organizationin the search box, expand the Organization group, and checkOrganization.Read.All. Clear the search, typeGroup, expand the Group group, and checkGroup.Read.All. Click Add permissions at the bottom of the panel. - Above the permissions table, click Grant admin consent for [tenant] and confirm. Both permissions should show a green check in the Status column.
The two most common mistakes are choosing Delegated instead of Application permissions, and skipping the Grant admin consent button. Either one produces an authorization error when the script runs.
Step 5 - Configure and test the script
- Save
Sync-M365ToCloudRadialTokens.ps1to a folder on the machine that will run it. - Open it in Notepad or PowerShell ISE and fill in the SETTINGS block at the top. Only change the text inside the quotes on the right side of each
=. Do not rename the$Variableon the left.-
$TenantId: the Directory (tenant) ID from the app's Overview page -
$ClientId: the Application (client) ID from the app's Overview page -
$ClientSecretValue: the client secret Value you copied in Step 4 (not the Secret ID) -
$CRPublicKey,$CRPrivateKey: paste the values from Step 3 -
$CRCompanyId: leave0for partner-level tokens. For a client company, use that company's ID (see Step 7). -
$LicenseTokenNameand$GroupTokenName: already set toM365LicensesandM365Groups. Leave them unless you named your tokens something else. No@sign; the@is only used when referencing the token inside a form.
-
- Open PowerShell and change to that folder. On Windows, right-click Start and choose Terminal or Windows PowerShell, then
cdto the folder (for examplecd "C:\Users\you\Downloads"). On macOS or Linux, install PowerShell 7 first (brew install --cask powershell, or the.pkgfrom the PowerShell GitHub releases page), then open Terminal, typepwsh, andcdto the folder. Run a dry run:
.\Sync-M365ToCloudRadialTokens.ps1 -DryRun
(On macOS or Linux use ./ instead of .\.)
This reads from Microsoft 365 and prints both lists without writing anything to CloudRadial. Confirm the licenses and groups look right.
- Run it for real:
.\Sync-M365ToCloudRadialTokens.ps1
- Open the form as a client user. The dropdowns now show the tenant's licenses and groups.
If PowerShell refuses to run the script, run this once and try again:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
Options in the SETTINGS block
-
$IncludeSeatCounts: show "Microsoft 365 E3 (12 of 25 available)" instead of just the name. Useful for techs, but the count is only as fresh as the last run. -
$SkipZeroSeatSkus: hide SKUs with no purchased seats, such as expired trials. -
$GroupNameFilter: a wildcard such asSG-*to include only groups that follow your naming convention. -
$IncludeSecurityGroupsand$IncludeM365Groups: include or exclude either type. Distribution lists are never included.
Step 6 - Schedule it
Run the script on a schedule so the lists stay current.
- Open Task Scheduler on the machine and click Create Task.
- General tab: name it, select Run whether user is logged on or not.
- Triggers tab: New, Daily, pick an overnight time.
- Actions tab: New, Action: Start a program.
- Program:
powershell.exe - Arguments:
-ExecutionPolicy Bypass -File "C:\Path\To\Sync-M365ToCloudRadialTokens.ps1"
- Program:
- Save. Right-click the task and choose Run to confirm it works.
Alternatives such as Azure Automation or your RMM's script scheduler work the same way.
Step 7 - Scaling to multiple clients
The script is written for one tenant writing to one company. To cover multiple clients:
- For each client, create the two tokens at the company level (Step 1) and find the company's ID. The easiest way is Swagger at api.us.cloudradial.com/swagger: authorize with your API key and run
GET /v2/company. Each result has acompanyIdand aname. Note that your own MSP company appears in this list with its own ID (often1). That is not the same as0, which means partner-level. Use0for global tokens and the client'scompanyIdfor company tokens. - For each client tenant, either create a separate app registration (Step 4) in that tenant, or convert the app to multi-tenant and grant consent in each client tenant. Per-tenant registrations are simpler to understand; a multi-tenant app is less to maintain at scale.
- Save one copy of the script per client with that client's tenant credentials and
$CRCompanyId, and schedule each one. Or, if you are comfortable with PowerShell, wrap the script in a loop over a list of clients.
Limitations and things to know
-
Commas are replaced. Because commas separate options, the script replaces any comma inside a group or license name with
-. A group namedSales, EMEAappears asSales - EMEA. - Values are a snapshot. Seat counts and group lists are only as current as the last run.
- Client secrets expire. Set a reminder before the 24-month expiry. When the secret expires the script fails and the dropdowns silently stop updating.
- API keys are all-or-nothing. The key the script uses can read and write everything in your portal's API. Restrict access to the machine and folder that hold the script.
- Dropdowns store the label, not an ID. The submitted ticket contains the friendly name your tech sees, which is exactly what they need to act on.
- This is a partner-built integration. CloudRadial supports the tokens, forms, and API endpoints used here. The script and the Microsoft 365 app registration are yours to maintain.
Troubleshooting
| Symptom | Likely cause |
|---|---|
AADSTS7000215 or invalid client secret |
Wrong secret value copied, or the Secret ID was copied instead of the Value |
Authorization_RequestDenied or 403 from Graph |
Permissions are Delegated instead of Application, or admin consent not granted |
| 401 from CloudRadial | Public or private key wrong, or key deleted |
Form shows @M365Licenses as text |
Token name mismatch or wrong capitalization |
| Dropdown shows one long option | Value is not comma-separated; check the token value in Partner > Settings > Tokens |
| Dropdown shows old values | Scheduled task not running; open Task Scheduler and check Last Run Result |
Same pattern, other lists
Nothing here is specific to Microsoft 365. Any system you can read from a script can feed a dropdown: departments or office locations from an HR system, hardware models from your distributor, products or agreements from your PSA. Create a token, point a dropdown at it, and write to POST /v2/token.
Comments
0 comments
Article is closed for comments.