Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Can we clarify IOSAccessibleStates and how to upgrade from 0.7 to 0.8 ? #290

Open
ou2s opened this issue Oct 7, 2022 · 2 comments

Comments

@ou2s
Copy link

ou2s commented Oct 7, 2022

We have an issue with version 0.7.1 and iOS 16 (no persistence for some users). We, therefore, need to upgrade this library to 0.8 because I think it might solve our issue. We use an encrypted instance.

The release notes for version 0.8 states that it is a breaking change, but I have trouble understanding what to change. Here are my questions:

1/ Do I need to specify an instanceId like explained in the release note? (I don't use multiple instances)

2/ We use this library with redux-persist. Should I make a data migration?

3/ I never specified any IOSAccessibleStates with setAccessibleMode. Do I need to specify one now? Can we please clarify what setAccessibleMode is? What is the default value used if I don't specify setAccessibleMode? Documentation about this method does not really help me understand why and how I should use it.

Thanks for providing this useful lib and thanks in advance for any answers.

@ou2s
Copy link
Author

ou2s commented Oct 7, 2022

I think I managed to answer some of my own questions with more research, thanks to reading the source code, Apple documentation, and @JoniVR comments on his PR. It would be nice if he or @ammarahm-ed could confirm if I understood correctly.

1/ You cannot change keychain accessibility on an existing instance. If you want to change it, you'll need to create a new instance, and therefore you won't be able to access the data stored in the previous instance.

2/ You need a data migration from one store to another one only if you change its instance/accessibility level.

3/ setAccessibleMode define the level of security of the encryption key, which is stored in the keychain. Apple documentation states:

When you use keychain services to store user secrets, the framework’s default behavior provides a reasonable trade-off between security and accessibility. However, in some cases, you might want to make different choices.

For example, by default, you can only access keychain items when the device is unlocked. However, a device not protected by a passcode is always unlocked, so you might want to restrict access further and insist that an item can only be accessed from a device protected by a passcode. Alternatively, you can relax access restrictions to be able to access an item from a background process when the device is locked.

You don't need to specify an IOSAccessibleStates value. The default value used in the library when creating a new instance is AFTER_FIRST_UNLOCK, which is defined by Apple as:

This condition becomes true once the user unlocks the device for the first time after a restart, or if the device does not have a passcode. It remains true until the device restarts again. Use this level of accessibility when your app needs to access the item while running in the background.

The default value in Apple SDK is WHEN_UNLOCKED since iOS 16, which seems to cause an issue with accessing the keychain when the app is launched from the background (like from a Push Notification).

Apple documentation: https://developer.apple.com/documentation/security/keychain_services/keychain_items/restricting_keychain_item_accessibility


The instance on my app which uses 0.7.1 has the WHEN_UNLOCKED default value. Not sure if upgrading to 0.8.0 without any migration will solve my issue. It seems like a lot of the impacted user are on the iPhone 14 models, which suggest it has to do iCloud keychain. But to be honest, I'm still very confused about what to do as I have no data/logs about the impacted users... Any help would be greatly appreciated...

@JoniVR
Copy link
Contributor

JoniVR commented Oct 18, 2022

I think I managed to answer some of my own questions with more research, thanks to reading the source code, Apple documentation, and @JoniVR comments on his PR. It would be nice if he or @ammarahm-ed could confirm if I understood correctly.

1/ You cannot change keychain accessibility on an existing instance. If you want to change it, you'll need to create a new instance, and therefore you won't be able to access the data stored in the previous instance.

Correct. There's probably a way to migrate the existing data, but we haven't seen an implementation yet.

2/ You need a data migration from one store to another one only if you change its instance/accessibility level.

Yes

3/ setAccessibleMode define the level of security of the encryption key, which is stored in the keychain. Apple documentation states:

When you use keychain services to store user secrets, the framework’s default behavior provides a reasonable trade-off between security and accessibility. However, in some cases, you might want to make different choices.

For example, by default, you can only access keychain items when the device is unlocked. However, a device not protected by a passcode is always unlocked, so you might want to restrict access further and insist that an item can only be accessed from a device protected by a passcode. Alternatively, you can relax access restrictions to be able to access an item from a background process when the device is locked.

You don't need to specify an IOSAccessibleStates value. The default value used in the library when creating a new instance is AFTER_FIRST_UNLOCK, which is defined by Apple as:

This condition becomes true once the user unlocks the device for the first time after a restart, or if the device does not have a passcode. It remains true until the device restarts again. Use this level of accessibility when your app needs to access the item while running in the background.

The default value in Apple SDK is WHEN_UNLOCKED since iOS 16, which seems to cause an issue with accessing the keychain when the app is launched from the background (like from a Push Notification).

Not entirely true iirc, the default is still AFTER_FIRST_UNLOCK, though this library used WHEN_UNLOCKED as the default in the javascript code, while the native code used AFTER_FIRST_UNLOCK, in this case, the javascript code became the default, which caused the problems people had mentioned in the issues.

The instance on my app which uses 0.7.1 has the WHEN_UNLOCKED default value. Not sure if upgrading to 0.8.0 without any migration will solve my issue. It seems like a lot of the impacted user are on the iPhone 14 models, which suggest it has to do iCloud keychain. But to be honest, I'm still very confused about what to do as I have no data/logs about the impacted users... Any help would be greatly appreciated...

Indeed, existing instances from 0.7.1 will be using WHEN_UNLOCKED, which will have issues with reading data in the background. I suggest you either write a migration or just create a new instance and notify your users if you need background access.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants