purchase play permission permiso pay library google app android android-billing

android - play - ¿Por qué es importante establecer la carga útil del desarrollador con la facturación en la aplicación?



permiso billing (7)

Estoy usando la versión 3 de la API de facturación en la aplicación. Tengo un artículo único, administrado y no consumible. Todavía no he lanzado esta función en mi aplicación, por lo que quiero decidir sobre el contenido de la carga de compra antes de realizar ninguna compra.

De "Mejores prácticas de seguridad" :

Establecer la cadena de carga útil del desarrollador al realizar solicitudes de compra

Con la API de facturación en la aplicación versión 3, puede incluir un token de cadena de ''carga útil del desarrollador'' al enviar su solicitud de compra a Google Play. Normalmente, esto se utiliza para pasar un token de cadena que identifica de forma única esta solicitud de compra. Si especifica un valor de cadena, Google Play devuelve esta cadena junto con la respuesta de compra. Posteriormente, cuando realiza consultas sobre esta compra, Google Play devuelve esta cadena junto con los detalles de la compra.

Debe pasar un token de cadena que ayude a su aplicación a identificar al usuario que realizó la compra, para que luego pueda verificar que esta sea una compra legítima por parte de ese usuario. Para los artículos consumibles, puede usar una cadena generada aleatoriamente, pero para los artículos no consumibles debe usar una cadena que identifica al usuario de manera única.

Cuando recuperes la respuesta de Google Play, asegúrate de verificar que la cadena de carga del desarrollador coincida con el token que enviaste previamente con la solicitud de compra. Como precaución adicional de seguridad, debe realizar la verificación en su propio servidor seguro.

Correcta o incorrectamente, he decidido no tomar la "mayor precaución de seguridad" de configurar un servidor para realizar la verificación de la compra. Y no guardo mi propio registro de la compra; siempre llamo a la API de facturación. Entonces, ¿hay realmente alguna razón para que haga esta verificación de carga útil? La API de verificación ciertamente verifica la identidad de un usuario antes de informar un artículo tal como lo compró, y si un atacante ha puesto en peligro un dispositivo (la aplicación o la API de google play), no veo ningún beneficio de hacer una verificación adicional en la identificación del usuario en el dispositivo donde puede eludirse fácilmente. ¿O hay alguna razón para hacer esto en la que no estoy pensando?


Debería pasar un token de cadena que ayude a su aplicación a identificar al usuario que realizó la compra ...

Si su aplicación proporciona su propio nombre de usuario e identidad, que es diferente de las cuentas de Google a las que está conectado el teléfono, entonces deberá usar la carga del desarrollador para adjuntar la compra a una de sus cuentas que realizó la compra. De lo contrario, alguien podría cambiar cuentas en su aplicación y obtener el beneficio de las cosas compradas.

p.ej

Supongamos que nuestra aplicación tiene login para userA y userB. Y la cuenta de Google para Android del teléfono es X.

  1. userA, inicia sesión en nuestra aplicación y compra membresía vitalicia. Los detalles de la compra se almacenan en la cuenta de Google X.
  2. userA cierra la sesión y userB inicia sesión en nuestra aplicación. Ahora, el usuario B también obtiene el beneficio de la membresía vitalicia, ya que la cuenta de Google Android todavía es X.

Para evitar dicho uso indebido, vincularemos una compra a una cuenta. En el ejemplo anterior, estableceremos la carga útil del desarrollador como "usuarioA" cuando userA realiza la compra. Entonces, cuando el usuario B inicia sesión, la carga útil no coincidirá con el usuario registrado (usuario B) e ignoraremos la compra. Por lo tanto, el usuario B no puede obtener los beneficios de una compra realizada por el usuario A.


Depende de cómo verifique el developerPayload . Hay dos escenarios: verificación remota (usando el servidor) y local (en el dispositivo).

Servidor

Si está utilizando un servidor para la verificación de la carga del developerPayload , puede ser una cadena arbitraria que se puede calcular fácilmente tanto en el dispositivo como en el servidor. Debería poder identificar al usuario que ha realizado la solicitud. Suponiendo que cada usuario tiene el accountId correspondiente, el developerPayload se puede calcular como una combinación con purchaseId (nombre del SKU) de esta manera:

