LoginSignup
9
11

More than 1 year has passed since last update.

iOSのリセマラを防ぐ

Last updated at Posted at 2021-06-09

要約

DeviceCheckを使ってリセマラを防ぎます

概要

リセマラ(リセットマラソン)を防ぐために、DeviceCheckを使って端末チェックを行います。
ここでいうリセマラとは、アプリをアンインストール/インストールを繰り返して、初回限定の利益を何度も受ける行為を指します。

端末チェックの結果、「この端末ではまだ初回限定の利益を受けていない」と判断できた場合、初回限定の特典を与えます。
DeviceCheckを使った端末チェックはiOSアプリ単体で完結するわけではなく、さまざまな手順が必要になります。
また、仕組み上、中古端末や譲渡を受けた端末では初回限定の判断はできないかと思われます。

アプリの流れ

  1. iOSアプリがDeviceCheckを利用して、トークンを発行する
  2. iOSアプリは、サーバーに対してトークンを送信する
  3. サーバーは、JWTを生成して、トークンとともにApple APIへリクエストを送る
  4. サーバーは、Apple APIの結果を受け取り、iOSアプリへ返す
  5. サーバーのレスポンスを元に、初回限定の利益を与える/与えない

端末チェックの手順

p8編

iOS Developer centerで、Keysを作成することができる権限のアカウントが必要です。
iOS Developer centerでDeviceCheck用のP8ファイルを作成する必要があります。
下記は手順の一例です。iOS Developer centerに変更が行われている場合は適宜読み替えてください。

  • Certificates, Identifiers & Profiles の Keysを選択
  • Create Keyを押下
  • Register a New Keyで、Key Nameを任意、DeviceCheckをチェック
  • Downloadで、p8ファイルをダウンロードする。これはサーバーサイドで利用します。

サーバ編

先ほどダウンロードしたp8ファイルが必要です。

サーバーサイドでは、p8ファイルiOS Developer centerで生成したKeyのKey IDiOS Developer centerのチームIDが必要になり、組み合わせてJWTを生成し、iOSアプリからデバイストークン受信時、Authorizationヘッダーに Bearer <GeneratedJWT> を付与して、bodyにPayloadを付与してAppleのAPIへリクエストを行います。

APIには query_two_bitsupdate_two_bits があり、まず query_two_bits を確認して、200 Bit State Not Foundであれば初回限定とみなせます。
必要であればこの時点でupdate_two_bitsで初回特典を付与済みとすればよいでしょう。

AppleのDevice check用APIについての公式はこちらです。

JWTを生成するライブラリは各種環境で選定してください。
以下はJWT生成時のHEADERとPAYLOADの例です。

HEADER例

{
  "alg": "ES256",
  "kid": "(iOS Developer centerで生成したKeyのKey ID)"
}

PAYLOAD例

{
  "iss": "(iOS Developer centerのチームID)",
  "iat": 1573712797,
  "exp": 1573716397
}

bodyの例

{
    "device_token": "Base 64エンコードされた、iOSから送られてきたデバイストークン",
    "transaction_id": "C94E26BD-714B-4D3F-8733-E86A790C0F8D",
    "timestamp": 1573707063000
}

iOSアプリ編

DeviceCheckは実機じゃないと動作しません。プロビジョニングもDeviceCheckのp8ファイルを作ったチームIDと等しい必要があります。
iOSアプリでは DCDevice.current.generateToken を実行し、生成したトークンをサーバーへ送信し、その結果を受け取って初回限定の特典を与えることになります。

import DeviceCheck
        DCDevice.current.generateToken { (deviceToken, error) in
            // TODO: サーバーにdeviceTokenを送信して、レスポンスを受け取って処理をする
        }

iOS単体での実機デバッグ

DeviceCheckは、サーバーと連携して使うことが前提のものですが、iOSアプリ単体でテストとして使いたい場合、CupertinoJWT を使ってApple APIとの通信が可能です。
下記はquery_two_bitsの例です。
あくまでテストとしてお使いください。

import DeviceCheck
import CupertinoJWT

        DCDevice.current.generateToken { (deviceToken, error) in
            //p8ファイルの中身
            let p8 = """
                    -----BEGIN PRIVATE KEY-----
                    ...
                    -----END PRIVATE KEY-----
                    """
            let keyID = "iOS Developer centerで生成したKeyのKey ID"
            let teamID = "iOS Developer centerのチームID"
            let jwt = JWT(keyID: keyID, teamID: teamID, issueDate: Date(), expireDuration: 60 * 60)

            do {
                let generatedJWT = try jwt.sign(with: p8)
                let url = URL(string: "https://api.development.devicecheck.apple.com/v1/query_two_bits")!
                var request = URLRequest(url: url)
                request.httpMethod = "POST"

                let deviceTokenString = deviceToken!.base64EncodedString(options: Data.Base64EncodingOptions.init())
                let timestamp:Int = Int(Date().timeIntervalSince1970)
                let transaction = UUID().uuidString
                let requestBody = """
                {
                   "device_token" : "\(deviceTokenString)",
                   "transaction_id" : "\(transaction)",
                   "timestamp" : \(timestamp)000
                }
                """
                let data = requestBody.data(using: .utf8)
                request.addValue("Bearer \(generatedJWT)", forHTTPHeaderField: "Authorization")

                request.httpBody = data
                let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
                    // NOTE:Apple Device Check APIの結果を判断して初回限定の付与などを判定
                }
                task.resume()
            } catch {
                // Handle error
            }
        }
9
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
11