¿No debería Android StoreManager almacenar símbolos de OAuth en una base de datos por aplicación / UID?

Android AccountManager parece buscar el mismo token de autorización en caché para aplicaciones con diferentes UIDs – esto es seguro? No parece compatible con OAuth2, ya que los tokens de acceso no se deben compartir entre diferentes clientes.

Antecedentes / Contexto

Estoy construyendo una aplicación de Android que utiliza OAuth2 para la autenticación / autorización de solicitudes de REST API a mi servidor, que es un proveedor de OAuth2. Dado que la aplicación es la aplicación "oficial" (a diferencia de una aplicación de terceros), se considera un cliente OAuth2 de confianza, por lo que estoy utilizando el flujo de contraseñas del propietario de recursos para obtener un token OAuth2: el usuario (el propietario del recurso) Introduce su nombre de usuario / contraseña en la aplicación, que luego envía su ID de cliente y secreto de cliente junto con las credenciales de usuario al punto final de token OAuth2 de mi servidor a cambio de un token de acceso que se puede utilizar para realizar llamadas API, Utilizado para obtener nuevos tokens de acceso cuando expiran. La justificación es que es más seguro guardar el token de actualización en el dispositivo que la contraseña del usuario.

Estoy utilizando AccountManager para administrar la cuenta y el token de acceso asociado en el dispositivo. Puesto que estoy proporcionando mi propio proveedor de OAuth2, he creado mi propio tipo de cuenta personalizada extendiendo AbstractAccountAuthenticator y otros componentes necesarios, como se explica en esta Guía para Android Dev y se demuestra en el proyecto de ejemplo SampleSyncAdapter. Puedo añadir con éxito cuentas de mi tipo personalizado desde mi aplicación y gestionarlas desde la pantalla de configuración de "Cuentas y sincronización" de Android.

La cuestión

Sin embargo, me preocupa la manera en que el AccountManager almacena en caché y emite tokens de autenticación, específicamente, que el mismo token de autenticación para un tipo de cuenta y tipo de token dado parece accesible para cualquier aplicación a la que el usuario haya concedido acceso.

Para obtener un token de autenticación a través del AccountManager, se debe invocar AccountManager.getAuthToken () , pasando, entre otras cosas, la instancia de Cuenta para la que se obtiene el token de autenticación y el authTokenType deseado. Si existe un token de autenticación para la cuenta especificada y authTokenType, y si el usuario concede acceso (a través de la pantalla "Solicitud de acceso" ) a la aplicación que ha realizado la solicitud de token de autorización (en casos en los que el UID de la aplicación solicitante no coincide El UID del autenticador), se devuelve el token. En caso de que mi explicación es la falta, esta entrada de blog útil explica muy claramente. Sobre la base de ese mensaje, y después de examinar el origen de AccountManager y AccountManagerService (una clase interna que hace el trabajo pesado para AccountManager) para mí, parece que sólo 1 token de autenticación se almacena por combinación authTokenType / cuenta.

Por lo tanto, parece factible que si una aplicación maliciosa sabía el tipo de cuenta y authTokenType (s) utilizado por mi autenticador, podría invocar AccountManager.getAuthToken () para obtener el token OAuth2 almacenado en mi aplicación, suponiendo que el usuario concede acceso a los maliciosos App.

Para mí, el problema es que la implementación de almacenamiento en caché por defecto de AccountManager se basa en un paradigma en el que, si tuviéramos que superponer un contexto de autenticación / autorización OAuth2, consideraría que el teléfono / dispositivo es un cliente OAuth2 único para un proveedor de servicios / recursos . Mientras que, el paradigma que tiene sentido para mí es que cada aplicación / UID debe ser considerado como su propio cliente OAuth2. Cuando mi proveedor OAuth2 emite un token de acceso, emite un token de acceso para esa aplicación en particular que ha enviado el ID de cliente y el secreto de cliente correctos, no todas las aplicaciones del dispositivo. Por ejemplo, el usuario puede tener tanto mi aplicación oficial (llamarla cliente de aplicación A) como una aplicación de terceros "con licencia" que utiliza mi API (llamarla aplicación Cliente B) instalada. Para el cliente oficial A, mi proveedor OAuth2 puede emitir un token de tipo / alcance "super" que otorgue acceso a partes públicas y privadas de mi API, mientras que para el tercero cliente B, mi proveedor puede emitir un tipo "restringido" / Scope que sólo otorga acceso a las llamadas API públicas. No debería ser posible que el cliente B de la aplicación obtenga el token de acceso del cliente A de la aplicación, que parece permitir la implementación actual de AccountManager / AccountManagerService. Porque, incluso si el usuario concede autorización al Cliente B para el Súper Token del Cliente A, el hecho es que mi proveedor OAuth2 sólo tenía la intención de otorgar ese token al Cliente A.