MD5(purchaseId + accountId)


Dispositivo

developerPayload no debe ser correo electrónico del usuario . Un buen ejemplo de por qué no debe usar el correo electrónico como carga útil es el servicio de Google for Work. Los usuarios pueden cambiar su correo electrónico asociado con la cuenta. Lo único constante es accountId . En la mayoría de los casos, el correo electrónico estará bien (por ejemplo, las direcciones de Gmail son inmutables en este momento), pero recuerde diseñar para el futuro.

Varios usuarios pueden usar el mismo dispositivo, por lo que debe poder distinguir quién es el propietario del artículo. Para la verificación del dispositivo, developerPayload es una cadena que identifica al usuario de manera única, por ejemplo:

MD5(purchaseId + accountId)


Conclusión

En general, el developerPayload en ambos casos puede ser solo el accountId . Para mí, parece seguridad a través de la oscuridad . El MD5 (u otro algoritmo de hashing) y purchaseId es solo una forma de hacer que la carga sea más aleatoria sin mostrar explícitamente que estamos usando la identificación de la cuenta. El atacante tendría que descompilar la aplicación para verificar cómo se calcula. Si la aplicación está ofuscada, aún mejor para ti.

La carga útil no proporciona ninguna seguridad . Se puede falsificar fácilmente con el enfoque de "dispositivo" y sin ningún esfuerzo incautado en la verificación de "servidor". Recuerde implementar la verificación de firma con su clave pública disponible en la consola de la cuenta de editor de Google.

* Una publicación de blog must-read sobre el uso de la identificación de la cuenta en lugar del correo electrónico.


En el video de Google IO sobre IAB v3 dado por el autor de la muestra de la unidad trivial, este fue brevemente abordado hacia el final del video. Es para prevenir ataques de repetición, por ejemplo, un atacante olfatea el tráfico, roba el paquete que contiene una compra exitosa y luego intenta reproducir el paquete en su propio dispositivo. Si su aplicación no verifica la identidad del comprador a través de la carga útil del revelador (idealmente en su servidor) antes de liberar el contenido premium (también idealmente desde su servidor), el atacante tendrá éxito. La verificación de firma no puede detectar esto ya que el paquete está intacto.

En mi opinión, esta protección parece ideal para aplicaciones con conectividad de cuentas en línea como Choque de clanes (la carga útil entra naturalmente porque tienes que identificar usuarios de todos modos), especialmente cuando el pirateo compromete el juego multijugador con efectos de gran alcance que no sean un simple caso localizado de piratería . Por el contrario, si los piratas informáticos del lado del cliente ya pueden desbloquear el contenido premium, esta protección no es muy útil.

(Si el atacante intenta falsificar la carga útil, la verificación de la firma debería fallar).


Esto a menudo responde a una definición de producto (su aplicación). Por ejemplo, en el caso de las suscripciones. ¿Podrá el mismo usuario usar la suscripción en todos los dispositivos que tenga? Si la respuesta es sí. No verificamos la carga útil.

Para consumibles. Supongamos que una compra en su aplicación le da 10 monedas virtuales. ¿Podrá el usuario usar estas monedas en diferentes dispositivos? 4 en un dispositivo y 6 en otro? Si queremos trabajar solo en el dispositivo que realizó la compra, tenemos que verificar la carga útil, por ejemplo, con una cadena autogenerada y guardada localmente.

En base a estas preguntas, debemos decidir cómo implementar la verificación de la carga útil.

Saludos

Santiago


Luché con este. Como una cuenta de Google Play solo puede tener uno de los artículos "administrados", pero podría tener varios dispositivos (tengo tres), el comentario anterior de alguien que vende un "por dispositivo" no funcionará ... ser capaz de ponerlo en su primer dispositivo, y nunca más ... Si compra una actualización premium, debería funcionar en todos sus teléfonos / tabletas.

