iOSでAndroidのSSAIDのような取得可能な識別子はあるのか調査してみた

iOSでAndroidのSSAIDのような取得可能な識別子はあるのか調査してみた

2025.12.09

iOSアプリ開発において、デバイスやユーザーを識別する必要が出てくることがある。特にAndroid開発経験者からよく聞かれるのが「AndroidにあるSSAID(Android ID)のような、再インストール後も永続する識別子はiOSにもあるのか?」という質問だ。

結論から言うと、iOSには公式にサポートされた「再インストール後も永続する識別子」は存在しない。これはAppleのプライバシーファースト設計による意図的なものである。

本記事では、iOSで利用可能な識別子の種類、取得条件、変更タイミング、そしてAndroidとの違いについて詳しく解説する。

Android SSAIDとは?

比較対象となるAndroidのSSAID(Settings.Secure.ANDROID_ID または Android ID)について簡単に触れておく。

SSAIDはAndroid 8.0以降で利用可能なデバイス識別子で、最大の特徴はアプリを再インストールしても同じIDが取得できる点だ。ユーザー許諾不要で、アプリごと・署名鍵ごとに異なるIDが生成される。デバイスの初期化や署名鍵の変更がない限り、IDは永続する。

https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID

この「ユーザー許諾なし」で「再インストール後も同じID」という特徴が、iOSには存在しない。

iOSで利用可能な識別子一覧

iOSで取得可能な主な識別子を表にまとめた。

識別子 スコープ ユーザー許可 再インストール後 主用途
UDID デバイス全体 不要 - 廃止済み
IDFA デバイス全体 ATT許可が必須[1] 変更可能 広告トラッキング
IDFV ベンダー単位 不要 変更される[2] 分析・認証
DeviceCheck デバイス全体 不要 永続(2ビット) 不正検知
App Attest アプリ単位 不要 永続 整合性検証
Firebase FID アプリ単位 不要 変更される Firebase内部
APNsトークン アプリ単位 不要 変更可能性あり プッシュ通知
Keychain UUID 設定可能 不要 永続(非公式) カスタム用途

1. UDID(廃止済み)

UDID(Unique Device Identifier)は、かつて存在したデバイス固有の識別子だ。iOS 5(2011年)で非推奨となり、2013年5月からApp Storeでの使用が禁止、iOS 7でAPIが完全に削除された。

NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];

広告ネットワークによるクロスアプリトラッキングの悪用、ユーザープライバシーの侵害、ユーザーが任意にIDをリセットする手段がないといった理由から廃止された。現在、UDIDを使用するアプリはApp Store審査で即座に却下される。廃止についてはApple Developer Newsで告知されている。

UDIDが非推奨になったあとMACアドレスを利用する方法が一時期使われていたことがあるが、iOS 7で常に固定値が返ってくるようになり、2025年現在利用不可能となっている。

2. IDFV(Identifier for Vendor)

IDFVは現在最も一般的に使用される識別子で、ユーザー許諾・ATT許可が不要で利用可能だ。同一ベンダー(開発者)のアプリ間で共有される。

let idfv = UIDevice.current.identifierForVendor?.uuidString
// 例: 95290AB7-FC58-4CC9-8B86-F8F38505B512

ユーザーが同一ベンダーのアプリを全て削除した場合、IDFVはリセットされる。つまり、AndroidのSSAIDのような完全な永続性はない。ベンダーがアプリを1つしかリリースしていない場合、再インストール後にIDFVは変更される。

IDFVの一意性はBundle Identifierの最初の2コンポーネント(例:com.example)で決定される。詳細な仕様や変更タイミングについてはAppleの公式ドキュメントを参照してほしい。

3. IDFA(Identifier for Advertisers)

IDFAは広告用の識別子だが、iOS 14.5以降はApp Tracking Transparency(ATT)の許可が必須となった。Info.plistにNSUserTrackingUsageDescriptionの設定が必要だ。

import AdSupport
import AppTrackingTransparency

ATTrackingManager.requestTrackingAuthorization { status in
    if status == .authorized {
        let idfa = ASIdentifierManager.shared().advertisingIdentifier
        print("IDFA: \(idfa.uuidString)")
    }
}

ユーザーがトラッキングを許可しなかった場合はゼロ値(00000000-0000-0000-0000-000000000000)が返る。ATT許諾ダイアログはアプリごとに1回のみ表示され、Flurryの調査によると全体の許可率は約25〜35%程度とされている。ユーザー全員から取得できるわけではないと考えておくべきだ。

