react-native-keychain: function getGenericPassword returns invalid data on ios

Hi guys. I have a problem.

I created a class in my project.

import Keychain, { SharedWebCredentials } from 'react-native-keychain';

export class Session {
    public static async setGenericPassword(username: string, password: string): Promise<void> {
        await Keychain.setGenericPassword(username, password);
    }

    public static async getGenericPassword(): Promise<SharedWebCredentials | false> {
         return await Keychain.getGenericPassword();
    }

    public static async resetGenericPassword(): Promise<void> {
        await Keychain.resetGenericPassword();
    }
}

Why am I calling the data retrieval function in my code.

useEffect(() => {
    const runEffectAsync = async () => {
        const credentials = await Session.getGenericPassword();

        console.log('credentials', credentials);
    };
    runEffectAsync();
}, []);

I run my application for the first time and the console displays.

credentials false

I close the application and run again, and the console displays.

credentials {"password": "1", "service": "...here app id...", "storage": "keychain", "username": "_pfo"}

I did not use the setGeneris Password function and did not write anything to the storage, I ran my application twice in half of its installation. This behavior is typical only for ios, since the android works fine. What to do with this problem?

I checked this problem on versions 6.1.1 and 6.1.0 there she is present.

React Native: 0.62.2 react-native-keychain: 6.1.1

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 15
  • Comments: 24

Most upvoted comments

getting EXACTLY the same issue, i’m getting _pfo on my username, and 1 on my password, please someone help us both

After some digging I suspect the problem is firebase analytics. I think it’s also using that same keychain service and it’s saving it’s own values. That’s probably why changing the service also works. Testing that assumption now.

@vomchik, you can fix it by setting your own key. This way it wont get overwritten.

var settings =  { service: 'com.appname-some-key' };
await Keychain.setGenericPassword(username,password, settings);
await Keychain.getGenericPassword(settings);
await Keychain.resetGenericPassword(settings);

I solved the problem using password verification, as the password length cannot be less than 7 characters.

useEffect(() => {
    const runEffectAsync = async () => {
        const credentials = await Session.getGenericPassword();
        if (credentials && credentials.username && credentials.password && credentials.password.length > 7) {
            console.log('credentials', credentials)
        } else {
            console.log('no credentials');
        }
    };
    runEffectAsync();
}, []);

But this is a temporary solution, you do not need to apply it. We are waiting for corrections from the authors of this library.

Same issue here…

React Native: 0.59.10 react-native-keychain: 3.1.3

Same issue here… “react-native”: “0.62.2”, “react-native-keychain”: “^6.1.1”,

Just deleted Firebase from the project and now all works fine 🤷‍♂️ Currently, I using Firebase 6.18. Is someone able to check it on the newest version?

BTW, _pfo => previous_first_open_count

Hey @JoelOnGithub, There were few things we found out that was causing issues with the keychain on ios and android. The main issue we had with ios was that leaving the service prop using the default value of the bundle id didnt work. Because of that we defined the service prop to be a random generated key, GUID for example. We also had some issues with Android where it wasnt able to store the keys.

On the end our config looked something like this:

{
  accessControl:
    Platform.OS === 'ios' ? undefined : ACCESS_CONTROL.APPLICATION_PASSWORD,
  accessible: ACCESSIBLE.WHEN_UNLOCKED, // iOS only
  securityLevel: SECURITY_LEVEL.SECURE_SOFTWARE, // Android only
  rules: 'none', // Android only
  // Keychain doesnt work with BundleId which is why we specify the service manually
  service: 'fba355de-1d7c-40be-b587-ad8805f8c042',
}

did anyone figure out the solution for randomly username getting set to _pfo and password to 1 Changing the service property didn’t help @fobtracker

The collision is caused by Firebase but the key and password should still be stored in the keychain. So technically Firebase SDK isn’t doing anything wrong. Any 3rd party library could store data in the iOS keychain. The issue is that this library fails to read the correct item out of the keychain items.

Getting the same error here. Applied a temporary fix waiting for a permanent solution!! Thank!!

For any future reference, we fixed the issue by defining the service property for the config options. More info here -> https://www.npmjs.com/package/react-native-keychain#options