Solving Corporate Device Identifier Headaches


I Built a Web App to Fix One of Intune’s Annoyances

If you use Autopilot v2 (Device Preparation Policies), or you don’t use Autopilot at all but still want to control which devices can enroll to your tenant, you’re stuck with Corporate Device Identifiers (CDIs). Unlike Autopilot v1 where you can (pre-)register hardware hashes, CDIs require manufacturer, model, and serial number for every Windows device. That means manually building CSV files and running PowerShell scripts on new hardware just to get the exact model name string that Intune will accept.

I built Intune-DeviceIDApp to fix that. It’s an open source web app that lets you pick manufacturer and model from auto-synced catalogs, enter serial numbers with format validation, queue up as many devices as you need, and push them straight to Intune via the Graph API. No more manual formatting of CSV files, no PowerShell, no guessing at model string formatting.


What the Problem Actually Looks Like

Intune’s corporate identifier restrictions work by pre-registering specific devices (manufacturer + model + serial). Any device that doesn’t match gets blocked from enrolling. It’s a solid feature in principle.

The pain is operational. The manufacturer/model strings have to match exactly what Intune expects, and there’s no built-in way to look them up. So you end up either copy-pasting from vendor sites and hoping the formatting is right, or running PowerShell on each new model to extract the correct string. This really gets tiring at scale.


What the App Does

The app has two main pieces: a device catalog and an Intune importer.

The catalog automatically downloads and parses hardware model lists directly from Dell, HP, and Lenovo, updated daily. So instead of guessing at model strings, you pick a manufacturer from a dropdown and a model from a filtered list. The app validates serial number formats too (Dell’s 7-character service tags, HP’s 10-character serials) and warns you if something looks off.

The importer talks to the Microsoft Graph API using OAuth2. You need an Entra App Registration with DeviceManagementServiceConfig.ReadWrite.All . Enter your tenant specific variables once in the settings page, test the connection, and you’re good. Add devices to a queue, review them, push to Intune.

A few other things worth mentioning:

  • Batch queue with CSV export if you still want the file for your records, or you want to upload the CSV manually.
  • Quick Load that recalls your last-used manufacturer/model for fast repeat entries
  • Dark mode by default, light mode toggle if you prefer that for some reason :)
  • Secure — the backend isn’t exposed to the host network; only Nginx is

The Stack

The whole app runs as a Docker Compose stack. Nginx sits in front so the API isn’t directly exposed. The architecture is straightforward:

Browser → Nginx (port 8090) → FastAPI backend → SQLite / Graph API / Vendor catalogs
  • Frontend: React 19 + Vite, Mantine UI
  • Backend: Python 3.12, FastAPI, Uvicorn, APScheduler
  • Database: SQLite (WAL mode) — stores the device catalog and Azure credentials
  • Infra: Docker Compose, Nginx as reverse proxy

Deploying is a one-liner:

git clone https://github.com/ankr98/Intune-DeviceIDApp.git
cd Intune-DeviceIDApp
docker-compose up -d

Or if you’re running Portainer, point it at the repo and deploy from there.


The Catalog Sync Engine

Device manufacturers unfortunately don’t publish a simple list of correctly formatted model names anywhere (I’ve checked). As such, I am working around this by extracting the values from the driver/update catalogs they publish for their support tools. Each vendor structures this differently:

  • Lenovo publishes a driver catalog (catalogv2.xml) where each entry contains a supported model string — The app parses these out of the XML attributes
  • HP publishes two CAB files (each containing XML manifests) that the app merges for good model coverage
  • Dell ships a large CAB file (~100 MB) with a similar XML structure — The app uses iterative streaming to parse it without loading the whole list into memory

All three sync every 24 hours via APScheduler. New model strings are inserted as they’re discovered; duplicates are ignored via a unique constraint on (manufacturer, model_name). Hands-off once it’s running.

One known fragility with this approach: the catalog URLs are hardcoded. Manufacturers might change the URL of their download endpoints, and when/if that happens the sync will fail until the sync engine is updated with new URLs. There’s no self-healing mechanism. if Lenovo or Dell moves their catalog file, the scheduler keeps hitting a dead URL and new models stop appearing. It’s a maintenance cost I’ve accepted for now.


Azure Setup

Simples stuff. App Registration in Entra ID, DeviceManagementServiceConfig.ReadWrite.All application permission. Paste the Tenant ID, Client ID, and Client Secret into the Settings page, hit Test Connection and save.

One small thing to be aware of: the client secret is stored in plaintext in the SQLite database. The backend masks it when returning it to the frontend, but make sure your Docker volume is properly secured if this is running in a shared environment.


How It Was Built

I built this using Gemini and Claude Code. The entire project took a fraction of the time it would have taken to do alone.


Get It

The repo is on GitHub: ankr98/Intune-DeviceIDApp

Licensed under AGPL-3.0. If you manage Intune at any scale, give it a try and let me know what you think. Issues and PRs welcome.