IDFAはユーザーが任意のタイミングでリセット可能なため、Appleのドキュメントでは保存せずに利用ごとにアクセスすることが推奨されている。詳細はAppleの公式ドキュメントを参照してほしい。

4. DeviceCheck

DeviceCheckは、開発者(ベンダー)ごと・デバイスごとに2ビット(4状態)のデータをAppleサーバーに保存できるフレームワークだ。同一開発者の複数アプリで2ビットを共有する点に注意が必要だ。アプリ削除後もデータは永続するが、識別子ではなく状態保存のためのAPIである。

import DeviceCheck

let tokenData = try await DCDevice.current.generateToken()
let token = tokenData.base64EncodedString()
// このトークンをサーバーに送信し、サーバー側でApple APIと連携

生成されるトークンは一時的なもので、毎回異なる値が返る。サーバー側でAppleのAPIを呼び出して2ビットの読み書きをおこなう仕組みのため、デバイスを一意に識別する用途には使えない。主な用途は不正利用の検出や一度限りの特典管理だ。詳細はAppleの公式ドキュメントを参照してほしい。

5. App Attest

App Attestは、アプリの整合性を検証するためのフレームワークだ(iOS 14+)。Secure Enclave内で暗号鍵を生成し、そのアプリが正規のインスタンスであることをAppleが証明する仕組みだ。

import DeviceCheck

let service = DCAppAttestService.shared
guard service.isSupported else { return }
let keyId = try await service.generateKey()
let attestation = try await service.attestKey(keyId, clientDataHash: serverChallenge)
// attestationをサーバーで検証

DeviceCheckと同様にサーバー側での検証が必須であり、シミュレータでは動作しない。主な用途はAPI保護や改ざんアプリからの不正アクセス防止だ。識別子として使用することは想定されていない

DeviceCheckとの違いは、DeviceCheckが「デバイスの状態を2ビットで保存」するのに対し、App Attestは「アプリが改ざんされていないことを証明」する点だ。両者は補完的に使用されることが多い。詳細はAppleの公式ドキュメントを参照してほしい。

6. Firebase Installation ID(FID)

Firebaseを使用している場合に自動生成される識別子だ。

import FirebaseInstallations

let id = try await Installations.installations().installationID()
print("Firebase Installation ID: \(id)")

FIDはアプリの再インストールやキャッシュクリア時に変更されるため、SSAIDの代替にはならない。また、270日間非アクティブだった場合はバックエンド側で削除される旨がFirebaseのドキュメントに明記されている。Firebase内部で使用される識別子であり、永続的なデバイス識別には適さない。

7. APNsデバイストークン

プッシュ通知用のトークンだ。トラッキング目的での使用は禁止である。

// AppDelegate.swift
func application(
  _ application: UIApplication,
  didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    print("APNs Token: \(token)")
}

Appleの公式ドキュメントでは「デバイストークンをローカルにキャッシュせず、必要な時にシステムから取得する」ことが推奨されている。トークンはOSアップデートやデバイス復元時に変更されるためだ。

8. Keychain UUID

自前でUUIDを生成してKeychainに保存する方法だ。技術的には可能だが、公式な手法ではないため実装方法については割愛する。

この方法にはいくつかの問題がある。まず公式APIではなく、Appleの仕様変更によって将来的に動作しなくなる可能性がある。また、トラッキング目的と判断されればApp Store審査で却下されるリスクもある。さらにkSecAttrAccessibleの設定次第ではデバイスバックアップで引き継がれてしまう点にも注意が必要だ。

iOS 10.3 Beta時に、Appleは一度「アプリ削除後にKeychainデータも削除する」という仕様変更を試みた。Apple Developer Forumsには「これは、ユーザーのプライバシーを保護するためのiOS 10.3における意図的な変更です。ユーザーを特定できる情報は、その情報を作成したアプリが削除された後もデバイスに残されるべきではありません」という記載があった。しかし、Beta 7でこの変更は撤回され、元の挙動(Keychainデータは削除されない)に戻った。