Desprecio la idea de obtener la dirección de correo electrónico del usuario, pero realmente no encontré otro método confiable. Así que tomé la primera cuenta que coincide con "google.com" en la lista de cuentas (sí, un permiso para agregar a su manifiesto), y luego la puse de inmediato para que ya no sea utilizable como dirección de correo electrónico pero proporciona un "token" Eso es lo que envío como carga útil del desarrollador. Como la mayoría de las personas activan su dispositivo con su ID de Google Play, hay una buena oportunidad de que los tres dispositivos obtengan el mismo token (usando el mismo algoritmo hash en cada dispositivo).

Incluso funciona en KitKat con múltiples "usuarios". (Mi ID de desarrollador está en un usuario, mi ID de prueba en otro y cada usuario en su propio entorno limitado).

Lo he probado en seis dispositivos con un total de 3 usuarios y cada dispositivo de los usuarios ha devuelto el mismo hash, y los diferentes usuarios tienen hashes distintos que satisfacen las directrices.

En ningún momento estoy almacenando la dirección de correo electrónico del usuario, se transfiere directamente desde el código para obtener los nombres de las cuentas en la función hash y solo el hash se guarda en el montón.

Probablemente haya una mejor solución que respete aún más la privacidad de los usuarios, pero hasta ahora no la he encontrado. Voy a poner una descripción muy clara de cómo uso la dirección de correo electrónico de los usuarios en mi política de privacidad una vez que se publique la aplicación.


Si no lleva un registro, no hay forma de verificar que lo que obtiene es lo que envió. Entonces, si agrega algo a la carga del desarrollador, puede confiar en que es legítimo (lo cual es una suposición razonable si la firma lo verifica), o no confiar completamente en él y solo usarlo como referencia, pero no para validar el estado de la licencia, etc. Si almacena el correo electrónico del usuario, por ejemplo, puede usar el valor en lugar de pedirle que lo vuelva a ingresar, lo cual es un poco más fácil de usar, pero su aplicación no se romperá si no está allí.

Personalmente, creo que toda esta parte de ''mejores prácticas'' es confusa e intenta hacer que hagas el trabajo que realmente debería hacer la API. Dado que la compra está ligada a una cuenta de Google, y Play Store obviamente guarda esta información, solo deben darle esto en los detalles de la compra. Obtener un ID de usuario adecuado requiere permisos adicionales que no debería necesitar agregar solo para cubrir las deficiencias de la API de IAB.

Entonces, en resumen, a menos que tenga su propio servidor y una lógica adicional especial, simplemente no use la carga útil del desarrollador. Debería estar bien, siempre y cuando la API de IAB v3 funcione (que, desafortunadamente, es un gran ''si'' en este momento).


También hay otro enfoque para el manejo de la carga útil del desarrollador. Como Nikolay Elenkov dijo que es demasiado sobrecargado para requerir ID de usuario y establecer permisos adicionales para el perfil de usuario a su aplicación, este no es un buen enfoque. Así que veamos lo que dice Google en la última versión de la aplicación de ejemplo TrivialDrive en muestras de In-App Billing v3:

  • ADVERTENCIA: generar localmente una cadena aleatoria al comenzar una compra y verificarla aquí podría parecer un buen enfoque, pero esto fallará en el caso en que el usuario compre un artículo en un dispositivo y luego use su aplicación en un dispositivo diferente, porque en el otro dispositivo no tendrá acceso a la cadena aleatoria que generó originalmente.

Por lo tanto, la cadena aleatoria no es una buena idea si va a verificar el artículo comprado en otro dispositivo, pero aún así no dicen que no es una buena idea para verificar la respuesta de compra. Diría que: use la carga útil del desarrollador solo para verificar la compra enviando una cadena aleatoria única, guárdela en preferencias / base de datos y en la respuesta de compra consulte esta carga útil del desarrollador. En cuanto a consultar el inventario (compras integradas en la aplicación) al inicio de la actividad, no se moleste en consultar la carga del desarrollador, ya que podría ocurrir en otro dispositivo donde no tenga almacenada esa cadena única aleatoria. Así es como lo veo.