Reading The UDID from an iPhone or iPad Through A Web Application

If you want to provide your app for internal testing purposes on a limited number of devices, you need to know the UDID of those devices. This guide shows you how to read the UDID from an iPhone or iPad through a web application.

Published on Thu, August 15, 2024

However, sometimes you can't even physically access a device as it belongs to one of your testers. In that case, you can ask your testers to provide you with the UDID. But that's cumbersome and error-prone. Instead, you can use a web application to read the UDID from the device and send it to your server.

The Process And Requirements

  1. You provide a manifest file for download.
  2. The iPhone or iPad of your user initiates a certificate installation process.
  3. The user installs the certificate.
  4. The device calls the URL provided through the manifest file and transmits the UDID.
  5. You process the UDID in whatever way you need.

Providing The Manifest

The manifest is a simple XML file you can host statically on your server:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <dict>
        <key>URL</key>
        <string>${udidEndpoint}</string>
    <key>DeviceAttributes</key>
    <array>
        <string>UDID</string>
    </array>
</dict>
<key>PayloadOrganization</key>
<string>${organizationName}</string>
<key>PayloadDisplayName</key>
<string>Reading your device's UDID</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadUUID</key>
<string>${payloadUuid}</string>
<key>PayloadIdentifier</key>
<string>${payloadId}</string>
<key>PayloadDescription</key>
<string>Determine the UDID of this device</string>
<key>PayloadType</key>
<string>Profile Service</string>
</dict>
</plist>

Replace the variables with some meaningful values. The ${udidEndpoint} is the URL where the device sends the UDID to. ${organizationName} is the name of your organization. ${payloadUuid} is a static unique identifier, while ${payloadId} is a unique identifier in the form of com.yourorg.getUDID.

The endpoint must be reachable from the device and use HTTPS. Otherwise, the device won't send the UDID.

Reading The UDID

The device will post some PLIST back to your endpoint. You can read it with whatever technology you use on your backend. Here is a sample using Next.js and the plist package:

import { NextRequest, NextResponse } from "next/server";
import plist from "plist";

export async function POST(req: NextRequest) {
  const chunks: Uint8Array[] = [];
  const reader = req.body?.getReader();

  if (reader) {
    let done = false;
    while (!done) {
      const { value, done: doneReading } = await reader.read();
      if (value) {
        chunks.push(value);
      }
      done = doneReading;
    }
  }

  const buffer = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)));

  const xmlContent = buffer.toString("utf-8");
  const result = plist.parse(xmlContent) as any;
  const udid = result?.UDID;

  return NextResponse.redirect(`/udid?udid=${udid}`, {
    status: 302,
  });
}

This code reads the PLIST sent by the device, extracts the UDID, and redirects the user to a page where they can see their UDID. Of course, you could also store the UDID in a database or use it in any other way.

What do you think?
Drop me a line and let me know!