¿Estoy pasando por alto algo aquí? Es mi creencia de que los tokens de autenticación deben ser emitidos en una base por aplicación / UID (cada aplicación es un cliente distinto) racional / práctico, o son auth-tokens por dispositivo (cada dispositivo es un cliente) ¿práctica?

¿O hay alguna falla en mi comprensión de las restricciones de código / seguridad alrededor de AccountManager / AccountManagerService , de tal manera que esta vulnerabilidad no existe en realidad? He probado el escenario de Cliente A / Cliente B anterior con el AccountManager y mi autenticador personalizado, y mi aplicación cliente de prueba B, que tiene un ámbito de paquete y UID diferentes, pudo obtener el token de autenticación que mi servidor había emitido para mi Prueba la aplicación de cliente A pasando en el mismo authTokenType (durante el cual se me pidió con "Solicitud de acceso" pantalla de concesión, que he aprobado, ya que soy un usuario y, por tanto, ni idea) …

Soluciones posibles

a. "Secreto" authTokenType
Para obtener el token de autenticación, se debe authTokenType el authTokenType ; Se debería authTokenType el authTokenType como un tipo de secreto de cliente, de manera que un token emitido para un tipo de token secreto determinado pueda ser obtenido únicamente por las aplicaciones de cliente "autorizadas" que conocen el tipo de token secreto? Esto no parece muy seguro; En un dispositivo enraizado, sería posible examinar la columna authtokens tabla authtokens en la base de datos de accounts del sistema y examinar los valores authTokenType que se almacenan con mis tokens. Por lo tanto, los tipos de token de autenticación "secretos" que se utilizan en todas las instalaciones de mi aplicación (y cualquier aplicación de terceros autorizada que se utilice en el dispositivo) habrán quedado expuestos en una ubicación central. Al menos con los ID / secretos de cliente de OAuth2, incluso si deben estar empaquetados con la aplicación, se distribuyen entre diferentes aplicaciones de cliente y se puede intentar ocultarlos (lo cual es mejor que nada) para ayudar a desalentar a quienes lo harían Descomprimir / descompilar la aplicación.

segundo. Tokens de autenticación personalizados
De acuerdo con los documentos de AccountManager.KEY_CALLER_UID y AuthenticatorDescription.customTokens , y el código fuente AccountManagerService que he mencionado anteriormente, debería ser capaz de especificar que mi tipo de cuenta personalizada utiliza "tokens personalizados" y girar mi propia implementación de caché / almacenamiento de token dentro de mi costumbre Autenticador, en el que puedo obtener el UID de la aplicación llamante en orden almacenar / buscar tokens de autenticación en una base por UID. Básicamente, tendría una tabla authtokens como la implementación por defecto, excepto que habría una columna de uid añadida para que los tokens estén indexados de forma exclusiva en UID, cuenta y Tipo de Token Auth (en contraposición a la cuenta y el tipo de Token Auth). Esto parece una solución más segura que el uso de authTokenTypes "secretos", ya que esto implicaría usar los mismos authTokenTypes en todas las instalaciones de mi app / authenticator, mientras que los UIDs varían de sistema a sistema y no pueden ser falsificados fácilmente. Aparte de la sobrecarga alegre de llegar a escribir y gestionar mi propio mecanismo de caché de fichas, ¿qué inconvenientes hay en este enfoque en términos de seguridad? ¿Es excesivo? ¿Estoy realmente protegiendo cualquier cosa, o me estoy perdiendo algo tal que incluso con tal implementación en su lugar, todavía sería bastante fácil para un cliente de aplicación malintencionada para obtener el token de autenticación de otro cliente de aplicación utilizando el AccountManager y authTokenType (s) que no son Garantizado para ser secreto (suponiendo que dicha aplicación malintencionada no conoce el secreto del cliente OAuth2, y por lo tanto no puede obtener directamente un nuevo token, pero sólo podría esperar obtener uno que ya estaba en caché en el AccountManager en nombre del cliente de la aplicación autorizada)?