2025年12月時点(iOS 26.1)でもこの動作は継続しているが、Appleは別のスレッドで「Keychainドキュメントはこのケースで何が起こるかを一度も明記していない」「アプリ削除時にKeychainアイテムが残ることはAPIの契約の一部ではなく、常に実装の詳細だった」と明言している。つまり「再インストールでも消えない」というのは仕様ではなく、昔からの挙動でそうなっているだけだ。この動作に依存する場合は、将来変更される可能性を考慮してアプリを設計する必要がある。

なぜiOSにはSSAID相当のものがないのか?

AppleのプライバシーポリシーとApp Store審査ガイドラインから読み取ると、これは意図的な設計だと考えられる。

アプリを削除するということは「私はこのアプリとの関係を断ち切りたい」というユーザーの明確な意思表示だ。再インストール後も追跡可能な識別子は、この意思に反する。また、永続的なIDは広告ネットワークによるクロスアプリトラッキングに悪用される可能性がある。IDFAは存在するが、iOS 14.5以降はATT許可を必須にして、任意のタイミングでリセット可能とすることでユーザーの選択権を確保している。

Appleはユーザーコントロールを重視しており、設定アプリから広告IDをリセットできる機能や、アプリ削除でデータを完全に削除できる権利、いわゆる「忘れられる権利」を尊重する設計思想が根底にある。

どうしても永続IDが必要な場合はどうすべきか?

最も適切なのはユーザーアカウントの作成を促すことだ。ログイン方法は簡単であればあるほどよいので、Sign in with Appleやメールアドレス・電話番号認証を利用するのがよいだろう。自前でIDを生成してKeychainに保存する方法もあるが、前述の通り短期的には動作するものの長期的なリスクが存在する。

Privacy Manifestsへの対応も忘れずに

ここまでAppleのプライバシーファーストな設計思想について触れてきた。iOSアプリを開発する上で忘れてはいけないのが「Privacy Manifests」である。アプリがどのような権限を必要とし、各種データをどのような目的で利用しているかをユーザーに明示しなければいけなくなった。

iOS 17以降、すべてのアプリとSDKは PrivacyInfo.xcprivacy ファイルで識別子の使用を宣言する必要がある。詳細については、少し前に書いた以下の記事を参照してほしい。

https://dev.classmethod.jp/articles/support-privacy-manifests-for-ios-app/

ただし、2025年12月現在 PrivacyInfo.xcprivacyを組み込んでいるアプリについては厳しくチェックされるが、PrivacyInfo.xcprivacyを組み込んでいなくても審査には通る状況が続いている。さすがにプライバシーマニフェストの仕組みが廃止されるとは思わない。ある日突然アプリの審査を拒否されるようになっても困るため、未対応のアプリがあれば対応しておくのがよいだろう。

まとめ

iOSにはSSAID相当のものは存在しない。これはAppleのプライバシーファースト設計の結果で、意図的に用意されていない。

AndroidのSSAIDに依存した設計をiOSに移植する場合は、ユーザーアカウントシステムの導入が最も確実だろう。Keychain UUIDは短期的には動作するが長期的なリスクがあることは前述した通りだ。

一般的なユースケースと使用すべき識別子を以下にまとめた。

ユースケース 推奨識別子
再インストール後も永続したい ❌ 公式には存在しない → ユーザーアカウント推奨
アプリ内分析 ✅ IDFV
広告トラッキング ✅ IDFA(ATT許可必須)
不正検知 ✅ DeviceCheck
アプリ整合性検証 ✅ App Attest

iOSのプライバシーモデルは、Androidとは根本的に異なる。「AndroidのSSAID相当のものがないから困る」ではなく、「iOSのプライバシーモデルに合わせた設計をする」という発想の転換が必要だ。

本記事ではiOSを主に扱ったため詳しく触れていないが、Androidでも広告用途ではAdvertising ID、アプリ分析ではApp Set ID、非広告用途ではFIDまたはGUIDが推奨されており、永続識別子から離れる方向に進んでいるように思う。

https://developer.android.com/identity/user-data-ids?hl=ja

ユーザーのプライバシーを尊重した設計は、長期的にはユーザーの信頼を獲得し、アプリの成功につながるだろう。用途に応じて適切な識別子を選択してほしい。

参考資料

脚注
  1. ATT許可されたアプリ間で共通のIDが利用できる ↩︎

  2. IDFVは当該ベンダーのアプリがすべて削除されるとリセットされる。ベンダーがアプリを1つしかリリースしていない場合は再インストール後に変更される ↩︎

この記事をシェアする

FacebookHatena blogX

関連記事