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,
                                                                             kSecAttrAccessibleAlways,
                                                                             kSecAccessControlDevicePasscode,
                                                                             &error);
            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.