do. Enviar identificador de cliente / secreto con token OAuth2
Podría seguir con la implementación de almacenamiento de token predeterminada de AccountManagerService y aceptar la posibilidad de acceso no autorizado al token de autenticación de mi aplicación, pero podría obligar a las solicitudes de API a incluir siempre el ID de cliente y el secreto de cliente de OAuth2, además del token de acceso. Compruebe en el lado del servidor que la aplicación es el cliente autorizado para el que se emitió el token en primer lugar. Sin embargo, me gustaría evitar esto porque A) AFAIK, la especificación OAuth2 no requiere la autenticación de cliente para las solicitudes de recursos protegidos – sólo el token de acceso es necesario, y B) Me gustaría evitar la sobrecarga adicional de autenticación del cliente en cada uno solicitud.

Esto no es posible en el caso general (todo lo que el servidor obtiene es una serie de mensajes en un protocolo – el código que generó esos mensajes no se puede determinar). Michael

Pero lo mismo podría decirse de la autenticación inicial del cliente en el flujo OAuth2 durante el cual el cliente se emite por primera vez el token de acceso. La única diferencia es que en lugar de autenticar sólo en la solicitud de token, las solicitudes de recursos protegidos también se autenticarán de la misma manera. (Tenga en cuenta que la aplicación cliente podría pasar su ID de cliente y su secreto de cliente a través del parámetro AccountManager.getAuthToken() de AccountManager.getAuthToken() , que mi autenticador personalizado sólo pasaría a mi proveedor de recursos, según el protocolo OAuth2).


Preguntas clave

  1. ¿Es realmente posible que una aplicación obtenga authToken de otra aplicación para una cuenta invocando AccountManager.getAuthToken () con el mismo authTokenType?
  2. Si esto es posible, ¿ es esto un problema de seguridad válido / práctico dentro de un contexto OAuth2?

    Usted nunca podría confiar en un token de autenticación dado a un usuario que permanece en secreto de ese usuario … por lo que es razonable para Android ignorar esta meta de seguridad por obscuridad en su diseño – Michael

    PERO – No estoy preocupado por el usuario (el propietario del recurso) obtener el token de autenticación sin mi consentimiento; Me preocupan los clientes no autorizados (aplicaciones). Si el usuario quiere ser un atacante de sus propios recursos protegidos, entonces él puede golpear a sí mismo fuera. Estoy diciendo que no debería ser posible que un usuario instale mi aplicación de cliente y, sin darse cuenta, una aplicación de cliente "imposter" que pueda acceder al token de autenticación de mi aplicación simplemente porque pasó el authTokenType correcto y el usuario fue Demasiado perezoso / inconsciente / apresurado para examinar la pantalla de solicitud de acceso. Esta analogía puede ser un poco simplificada, pero no considero "seguridad por oscuridad" que mi aplicación de Facebook instalada no puede leer correos electrónicos almacenados en caché por mi aplicación de Gmail, que es diferente de mi (el usuario) enraizando mi teléfono y examinando la caché Contenido yo mismo.

    El usuario necesitaba aceptar una solicitud de acceso a la aplicación (sistema Android) para que la aplicación utilizara su token … Dado que, la solución Android parece estar bien – las aplicaciones no pueden usar silenciosamente la autenticación de un usuario sin preguntar – Michael

    PERO – Esto también es un problema de autorización – el token de autorización emitido para mi cliente "oficial" es la clave para un conjunto de recursos protegidos para los cuales ese cliente y sólo ese cliente está autorizado. Supongo que se podría argumentar que ya que el usuario es el propietario de los recursos protegidos, si acepta la solicitud de acceso de un cliente de terceros (ya sea una aplicación de socio "sactioned" o algún phisher), entonces está autorizando efectivamente el tercero, Cliente que hizo la solicitud para acceder a esos recursos. Pero tengo problemas con esto:

    • El usuario medio no es lo suficientemente consciente de la seguridad como para poder tomar esta decisión con competencia. No creo que debamos depender únicamente del criterio del usuario para tocar "Negar" en la pantalla de solicitud de acceso de Android para evitar incluso un intento de phishing. Cuando se presenta al usuario la solicitud de acceso, mi autenticador podría ser super-detallado y enumerar todos los tipos de recursos protegidos sensibles (que sólo mi cliente debe poder acceder) para los cuales el usuario se concederá si acepta la solicitud, Y en la mayoría de los casos, el usuario seguirá siendo demasiado inconsciente y va a aceptar. Y en otros intentos de phishing más sofisticados, la aplicación "impostora" sólo va a parecer demasiado "oficial" para que el usuario incluso levante una ceja en la pantalla de solicitud de acceso. O bien, aquí hay un ejemplo más contundente: en la pantalla de solicitud de acceso, mi autenticador podría simplemente decir: "No acepte esta solicitud. Si está viendo esta pantalla, una aplicación malintencionada está intentando acceder a su cuenta". Esperemos que, en tal caso, la mayoría de los usuarios denegaría la solicitud. Pero, ¿por qué debería llegar tan lejos? Si Android simplemente mantuvo tokens de autenticación aislados en el ámbito de aplicación de cada aplicación / UID para el que se emitieron, esto sería un problema no. Vamos a simplificar – incluso en el caso de que sólo tengo una aplicación cliente "oficial", y por lo tanto mi proveedor de recursos ni siquiera se preocupa por la emisión de tokens a otros clientes de terceros, como desarrollador debo tener la opción de decir a la AccountManager, "No! Bloquee este token de autenticación para que solo tenga acceso a mi aplicación". Puedo hacer esto si voy a lo largo de la ruta "tokens personalizados", pero incluso en ese caso, no sería capaz de impedir que el usuario de ser presentado por primera vez con la pantalla de solicitud de acceso. Como mínimo, debería estar mejor documentado que la implementación predeterminada de AccountManager.getAuthToken () devolverá el mismo token de autenticación para todas las aplicaciones solicitantes / UIDs.
    • Incluso los documentos Android reconocen a OAuth2 como el " estándar de la industria " para la autenticación (y presumiblemente autorización). La especificación OAuth2 establece claramente que los tokens de acceso no deben ser compartidos entre clientes o divulgados de ninguna manera. ¿Por qué, entonces, la implementación / configuración predeterminada de AccountManager hace que sea tan fácil para un cliente obtener el mismo token de autorización en caché que originalmente se obtuvo del servicio por otro cliente? Una simple solución en el AccountManager sería volver a usar sólo fichas en caché para la misma aplicación / UID bajo el que se obtuvieron originalmente del servicio. Si no hay ningún token de autorización en caché local disponible para un UID dado, debe obtenerse del servicio. O al menos hacer de esta una opción configurable para el desarrollador.
    • En el flujo OAuth de 3 patas (que implica que el usuario conceda acceso al cliente), no se supone que es el proveedor de servicios / recursos (y no, digamos, el sistema operativo) el que llega a A) autenticar el cliente y B ) Si el cliente es válido, presentar al usuario con la solicitud de acceso a la subvención? Parece que Android está (incorrectamente) usurpando este papel en el flujo.

    Pero el usuario puede permitir explícitamente que las aplicaciones reutilicen una autenticación previa a un servicio, lo cual es conveniente para el usuario .– Michael

    PERO – No creo que el ROI en comodidad garantiza el riesgo de seguridad. En los casos en que la contraseña del usuario se almacena en la cuenta del usuario, entonces realmente, la única conveniencia que se está comprando para el usuario es que en lugar de enviar una solicitud web a mi servicio para obtener un nuevo distintivo que está realmente autorizado para El cliente solicitante, se devuelve un token en caché local que no está autorizado para el cliente. Así que el usuario obtiene la ligera conveniencia de ver un diálogo de "Firma en …" por un par de segundos menos, con el riesgo de que el usuario sea mayormente molestado por tener sus recursos robados o mal utilizados.

  3. Teniendo en cuenta que estoy comprometido a usar el protocolo OAuth2 para proteger mis solicitudes de API, B) proporcionar mi propio proveedor de recursos / autenticación OAuth2 (en contraposición a autenticar con decir, Google o Facebook) yc ) utilizar AccountManager de Android para Administrar mi tipo de cuenta personalizada y su token (s), ¿son válidas algunas de mis soluciones propuestas? ¿Qué tiene más sentido? ¿Estoy pasando por alto cualquiera de los pros / contras? ¿Hay alternativas valiosas que no he pensado?

    [Uso] Clientes alternativos No tiene una API secreta que intenta ser accesible solamente a un cliente oficial; La gente va a superar esto. Asegúrese de que todas las API de cara al público sean seguras, sin importar qué cliente (futuro) el usuario esté usando – Michael

    PERO – ¿No derrota uno de los propósitos clave de usar OAuth2 en primer lugar? ¿De qué sirve la autorización si todas las autorizaciones potenciales estarían autorizadas al mismo alcance de los recursos protegidos?

  4. ¿Alguien más ha pensado que esto era un problema, y ​​cómo funcionó? He hecho un extenso Google para tratar de encontrar si otros han sentido que esto es una cuestión de seguridad / preocupación, pero parece que la mayoría de los mensajes / preguntas que implican AccountManager de Android y tokens de autenticación son acerca de cómo autenticarse con una cuenta de Google y no Con un tipo de cuenta personalizado y el proveedor OAuth2. Por otra parte, no pude encontrar a nadie que fue concerend acerca de la posibilidad de que el mismo token de autenticación que utilizan diferentes aplicaciones, lo que me hace pensar si esto es realmente una posibilidad / digno de preocupación en primer lugar (ver mis primeras 2 " " listados arriba).

