3 Replies
      Latest reply on Apr 8, 2019 2:01 AM by eskimo
      Bennyb123 Level 1 Level 1 (0 points)

        I'm developing a react-native app using https://github.com/oblador/react-native-keychain to save and get things from keychain.


        The things stored in keychain (and some other things) should be accessible from all our apps. So in xcode under capabilities I have activated an app-group "group.something.test".


        I'm using setGenericPassword function of react-native-keychain like this:


            await Keychain.setGenericPassword(
              'a username',
              'a password',
                service: 'a userId',
                accessible: Keychain.ACCESSIBLE.ALWAYS,
                accessGroup: 'group.something.test',
                accessControl: Keychain.ACCESS_CONTROL.DEVICE_PASSCODE


        In the native module this will store it to the keychain something like this:


            SecAccessControlRef sacRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
            NSDictionary *attributes = attributes = @{
                (__bridge NSString *)kSecClass: (__bridge id)(kSecClassGenericPassword),
                (__bridge NSString *)kSecAttrService: service,
                (__bridge NSString *)kSecAttrAccount: username,
                (__bridge NSString *)kSecValueData: [password dataUsingEncoding:NSUTF8StringEncoding],
                (__bridge NSString *)kSecAttrAccessControl] = (__bridge id)sacRef,
                (__bridge NSString *)kSecAttrAccessGroup] = accessGroup;
                OSStatus osStatus = SecItemAdd((__bridge CFDictionaryRef) attributes, NULL);


        And keychain items are retrieved in the following way:


            await Keychain.getGenericPassword({ service: 'a userId' });


        Which will will run the following native code:


            NSDictionary *query = @{
                (__bridge NSString *)kSecClass: (__bridge id)(kSecClassGenericPassword),
                (__bridge NSString *)kSecAttrService: service,
                (__bridge NSString *)kSecReturnAttributes: (__bridge id)kCFBooleanTrue,
                (__bridge NSString *)kSecReturnData: (__bridge id)kCFBooleanTrue,
                (__bridge NSString *)kSecMatchLimit: (__bridge NSString *)kSecMatchLimitOne,
                (__bridge NSString *)kSecUseOperationPrompt:@"Authenticate to retrieve secret"
            CFTypeRef foundTypeRef = NULL;
              OSStatus osStatus = SecItemCopyMatching((__bridge CFDictionaryRef) query, (CFTypeRef*)&foundTypeRef);


        This works fine in the first app, I can store and retrieve an item from the keychain.

        When I deploy a second app through xcode by just changing Display name and Bundle identifier to something different it also works. I can retrieve the key saved by the first app.

        However if I now go back to the first app and try to retrieve the keychain item osStatus is -25308 (errSecInteractionNotAllowed).

        If I uninstall the second app, it will start working in the first app again.


        What am I doing wrong? Is there something more I need to do in the project settings?

        I have also tried with keychain group capability, having the same keychain group as the first index in the keychain groups array, using that id as kSecAttrAccessGroup.