Keychain touch id issue on ios

I need help please, I am using this plugin https://ionicframework.com/docs/native/keychain-touch-id for fingerprint and face ID, using the example code, it works on android, however on IOS I am getting an error Password could not be save in chain

my angular code looks like

await this.keychainTouchId.isAvailable().then((res: any) => {
   console.log(res); `// res = true`
  this.keychainTouchId.save('refresh_token', credentials, true).then((result: any) => {
     console.log(result);`  // result = Password could not be save in chain`
     return result;
   }).catch((err: any) => {
      console.log('key save error ' + err)
      return err;
});

I believe this might be broken because i created cordova app project just to test it, using the example code in https://github.com/sjhoeksma/cordova-plugin-keychain-touch-id the fingerprint dialog shows on ios. So I am left really confused.
Is the an issue with the ionic-native library?

Try removing the third parameter in save method call, this method have 2 parameters only, and the error message you have is a generic catch in this method.

Plugin code

Hi, first of all thanks for looking at this question.,

I tried it has shown in the example code in ionic.it shows an error. looking at the save method it has this extra argument userAuthenticationRequired doesn’t seem to be optional.

save(key: string, password: string, userAuthenticationRequired: boolean): Promise<any>;

Yes Ionic example is wrong, I was facing the same issues past month, I’m using this version of ionic native, it does not have this error.

"@ionic-native/keychain-touch-id": "5.15.1"

thanks again. i downgraded to that version however, when i run the app when it gets to the part that calls .save method. The app force closes. I am looking to find an alternative. You have any suggestions?

Try to log error with xcode or android studio

Downgraded to ionic 4

await this.keychainTouchId.isAvailable().then((res: any) => {
      console.log(res); // null on IOS but YES on Android
      if (res) {
        //save
      }
        }).catch((error: any) => {
            console.log('no Available');
 });

Using iphone 11 not emulator. So not sure why it will return null. Any ideas what I might be missing?

Thanks

Change from EddyVerbruggen plugin to this https://github.com/sjhoeksma/cordova-plugin-keychain-touch-id

And try a mix of that and this solution https://ionicframework.com/docs/native/keychain

thanks again for the reply. So I gave it a try and still, nothing got null from result

async login(credentials: any) {
        if (await this.platform.ready()) {
            if (this.platform.is('ios')) {
                alert('ios');
                await this.keychain.set('refresh_token', credentials.refresh_token, true).then((result: any) => {
                    alert(result) //null
                }).catch((err: any) => {
                    return err;
                });
            }
        }

Take care with async/await sintax, start from scrach this metho, do not use async await at all, use then and catch to resolve the promises.

You have two things that could braking the plugin lifecicle:

  1. The platform ready await inside an if
  2. calling set method with await but using then to resolve the promise.
1 Like

thanks again so changed it to

 login(credentials: any, emit?: boolean) {
        this.platform.ready().then((readySource) => {
            if (this.platform.is('ios')) {
                alert('ios');
                this.keychain.set('refresh_token', credentials.refresh_token, true).then((result: any) => {
                    alert(result) // still null
                    console.log(result);
                }).catch((err: any) => {
                    alert(err);
                });
            }
        }).catch((err: any) => {
           alert(err);
       });

still nothing

looks good, but I’m not sure about the return in set method, it’s promise, but I never use it return before. If you want to get the saved data use the get method after set the data.

About async/await, don’t get me wrong, I use it all time, but for platform ready never, I prefer use then catch notation for it.

try this

await this.keychain.set(‘refresh_token’, credentials.refresh_token, true);
const resp = await this.keychain.set(‘refresh_token’, ‘a message’);

remember always wrap your await calls into try catch

Hi so after a while I believe I found the issue.

ionic cordova plugin add cordova-plugin-keychain-touch-id is installing old version of the code which doesn’t have userAuthenticationRequired needed to install the one directly from the git repo which is ionic cordova plugin add https://github.com/sjhoeksma/cordova-plugin-keychain-touch-id this might solve your issue also so you can use the latest version

1 Like

Good to know thank’s

Hi, got some more details from xcode

2020-04-04 17:02:26.514607+0100 HelloWorld[3422:896268] THREAD WARNING: [‘TouchID’] took ‘21.125977’ ms. Plugin should use a background thread.

2020-04-04 17:02:26.529443+0100 HelloWorld[3422:896522] [access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSFaceIDUsageDescription key with a string value explaining to the user how the app uses this data.

However

ionic cordova plugin add https://github.com/simon-ntitle/cordova-plugin-keychain-touch-id.git --variable FACEID_USAGE_DESCRIPTION="For easy authentication"

so not sure why it is complaining

yo should to add in config.xml NSFaceIDUsageDescription with a description of use for Face Recognition

In your config.xml, insied ios platform section add the following:

<config-file parent="NSFaceIDUsageDescription" target="*-Info.plist">
            <string>a here your description</string>
        </config-file>