¡Aprecio su entrada / guía!


En respuesta a…

Respuesta de Michael – Creo que las principales dificultades que tengo con su respuesta son:

  1. Todavía estoy inclinado a pensar que las aplicaciones son clientes separados y distintos de un servicio, en contraposición a que el usuario / teléfono / dispositivo en sí sea un cliente "grande", por lo que un token que ha sido autorizado para una aplicación no debería Por defecto, ser transferible a uno que no lo ha hecho. Parece que usted puede estar insinuando que es discutible considerar cada aplicación como un cliente distinto debido a la posibilidad de que,

    El usuario podría estar ejecutando un teléfono enraizado, leer el token, acceder a su API privada … [o] si el sistema del usuario estaba comprometido (el atacante podría leer el token en este caso)

    Y que por lo tanto, en el gran esquema de cosas, deberíamos considerar el dispositivo como un cliente del servicio, ya que no podemos garantizar la seguridad entre las aplicaciones en el propio dispositivo. Es cierto que si el propio sistema ha sido comprometido, no puede garantizarse la autenticación / autorización de las solicitudes enviadas desde ese dispositivo a un servicio. Pero lo mismo podría decirse, por ejemplo, TLS; La seguridad del transporte es irrelevante si los puntos finales no pueden ser asegurados. Y para la gran mayoría de los dispositivos Android, que no están comprometidos, creo que es más seguro considerar cada cliente de aplicación como un punto final distinto, en lugar de agruparlos todos en uno compartiendo el mismo token de autenticación.

  2. Cuando se presenta con la pantalla "solicitud de acceso" (similar al contrato de licencia de usuario de software que siempre leímos a fondo antes de consentir e instalar), no confío en el criterio del usuario para distinguir una aplicación cliente malintencionada o no autorizada de una que no lo es.

¿Se trata de un problema de seguridad válido / práctico?

Para el cliente oficial A, mi proveedor OAuth2 puede emitir un token de tipo / alcance "super" que otorgue acceso a partes públicas y privadas de mi API

En el caso general, nunca se puede confiar en un token de autenticación dado a un usuario que permanece en secreto de ese usuario . Por ejemplo – el usuario podría estar ejecutando un teléfono con raíces, y leer el token, obteniendo acceso a su API privada. Lo mismo ocurre con el sistema del usuario (el atacante podría leer el token en este caso).

Dicho de otra manera, no hay tal cosa como una API "privada" que es al mismo tiempo accesible a cualquier usuario autenticado, por lo que es razonable que Android ignore este objetivo de seguridad por obscuridad en su diseño.

Una aplicación malintencionada … podría obtener acceso al token OAuth2 almacenado en mi aplicación

Para el caso de la aplicación malintencionada, comienza a parecer más razonable que una aplicación malintencionada no pueda utilizar el token del cliente, ya que esperamos que el sistema de permisos de Android proporcione aislamiento de aplicaciones maliciosas (siempre que el usuario lea / Aceptado cuando lo instalaron). Sin embargo, como usted dice, el usuario necesita aceptar una solicitud de acceso (sistema Android) para que la aplicación use su token.

