1 page.title=Best Practices for Unique Identifiers 2 page.metaDescription=How to manage unique identifiers the right way for users. 3 page.tags=ids, user data 4 meta.tags="ids", "user data" 5 page.image=images/cards/card-user-ids_2x.png 6 7 page.article=true 8 @jd:body 9 10 <div id="tb-wrapper"> 11 <div id="tb"> 12 <h2>In this document</h2> 13 <ol> 14 <li><a href="#tenets_of_working_with_android_identifiers">Tenets of Working with 15 Android Identifiers</a></li> 16 <li><a href="#version_specific_details_identifiers_in_m">Identifiers in Android 6.0+</a></li> 17 <li><a href="#working_with_advertising_ids">Working with Advertising IDs</a></li> 18 <li><a href="#working_with_instance_ids_&_guids">Working with Instance IDs and GUIDs</a></li> 19 <li><a href="#understand_identifier_characteristics">Understanding Identifier 20 Characteristics</a> 21 <ol> 22 <li><a href="#scope">Scope</a></li> 23 <li><a href="#resettability_&_persistence">Resettability & persistence</a></li> 24 <li><a href="#uniqueness">Uniqueness</h3> 25 <li><a href="#integrity_protection_and_non-repudiability">Integrity protection and 26 non-repudiability</a></li> 27 </ol> 28 </li> 29 <li><a href="#use_appropriate_identifiers">Common Use Cases and the Identifier to Use</a> 30 <ol> 31 <li><a href="#a_track_signed-out_user_preferences">Tracking signed-out user 32 preferences</a></li> 33 <li><a href="#b_track_signed-out_user_behavior">Tracking signed-out user behavior</a></li> 34 <li><a href="#c_generate_signed-out_anonymous_user_analytics">Generating 35 signed-out/anonymous user analytics</a></li> 36 <li><a href="#d_track_signed-out_user_conversion">Tracking signed-out user 37 conversion</a></li> 38 <li><a href="#e_handle_multiple_installations">Handling multiple installations</a></li> 39 <li><a href="#f_anti-fraud_enforcing_free_content_limits_detecting_sybil_attacks">Anti-fraud: 40 Enforcing free content limits / detecting Sybil attacks</a></li> 41 <li><a href="#g_manage_telephony_&_carrier_functionality">Managing telephony and carrier 42 functionality</a></li> 43 <li><a href="#h_abuse_detection_identifying_bots_and_ddos_attacks">Abuse detection: 44 Identifying bots and DDoS attacks</a></li> 45 <li><a href="#i_abuse_detection_detecting_high_value_stolen_credentials">Abuse detection: 46 Detecting high value stolen credentials</a></li> 47 </ol> 48 </li> 49 </ol> 50 </div> 51 </div> 52 53 <p> 54 While there are valid reasons why your application may need to identify a 55 device rather than an instance of the application or an authenticated user on 56 the device, for the vast majority of applications, the ultimate goal is to 57 identify a particular <em>installation</em> of your app (not the actual 58 physical device). 59 </p> 60 61 <p> 62 Fortunately, identifying an installation on Android is straightforward using 63 an Instance ID or by creating your own GUID at install time. This document 64 provides guidance for selecting appropriate identifiers for your application, 65 based on your use-case. 66 </p> 67 68 <p> 69 For a general look at Android permissions, please see <a href= 70 "{@docRoot}training/articles/user-data-overview.html">Permissions 71 and User Data</a>. For specific best practices for 72 working with Android permissions, please see <a href= 73 "{@docRoot}training/articles/user-data-permissions.html">Best Practices for 74 App Permissions</a>. 75 </p> 76 77 78 <h2 id="tenets_of_working_with_android_identifiers">Tenets of Working with Android Identifiers</h2> 79 80 <p> 81 We recommend that you follow these tenets when working with Android 82 identifiers: 83 </p> 84 85 <p> 86 <em><strong>#1: Avoid using hardware identifiers.</strong></em> Hardware 87 identifiers such as SSAID (Android ID) and IMEI can be avoided in most 88 use-cases without limiting required functionality. 89 </p> 90 91 <p> 92 <em><strong>#2: Only use Advertising ID for user profiling or ads 93 use-cases.</strong></em> When using an <a href= 94 "https://support.google.com/googleplay/android-developer/answer/6048248?hl=en"> 95 Advertising ID</a>, always respect the <a href= 96 "https://play.google.com/about/developer-content-policy.html#ADID">Limit Ad 97 Tracking</a> flag, ensure the identifier cannot be connected to personally 98 identifiable information (PII) and avoid bridging Advertising ID resets. 99 </p> 100 101 <p> 102 <em><strong>#3: Use an Instance ID or a privately stored GUID whenever 103 possible for all other use-cases except payment fraud prevention and 104 telephony.</strong></em> For the vast majority of non-ads use-cases, an 105 instance ID or GUID should be sufficient. 106 </p> 107 108 <p> 109 <em><strong>#4: Use APIs that are appropriate to your use-case to minimize 110 privacy risk.</strong></em> Use the 111 <a href="http://source.android.com/devices/drm.html">DRM 112 API</a> API for high value content 113 protection and the <a href="{@docRoot}training/safetynet/index.html">SafetyNet 114 API</a> for abuse prevention. The Safetynet API is 115 the easiest way to determine whether a device is genuine without incurring 116 privacy risk. 117 </p> 118 119 <p> 120 The remaining sections of this guide elaborate on these rules in the context 121 of developing Android applications. 122 </p> 123 124 <h2 id="version_specific_details_identifiers_in_m">Identifiers in Android 6.0+</h2> 125 126 <p> 127 MAC addresses are globally unique, not user-resettable and survive factory 128 reset. It is generally not recommended to use MAC address for any form of 129 user identification. As a result, as of Android M, local device MAC addresses 130 (for example, Wifi and Bluetooth) <em><strong>are not available via third party 131 APIs</strong></em>. The {@link android.net.wifi.WifiInfo#getMacAddress WifiInfo.getMacAddress()} 132 method and the {@link android.bluetooth.BluetoothAdapter#getAddress 133 BluetoothAdapter.getDefaultAdapter().getAddress()} method will 134 both return <code>02:00:00:00:00:00</code>.. 135 </p> 136 137 <p> 138 Additionally, you must hold the following permissions to access MAC addresses 139 of nearby external devices available via Bluetooth and Wifi scans: 140 </p> 141 142 <table> 143 <tr> 144 <th><strong>Method/Property</strong></td> 145 <th><strong>Permissions Required</strong></td> 146 </tr> 147 <tr> 148 <td> 149 <code><a href="{@docRoot}reference/android/net/wifi/WifiManager.html#getScanResults()">WifiManager.getScanResults()</a></code> 150 </td> 151 <td> 152 <code>ACCESS_FINE_LOCATION</code> or <code>ACCESS_COARSE_LOCATION</code> 153 </td> 154 </tr> 155 <tr> 156 <td> 157 <code><a href="{@docRoot}reference/android/bluetooth/BluetoothDevice.html#ACTION_FOUND">BluetoothDevice.ACTION_FOUND</a></code> 158 </td> 159 <td> 160 <code>ACCESS_FINE_LOCATION</code> or <code>ACCESS_COARSE_LOCATION</code> 161 </td> 162 </tr> 163 <tr> 164 <td> 165 <code><a href="{@docRoot}reference/android/bluetooth/le/BluetoothLeScanner.html#startScan(android.bluetooth.le.ScanCallback)">BluetoothLeScanner.startScan(ScanCallback)</a></code> 166 </td> 167 <td> 168 <code>ACCESS_FINE_LOCATION</code> or <code>ACCESS_COARSE_LOCATION</code> 169 </td> 170 </tr> 171 </table> 172 173 174 <h2 id="working_with_advertising_ids">Working with Advertising IDs</h2> 175 176 <p> 177 Advertising ID is a user-resettable identifier and is appropriate for Ads 178 use-cases, but there are some key points to bear in mind when using it: 179 </p> 180 181 <p> 182 <em><strong>Always respect the users intention in resetting the advertising 183 ID</strong></em>. Do not bridge user resets by using a more persistent device 184 identifier or fingerprint to link subsequent Advertising IDs together without 185 the users consent. The <a href= 186 "https://play.google.com/about/developer-content-policy.html">Google Play 187 Developer Content Policy</a> states: 188 </p> 189 190 <div style="padding:.5em 2em;"> 191 <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;"> 192 <p>...if reset, a new advertising 193 identifier must not be connected to a previous advertising identifier or data 194 derived from a previous advertising identifier without the explicit consent 195 of the user.</span></p> 196 </div> 197 </div> 198 199 <p> 200 <em><strong>Always respect the associated Personalized Ads 201 flag</strong></em>. Advertising IDs are configurable in that users can limit 202 the amount of tracking associated with the ID. Always use the <code><a href= 203 "https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.Info.html#isLimitAdTrackingEnabled()"> 204 AdvertisingIdClient.Info.isLimitAdTrackingEnabled()</a></code> method to 205 ensure you are not circumventing your users' wishes. The <a href= 206 "https://play.google.com/about/developer-content-policy.html">Google Play 207 Developer Content Policy</a> states: 208 </p> 209 210 211 <div style="padding:.5em 2em;"> 212 <div style="border-left:4px solid #999;padding:0 1em;font-style:italic;"> 213 <p>...you must abide by a users Opt out of interest-based advertising or 'Opt 214 out of Ads Personalization' setting. If a user has enabled this setting, you 215 may not use the advertising identifier for creating user profiles for 216 advertising purposes or for targeting users with personalized advertising. 217 Allowed activities include contextual advertising, frequency capping, 218 conversion tracking, reporting and security and fraud detection.</span></p> 219 </div> 220 </div> 221 222 <p> 223 <em><strong>Be aware of any privacy or security policies associated with SDKs 224 you use that are related to Advertising ID use.</strong></em> For example, if 225 you are using the Google Analytics SDK 226 <code><a href= 227 "https://developers.google.com/android/reference/com/google/android/gms/analytics/Tracker.html#enableAdvertisingIdCollection(boolean)">mTracker.enableAdvertisingIdCollection(true)</a></code> 228 method, make sure to review and adhere to all applicable <a href= 229 "https://developers.google.com/analytics/devguides/collection/android/v4/policy"> 230 Analytics SDK policies</a>. 231 </p> 232 233 <p> 234 Also, be aware that the <a href= 235 "https://play.google.com/about/developer-content-policy.html">Google Play 236 Developer Content Policy</a> requires that the Advertising ID must not be 237 connected to personally-identifiable information or associated with any 238 persistent device identifier (for example: SSAID, MAC address, IMEI, etc.,) 239 without the explicit consent of the user. 240 </p> 241 242 <p> 243 As an example, suppose you want to collect information to populate database 244 tables with the following columns: 245 </p> 246 247 <table> 248 <tr> 249 <td> 250 <table> 251 <tr> 252 <td class="tab2"> 253 <code>timestamp</code></td> 254 <td class="tab2"> 255 <code>ad_id</code></td> 256 <td> 257 <code><strong>account_id</strong></code></td> 258 <td class="tab2"> 259 <code>clickid</code></td> 260 </tr> 261 </table> 262 263 <p>TABLE-01</p> 264 </td> 265 <td> 266 <table> 267 <tr> 268 <td> 269 <code><strong>account_id</strong></code></td> 270 <td class="tab2"> 271 <code>name</code></td> 272 <td class="tab2"> 273 <code>dob</code></td> 274 <td class="tab2"> 275 <code>country</code></td> 276 </tr> 277 </table> 278 <p>TABLE-02</p> 279 </td> 280 </tr> 281 </table> 282 283 284 <p> 285 In this example, the <code>ad_id</code> column could be joined to PII via the 286 <code>account_id</code> column in both tables, which would be a violation of 287 the <a href= 288 "https://play.google.com/about/developer-content-policy.html">Google Play 289 Developer Content Policy</a>, if you did not get explicit permission from 290 your users. 291 </p> 292 293 <p> 294 Keep in mind that links between Advertiser ID and PII aren't always this 295 explicit. It's possible to have quasi-identifiers that appear in both PII 296 and Ad ID keyed tables, which also cause problems. For example, assume we 297 change TABLE-01 and TABLE-02 as follows: 298 </p> 299 300 <table> 301 <tr> 302 <td><table> 303 <tr> 304 <td> 305 <code><strong>timestamp</strong></code></td> 306 <td class="tab2"> 307 <code>ad_id</code></td> 308 <td> 309 <code>clickid</code></td> 310 <td> 311 <code><strong>dev_model</strong></code></td> 312 </tr> 313 </table> 314 315 </pre> 316 <p>TABLE-01</p> 317 </td> 318 <td> 319 <table> 320 <tr> 321 <td> 322 <code><strong>timestamp</strong></code></td> 323 <td class="tab2"> 324 <code>demo</code></td> 325 <td class="tab2"> 326 <code>account_id</code></td> 327 <td> 328 <code><strong>dev_model</strong></code></td> 329 <td class="tab2"> 330 <code>name</code></td> 331 </tr> 332 </table> 333 <p>TABLE-02</p> 334 </td> 335 </tr> 336 </table> 337 338 339 <p> 340 In this case, with sufficiently rare click events, it's still possible to 341 join between the Advertiser ID TABLE-01 and the PII contained in TABLE-2 342 using the timestamp of the event and the device model. 343 </p> 344 345 <p> 346 While it is often difficult to guarantee that no such quasi-identifiers exist 347 in a dataset, the most obvious join risks can be prevented by generalizing 348 unique data where possible. In the example, this would mean reducing the 349 accuracy of the timestamp so that multiple devices with the same model appear 350 for every timestamp. 351 </p> 352 353 <p> 354 Other solutions include: 355 </p> 356 357 <ul> 358 <li><em><strong>Not designing tables that explicitly link PII with Advertising 359 IDs</strong></em>. In the first example above this would mean not including the 360 account_id column in TABLE-01.</li> 361 362 <li><em><strong>Segregating and monitoring access control lists for users or roles 363 that have access to both the Advertising ID keyed data and PII</strong></em>. If the 364 ability to access both sources simultaneously (for example, to perform 365 a join between two tables) is tightly controlled and audited, it reduces the 366 risk of association between the Advertising ID and PII. Generally speaking, 367 controlling access means: 368 369 <ol> 370 <li> Keeping access control lists (ACLs) for Advertiser ID keyed data and PII disjoint to 371 minimize the number of individuals or roles that are in both ACLs, and</li> 372 <li> Implementing access logging and auditing to detect and manage any exceptions to 373 this rule.</li> 374 </ol> 375 </li> 376 </ul> 377 378 <p> 379 For more information on working responsibly with Advertising IDs, please see 380 the <a href= 381 "https://support.google.com/googleplay/android-developer/answer/6048248?hl=en"> 382 Advertising ID</a> help center article. 383 </p> 384 385 <h2 id="working_with_instance_ids_&_guids">Working with Instance IDs and GUIDs</h2> 386 387 <p> 388 The most straightforward solution to identifying an application instance 389 running on a device is to use an Instance ID, and this is the recommended 390 solution in the majority of non-ads use-cases. Only the app instance for 391 which it was provisioned can access this identifier, and it's (relatively) 392 easily resettable because it only persists as long as the app is installed. 393 </p> 394 395 <p> 396 As a result, Instance IDs provide better privacy properties compared to 397 non-resettable, device-scoped hardware IDs. They also come with a key-pair 398 for message signing (and similar actions) and are available on Android, iOS 399 and Chrome. Please see the <a href= 400 "https://developers.google.com/instance-id/">What is Instance ID?</a> help 401 center document for more information. 402 </p> 403 404 <p> 405 In cases where an Instance ID isn't practical, custom globally unique IDs 406 (GUIDs) can also be used to uniquely identify an app instance. The simplest 407 way to do so is by generating your own GUID using the following code. 408 </p> 409 410 <pre>String uniqueID = UUID.randomUUID().toString();</pre> 411 412 <p> 413 Because the identifier is globally unique, it can be used to identify a 414 specific app instance. To avoid concerns related to linking the identifier 415 across applications, GUIDs should be stored in internal storage rather than 416 external (shared) storage. Please see <a href= 417 "{@docRoot}guide/topics/data/data-storage.html">Storage Options</a> guide for 418 more information. 419 </p> 420 421 422 <h2 id="understand_identifier_characteristics">Understanding Identifier Characteristics</h2> 423 424 <p> 425 The Android Operating system offers a number of IDs with different behavior 426 characteristics and which ID you should use depends on how those following 427 characteristics work with your use-case. But these characteristics also come 428 with privacy implications so it's important to understand how these 429 characteristics play together. 430 </p> 431 432 <h3 id="scope">Scope</h3> 433 434 <p> 435 Identifier scope explains which systems can access the identifier. Android 436 identifier scope generally comes in three flavors: 437 </p> 438 439 <ul> 440 <li> <em>Single app</em>. the ID is internal to the app and not accessible to other apps. 441 <li> <em>Group of apps</em> - the ID is accessible to a pre-defined group of related apps. 442 <li> <em>Device</em> - the ID is accessible to all apps installed on the device. 443 </ul> 444 445 <p> 446 The wider the scope granted to an identifier, the greater the risk of it 447 being used for tracking purposes. Conversely, if an identifier can only be 448 accessed by a single app instance, it cant be used to track a device across 449 transactions in different apps. 450 </p> 451 <h3 id="resettability_&_persistence">Resettability and persistence</h3> 452 453 <p> 454 Resettability and persistence define the lifespan of the identifier and 455 explain how it can be reset. Common reset triggers are: in-app resets, resets 456 via System Settings, resets on launch, and resets on installation. Android 457 Identifiers can have varying lifespans, but the lifespan is usually related 458 to how the ID is reset: 459 </p> 460 <ul> 461 <li> <em>Session-only</em> - a new ID is used every time the user restarts the app. 462 <li> <em>Install-reset</em> - a new ID is used every time user uninstalls and reinstalls the app. 463 <li> <em>FDR-reset</em> - a new ID is used every time the user factory-resets the device. 464 <li> <em>FDR-persistent</em> - the ID survives factory reset. 465 </ul> 466 467 <p> 468 Resettability gives users the ability to create a new ID that is 469 disassociated from any existing profile information. This is important 470 because the longer, and more reliably, an identifier persists (e.g. across 471 factory resets etc.), the greater the risk that the user may be subjected to 472 long-term tracking. If the identifier is reset upon app reinstall, this 473 reduces the persistence and provides a means for the ID to be reset, even if 474 there is no explicit user control to reset it from within the app or the 475 System Settings. 476 </p> 477 <h3 id="uniqueness">Uniqueness</h3> 478 479 <p> 480 Uniqueness establishes the likelihood that identical identifiers exist within 481 the associated scope. At the highest level, a globally unique identifier will 482 never have a collision - even on other devices/apps. Otherwise, the level of 483 uniqueness depends on the size of the identifier and the source of randomness 484 used to create it. For example, the chance of a collision is much higher for 485 random identifiers seeded with the calendar date of installation (e.g., 486 2015-01-05) than for identifiers seeded with the Unix timestamp of 487 installation (e.g., 1445530977). 488 </p> 489 490 <p> 491 In general, user account identifiers can be considered unique (i.e., each 492 device/account combo has a unique ID). On the other hand, the less unique 493 an identifier is within a population (e.g. of devices), the greater the 494 privacy protection because it's less useful for tracking an individual user. 495 </p> 496 497 <h3 id="integrity_protection_and_non-repudiability">Integrity protection and 498 non-repudiability</h3> 499 500 <p> 501 An identifier that is difficult to spoof or replay can be used to prove that 502 the associated device or account has certain properties (e.g. its not a 503 virtual device used by a spammer). Difficult to spoof identifiers also 504 provide <em>non-repudiability</em>. If the device signs a message with a 505 secret key, it is difficult to claim someone elses device sent the message. 506 Non-repudiability could be something a user wants (e.g. authenticating a 507 payment) or it could be an undesirable property (e.g. sending a message they 508 regret). 509 </p> 510 511 512 <h2 id="use_appropriate_identifiers">Common Use Cases and the Identifier to Use</h2> 513 514 <p> 515 This section provides alternatives to using hardware IDs such as IMEI or 516 SSAID for the majority of use-cases. Relying on hardware IDs is discouraged 517 because the user cannot reset them and generally has limited control over 518 their collection. 519 </p> 520 521 <h3 id="a_track_signed-out_user_preferences">Tracking signed-out user preferences</h3> 522 523 <p> 524 <em>In this case, you are saving per-device state on the server side.</em> 525 </p> 526 527 <p> 528 <strong>We Recommend</strong>: Instance ID or a GUID. 529 </p> 530 531 <p> 532 <strong>Why this Recommendation?</strong> 533 </p> 534 535 <p> 536 Persisting information through reinstalls is not recommended because users 537 may want to reset their preferences by reinstalling the app. 538 </p> 539 540 <h3 id="b_track_signed-out_user_behavior">Tracking signed-out user behavior</h3> 541 542 <p> 543 <em>In this case, you have created a profile of a user based on their 544 behavior across different apps/sessions on the same device.</em> 545 </p> 546 547 <p> 548 <strong>We Recommend</strong>: Advertising ID. 549 </p> 550 551 <p> 552 <strong>Why this Recommendation?</strong> 553 </p> 554 555 <p> 556 Use of the Advertising ID is mandatory for Advertising use-cases per the 557 <a href="https://play.google.com/about/developer-content-policy.html">Google 558 Play Developer Content Policy</a> because the user can reset it. 559 </p> 560 561 <h3 id="c_generate_signed-out_anonymous_user_analytics">Generating signed-out/anonymous user analytics</h3> 562 563 <p> 564 <em>In this case, you are measuring usage statistics and analytics for 565 signed-out or anonymous users.</em> 566 </p> 567 568 <p> 569 <strong>We Recommend</strong>: Instance ID; if an Instance ID is 570 insufficient, you can also use a GUID. 571 </p> 572 573 <p> 574 <strong>Why this Recommendation?</strong> 575 </p> 576 577 <p> 578 An Instance ID or a GUID is scoped to the app that creates it, which prevents 579 it from being used to track users across apps. It is also easily reset by 580 clearing app data or reinstalling the app. Creating Instance IDs and GUIDs is 581 straightforward: 582 </p> 583 584 <ul> 585 <li> Creating an Instance ID: <code>String iid = InstanceID.getInstance(context).getId()</code> 586 <li> Creating a GUID: <code>String uniqueID = UUID.randomUUID().toString</code> 587 </ul> 588 589 <p> 590 Be aware that if you have told the user that the data you are collecting is 591 anonymous, you should <em><strong>ensure you are not connecting the 592 identifier to PII</strong></em> or other identifiers that may be linked to 593 PII. 594 </p> 595 596 <p> 597 You can also use Google Analytics for Mobile Apps, which offers a solution 598 for per-app analytics. 599 </p> 600 601 <h3 id="d_track_signed-out_user_conversion">Tracking signed-out user conversion</h3> 602 603 <p> 604 <em>In this case, you are tracking conversions to detect if your marketing 605 strategy was successful.</em> 606 </p> 607 608 <p> 609 <strong>We Recommend</strong>: Advertising ID. 610 </p> 611 612 <p> 613 <strong>Why this Recommendation?</strong> 614 </p> 615 616 <p> 617 This is an ads-related use-case which may require an ID that is available 618 across different apps so using an Advertising ID is the most appropriate 619 solution. 620 </p> 621 622 <h3 id="e_handle_multiple_installations">Handling multiple installations</h3> 623 624 <p> 625 <em>In this case, you need to identify the correct instance of the app when 626 it's installed on multiple devices for the same user.</em> 627 </p> 628 629 <p> 630 <strong>We Recommend</strong>: Instance ID or GUID. 631 </p> 632 633 <p> 634 <strong>Why this Recommendation?</strong> 635 </p> 636 637 <p> 638 Instance ID is designed explicitly for this purpose; its scope is limited to 639 the app so that it cannot be used to track users across different apps and it 640 is reset upon app reinstall. In the rare cases where an Instance ID is 641 insufficient, you can also use a GUID. 642 </p> 643 644 <h3 id="f_anti-fraud_enforcing_free_content_limits_detecting_sybil_attacks">Anti-fraud: Enforcing free content limits / detecting Sybil attacks</h3> 645 646 <p> 647 <em>In this case, you want to limit the number of free content (e.g. 648 articles) a user can see on a device.</em> 649 </p> 650 651 <p> 652 <strong>We Recommend</strong>: Instance ID or GUID. 653 </p> 654 655 <p> 656 <strong>Why this Recommendation?</strong> 657 </p> 658 659 <p> 660 Using a GUID or Instance ID forces the user to reinstall the app in order to 661 overcome the content limits, which is a sufficient burden to deter most 662 people. If this is not sufficient protection, Android provides a 663 <a href="http://source.android.com/devices/drm.html">DRM API</a> 664 which can be used to limit access to content. 665 </p> 666 667 <h3 id="g_manage_telephony_&_carrier_functionality">Managing telephony and carrier functionality</h3> 668 669 <p> 670 <em>In this case, your app is interacting with the device's phone and texting 671 functionality.</em> 672 </p> 673 674 <p> 675 <strong>We Recommend</strong>: IMEI, IMSI, and Line1 (requires <code>PHONE</code> 676 permission group in Android 6.0 (API level 23) and higher). 677 </p> 678 679 <p> 680 <strong>Why this Recommendation?</strong> 681 </p> 682 683 <p> 684 Leveraging hardware identifiers is acceptable if it is required for 685 telephony/carrier related functionality; for example, switching between 686 cellular carriers/SIM slots or delivering SMS messages over IP (for Line1) - 687 SIM-based user accounts. But it's important to note that in Android 6.0+ 688 these identifiers can only be used via a runtime permission and that users 689 may toggle off this permission so your app should handle these exceptions 690 gracefully. 691 </p> 692 693 <h3 id="h_abuse_detection_identifying_bots_and_ddos_attacks">Abuse detection: 694 Identifying bots and DDoS attacks</h3> 695 696 <p> 697 <em>In this case, you are trying to detect multiple fake devices attacking 698 your backend services.</em> 699 </p> 700 701 <p> 702 <strong>We Recommend:</strong> The Safetynet API. 703 </p> 704 705 <p> 706 <strong>Why this Recommendation?</strong> 707 </p> 708 709 <p> 710 An identifier in isolation does little to indicate that a device is genuine. 711 You can verify that a request comes from a genuine Android device (as opposed 712 to an emulator or other code spoofing another device) using the Safetynet 713 API's <code>SafetyNet.SafetyNetApi.attest(mGoogleApiClient, nonce)</code> 714 method to verify the integrity of a device making a request. For more 715 detailed information, please see <a href= 716 "{@docRoot}training/safetynet/index.html">Safetynet's API documentation</a>. 717 </p> 718 719 <h3 id="i_abuse_detection_detecting_high_value_stolen_credentials">Abuse detection: 720 Detecting high value stolen credentials</h3> 721 722 <p> 723 <em>In this case, you are trying to detect if a single device is being used 724 multiple times with high-value, stolen credentials (e.g. to make fraudulent 725 payments).</em> 726 </p> 727 728 <p> 729 <strong>We Recommend</strong>: IMEI/IMSI (requires <code>PHONE</code> 730 permission group in Android 6.0 (API level 23) and higher.) 731 </p> 732 733 <p> 734 <strong>Why this Recommendation?</strong> 735 </p> 736 737 <p> 738 With stolen credentials, devices can be used to monetize multiple high value 739 stolen credentials (such as tokenized credit cards). In these scenarios, 740 software IDs can be reset to avoid detection, so hardware identifiers may be 741 used. 742 </p>