iphone - iOS KeyChain no recupera valores del fondo
background lockscreen (3)
Actualmente estoy almacenando el nombre de usuario (correo electrónico) y un hash salado del correo electrónico y la contraseña en iOS KeyChain. Estoy usando la versión ARC''ified que se encuentra here .
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
[wrapper setObject:APP_NAME forKey:(__bridge id)kSecAttrService];
[wrapper setObject:email forKey:(__bridge id)kSecAttrAccount];
[wrapper setObject:token forKey:(__bridge id)kSecValueData];
Todo esto funciona bien cuando necesito sacar el token para mis llamadas de red mientras la aplicación está activa. Funciona para iniciar sesión desde un inicio limpio, así como todas las llamadas de red en todo momento. El problema comienza cuando la aplicación está en segundo plano.
Tenga en cuenta que esto solo ocurre esporádicamente y aún no he definido el contenido de una versión o dispositivo de iOS específico.
El usuario dispara una ubicación (monitoreo de región) y quiero actualizar el servidor con su estado. Intento sacar la ficha del llavero, de la misma manera que hago para cada otra llamada de red, y actualizo el estado. Pero para algunos usuarios, el valor es nulo. Sin eso, no puedo actualizar las cosas de la red. ¿Por qué funcionaría esto para la mayoría, pero no para un pequeño porcentaje?
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyCustomIdentifier" accessGroup:nil];
NSString *token = [wrapper objectForKey:(__bridge id)kSecValueData];
Volví a la versión que no es ARC de keychainwrapper, pero aún obtengo los mismos resultados. Agradecería cualquier comentario sobre esto. Es solo una pequeña parte de mis usuarios, pero es un problema que me gustaría solucionar y no preocuparme. Gracias por adelantado.
Además, todo mi trabajo de fondo está configurado en un backgroundTask para evitar que se agote el tiempo de espera. No estoy teniendo ningún problema con el trabajo que rodea al llavero, pero no dejo que las cosas avancen hasta que mi token esté lleno.
EDITAR He descubierto mi problema con que keychain no recupere valores del fondo. Publicaré la respuesta a continuación y la aceptaré, ya que creo que esta pregunta puede ser valiosa para otros más adelante.
En mi caso, watchOS2 accede a los datos de llavero en el lado de iOS.
Al principio, se usa kSecAttrAccessibleWhenUnlockedThisDeviceOnly. Puedo leer los datos sin importar si el iPhone está bloqueado o no. Es muy confuso para mí recibir un error cuando Watch intente acceder al llavero:: SecTrustEvaluate [leaf IssuerCommonName SubjectCommonName]
Y en algunos casos se convertirá en: SecOSStatusCon error: [- 25308] Error Domain = NSOSStatusErrorDomain Code = -25308 "ks_crypt: e00002e2 falló al elemento ''oe'' (clase 6, bolsa: 0) Acceso al elemento intentado mientras el llavero está bloqueado. " UserInfo = {NSDescription = ks_crypt: e00002e2 no pudo ''oe'' elemento (clase 6, bolsa: 0) Acceso al elemento intentado mientras llavero está bloqueado.}
Actualizaré mi respuesta si obtengo más información.
Mi pregunta estuvo cerca de la marca por el motivo, pero no del todo. Después de leer blog tras blog, tutorial tras tutorial, finalmente encontré uno que daba una pista de lo que podría estar sucediendo.
Se bloquearon las pantallas de inicio. Los tutoriales de llavero siempre dejaron la configuración de accesibilidad para el llavero en blanco, por lo que el valor predeterminado sería el nivel de acceso más bajo / más seguro de Apple. Sin embargo, este nivel no permite el acceso al llavero si el usuario tiene un código de acceso en la pantalla de bloqueo. ¡Bingo! Esto explica el comportamiento esporádico y por qué esto solo le sucede a un pequeño porcentaje de usuarios.
Una línea de código, resuelve todo el desastre.
[wrapper setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];
Agregue esta línea donde estoy configurando los valores de nombre de usuario y contraseña. Funciona de maravilla. Espero que esto ayude a alguien por ahí. Me confundió por un buen tiempo hasta que pude juntar las piezas.
Use kSecAttrAccessibleAfterFirstUnlock
lugar de kSecAttrAccessibleAlways
.
De la documentación de Apple :
kSecAttrAccessibleAfterFirstUnlock
No se puede acceder a los datos en el elemento llavero después de un reinicio hasta que el usuario haya desbloqueado el dispositivo una vez.Después del primer desbloqueo, los datos permanecen accesibles hasta el próximo reinicio. Esto se recomienda para los artículos a los que se necesita acceder mediante aplicaciones en segundo plano. Los elementos con este atributo migran a un nuevo dispositivo cuando se utilizan copias de seguridad encriptadas.