Teniendo en cuenta que, la solución de Android parece estar bien: las aplicaciones no pueden usar la autenticación de un usuario de forma silenciosa sin preguntar, pero el usuario puede permitir explícitamente que las aplicaciones reutilicen una autenticación previa a un servicio, lo cual es conveniente para el usuario.

Revisión de posibles soluciones

"Secreto" authTokenType … no parece muy seguro

Convenido – es sólo otra capa de seguridad a través de la oscuridad; Suena como cualquier aplicación que desee compartir su autenticación habría tenido que buscar lo que el authTokenType era de todos modos, por lo que la adopción de este enfoque sólo lo hace un poco más incómodo para este desarrollador de aplicaciones hipotético.

Envíe el identificador del cliente / secreto con el símbolo de OAuth2 … para verificar por el lado del servidor que la aplicación es el cliente autorizado

Esto no es posible en el caso general (todo lo que el servidor obtiene es una serie de mensajes en un protocolo – el código que generó esos mensajes no se puede determinar). En esta instancia específica, podría proteger contra la amenaza más limitada de una aplicación cliente / malintencionado (no root). No estoy familiarizado con el AccountManager para comentar (idem para sus soluciones de tokens de autenticación personalizados).

Sugerencia

Ha descrito dos amenazas: aplicaciones malintencionadas que un usuario no desea tener acceso a su cuenta y clientes alternativos que usted (el desarrollador) no desea utilizar partes de la API.

  • Aplicaciones malintencionadas: considere la sensibilidad del servicio que ofrece y, si no es más sensible que, por ejemplo, las cuentas de Google / Twitter, confíe en las protecciones de Android (permisos de instalación, pantalla Solicitud de acceso). Si es más sensible, considere si su restricción de utilizar AccountManager de Android es apropiada. Para proteger fuertemente al usuario contra el uso malintencionado de su cuenta, pruebe la autenticación de dos factores para las acciones peligrosas (véase la adición de los detalles de la cuenta de un nuevo destinatario en la banca en línea).

  • Clientes alternativos: no tienen una API secreta que intenta sólo ser accesible a un cliente oficial; La gente va a superar esto. Asegúrese de que todas las API de cara al público sean seguras, sin importar qué cliente (futuro) utilice el usuario.

Su observación es correcta. Authenticator se ejecutará con el mismo UID que la aplicación de instalación. Cuando otra aplicación se conecta al Administrador de cuentas y obtiene un token para este autenticador, se vinculará al servicio de autenticación proporcionado. Se ejecutará como su UID, por lo que las nuevas cuentas estarán relacionadas con este autenticador. Cuando app llama a getAuthToken, se producirá la vinculación y Authenticator seguirá ejecutándose en la misma UId. Los permisos incorporados por defecto comprueban el UID de la cuenta, de modo que el Authenticator diferente no pueda acceder a otra cuenta desde Authenticator diferente.

Puede resolver este problema con el uso de "Calling UID" para addAccount y GetAuthToken desde que el servicio de administrador de cuentas añade que para agrupar. La implementación de su autenticador puede comprobarlo.

  @Override public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle loginOptions) throws NetworkErrorException { Log.v( TAG, "getAuthToken() for accountType:" + authTokenType + " package:" + mContext.getPackageName() + "running pid:" + Binder.getCallingPid() + " running uid:" + Binder.getCallingUid() + " caller uid:" + loginOptions.getInt(AccountManager.KEY_CALLER_UID)); ... } 

Le sugiero que siga el flujo de autorización en lugar de almacenar el secreto del cliente en su aplicación nativa, ya que otros desarrolladores pueden extraer ese secreto. Tu aplicación no es una aplicación web y no debería tener secretos.

Cuando agrega una cuenta, puede consultar también el archivo callingUId. Usted necesita setUserData en su actividad relacionada con addAccount que se ejecutará como el UID de su aplicación, por lo que puede llamar a setUserData .

GetUserData y setUserData utiliza base de datos sqllite incorporada, por lo que no es necesario crear caché por ti mismo. Sólo puede almacenar tipo de cadena, pero puede analizar json y almacenar información adicional por cuenta.

Cuando hay distintas cuentas de aplicaciones de terceros y se pide getAuthtoken con su cuenta, puede comprobar el UID en el userdata de la cuenta. Si el UID de llamada no aparece en la lista, puede hacer el aviso y / u otras cosas para obtener permiso. Si está permitido, puede agregar un nuevo UID a la cuenta.

Compartir fichas entre aplicaciones : Cada aplicación normalmente se registra con clientid diferente y no debe compartir token. Token es para una aplicación cliente.

Almacenamiento : AccountManager no está cifrando sus datos. Si necesita una solución más segura, debe encriptar los tokens y luego almacenarlos.

Estoy enfrentando el mismo problema arquitectónico para una aplicación.

La solución que obtuve es asociar / hash el token oauth, con el token del proveedor de la aplicación (por ejemplo, el token que Facebook da a una aplicación) y el identificador del dispositivo ( android_id ). Tan sólo la aplicación autorizada, para el dispositivo es capaz de utilizar el token de administrador de cuenta.

Por supuesto, es sólo una nueva capa de seguridad, pero no a prueba de balas.

Creo que @ Michael respondió a la pregunta perfectamente; Sin embargo, para hacer la respuesta más sensata y corta para aquellos que buscan una respuesta rápida estoy escribiendo esto.

Su preocupación por la seguridad de android AccountManager es correcta, pero esto es lo que OAuth está destinado a ser, sobre el que cuenta android AccountManager .

En otras palabras, si está buscando un mecanismo de autenticación muy seguro, esto no sería una buena opción para usted. No debe confiar en ningún fichero en caché para la autenticación, ya que puede revelarse fácilmente al intruso en caso de que exista alguna vulnerabilidad de seguridad en el dispositivo del usuario, como la concesión inadvertidamente de permisos de acceso al intruso, la ejecución de un dispositivo enraizado, etc.

La mejor alternativa a OAuth en sistemas de autenticación más seguros, por ejemplo, las aplicaciones bancarias en línea, está utilizando el cifrado asimétrico mediante claves públicas y privadas, en las que el usuario debe introducir su contraseña cada vez que utilice los servicios. La contraseña se cifra con la clave pública en el dispositivo y se envía al servidor. Aquí, incluso si el intruso se da cuenta de la contraseña cifrada, no puede hacer nada con eso porque no puede descifrarlo con esa clave pública y sólo necesita la clave privada del servidor.

De todos modos, si uno quiere hacer uso del sistema AccountManager del android, así como mantener un alto nivel de seguridad, sería posible por no guardar las fichas en el dispositivo. El método getAuthToken de AbstractAccountAuthenticator puede ser reemplazado así:

 @Override public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { AuthenticatorManager authenticatorManager = AuthenticatorManager.authenticatorManager; Bundle result; AccountManager accountManager = AccountManager.get(context); // case 1: access token is available result = authenticatorManager.getAccessTokenFromCache(account, authTokenType, accountManager); if (result != null) { return result; } final String refreshToken = accountManager.getPassword(account); // case 2: access token is not available but refresh token is if (refreshToken != null) { result = authenticatorManager.makeResultBundle(account, refreshToken, null); return result; } // case 3: neither tokens is available but the account exists if (isAccountAvailable(account, accountManager)) { result = authenticatorManager.makeResultBundle(account, null, null); return result; } // case 4: account does not exist return new Bundle(); } 

En este método, ni el caso 1, el caso 2 ni el caso 4 son válidos porque no hay un token guardado, aunque la account esté allí. Por lo tanto, sólo se devolverá el caso 3 que se puede establecer en la devolución de llamada correspondiente para abrir una Activity en la que el usuario introduce el nombre de usuario y la contraseña para la autenticación.

No estoy seguro de estar en el camino correcto para describir esto más a fondo aquí, pero los mensajes de mi sitio web en AccountManager pueden ayudar por si acaso.

  • Prevención de la piratería de la aplicación android
  • ¿Cómo se puede comprobar el permiso en tiempo de ejecución sin lanzar SecurityException?
  • Proveedor de contenido privado de Android?
  • Referencia sobre Dalvik o Java Virtual Machines?
  • Seguridad de Android App
  • Android RSA Generación de pares de claves - ¿Debo usar Java estándar / Bouncy Castle / Spongy Castle / JSch / Other?
  • Seguridad de SharedPreference de Android
  • Prácticas recomendadas (lo mejor para Android): autenticar a un usuario con acceso a Facebook o Google
  • Usar bloqueo de pantalla en mi aplicación
  • SecurityException - Nombre del paquete de llamadas desconocido -Android 6.0.1
  • Xamarin Código de Seguridad
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.