I'm trying to initialize the secure storage plugin. When this fails it means the user does not have a secure lockscreen set. Using the github page i'm trying to recreate the sample provided:
var ss;
var _init = function () {
ss = new cordova.plugins.SecureStorage(
function () {
console.log('OK');
},
function () {
navigator.notification.alert(
'Please enable the screen lock on your device. This app cannot operate securely without it.',
function () {
ss.secureDevice(
function () {
_init();
},
function () {
_init();
}
);
},
'Screen lock is disabled'
);
},
'my_app');
};
_init();
This is my attempt:
private createSecureStorage() {
this.secureStorageAPI.create(this.storeName).then(
(storage: SecureStorageObject) => {
this.secureStorage = storage;
}).catch(
(error) => {
this.dialogs.alert( 'Please enable the screen lock on your device. This app cannot operate securely without it.').then(
() => {
// Alert Dismissed, should open the secure lockscreen settings here
this.secureStorage.secureDevice().then(
() => {
// Try again
this.createSecureStorage();
}
).catch( () => {
// Try again
this.createSecureStorage();
})
} )
} );
}
The problem i'm having is that when the secureStorageApi.create call fails, secureStorage will be undefined so I can't use it to call call secureDevice().
Any help would be much appreciated.
I'm trying to initialize the secure storage plugin. When this fails it means the user does not have a secure lockscreen set. Using the github page i'm trying to recreate the sample provided:
var ss;
var _init = function () {
ss = new cordova.plugins.SecureStorage(
function () {
console.log('OK');
},
function () {
navigator.notification.alert(
'Please enable the screen lock on your device. This app cannot operate securely without it.',
function () {
ss.secureDevice(
function () {
_init();
},
function () {
_init();
}
);
},
'Screen lock is disabled'
);
},
'my_app');
};
_init();
This is my attempt:
private createSecureStorage() {
this.secureStorageAPI.create(this.storeName).then(
(storage: SecureStorageObject) => {
this.secureStorage = storage;
}).catch(
(error) => {
this.dialogs.alert( 'Please enable the screen lock on your device. This app cannot operate securely without it.').then(
() => {
// Alert Dismissed, should open the secure lockscreen settings here
this.secureStorage.secureDevice().then(
() => {
// Try again
this.createSecureStorage();
}
).catch( () => {
// Try again
this.createSecureStorage();
})
} )
} );
}
The problem i'm having is that when the secureStorageApi.create call fails, secureStorage will be undefined so I can't use it to call call secureDevice().
Any help would be much appreciated.
Share Improve this question edited Oct 2, 2017 at 6:48 Juxture asked Oct 2, 2017 at 6:29 JuxtureJuxture 2533 silver badges15 bronze badges 1- No one able to help with this one? I think this might be a faulty design because you need the SecureStorage object in order to call secureDevice() – Juxture Commented Oct 3, 2017 at 11:17
3 Answers
Reset to default 3For everyone that needs this to work right now modify:
node_modules\@ionic-native\secure-storage\index.js
Working code
It should look like this:
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Injectable } from '@angular/core';
import { CordovaInstance, Plugin, CordovaCheck, IonicNativePlugin } from '@ionic-native/core';
/**
* @hidden
*/
var SecureStorageObject = (function () {
function SecureStorageObject(_objectInstance) {
this._objectInstance = _objectInstance;
}
/**
* Gets a stored item
* @param key {string}
* @returns {Promise<string>}
*/
SecureStorageObject.prototype.get = function (key) { return; };
/**
* Stores a value
* @param key {string}
* @param value {string}
* @returns {Promise<any>}
*/
SecureStorageObject.prototype.set = function (key, value) { return; };
/**
* Removes a single stored item
* @param key {string}
* @returns {Promise<string>} returns a promise that resolves with the key that was removed
*/
SecureStorageObject.prototype.remove = function (key) { return; };
/**
* Get all references from the storage.
* @returns {Promise<string[]>} returns a promise that resolves with array of keys storage
*/
SecureStorageObject.prototype.keys = function () { return; };
/**
* Clear all references from the storage.
* @returns {Promise<any>}
*/
SecureStorageObject.prototype.clear = function () { return; };
return SecureStorageObject;
}());
/**
* @hidden
*/
var SecureDeviceObject = (function () {
function SecureDeviceObject(_objectInstance) {
this._objectInstance = _objectInstance;
}
/**
* Brings up the screen-lock settings
* @returns {Promise<any>}
*/
SecureStorageObject.prototype.secureDevice = function () { return; };
return SecureDeviceObject;
}());
export { SecureStorageObject, SecureDeviceObject };
__decorate([
CordovaInstance({
callbackOrder: 'reverse'
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "get", null);
__decorate([
CordovaInstance({
callbackOrder: 'reverse'
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String, String]),
__metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "set", null);
__decorate([
CordovaInstance({
callbackOrder: 'reverse'
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "remove", null);
__decorate([
CordovaInstance({
callbackOrder: 'reverse'
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "keys", null);
__decorate([
CordovaInstance({
callbackOrder: 'reverse'
}),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], SecureStorageObject.prototype, "clear", null);
__decorate([
CordovaInstance(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], SecureDeviceObject.prototype, "secureDevice", null);
/**
* @name Secure Storage
* @description
* This plugin gets, sets and removes key,value pairs from a device's secure storage.
*
* Requires Cordova plugin: `cordova-plugin-secure-storage`. For more info, please see the [Cordova Secure Storage docs](https://github./Crypho/cordova-plugin-secure-storage).
*
* The browser platform is supported as a mock only. Key/values are stored unencrypted in localStorage.
*
* @usage
*
* ```typescript
* import { SecureStorage, SecureStorageObject } from '@ionic-native/secure-storage';
*
* constructor(private secureStorage: SecureStorage) { }
*
* ...
*
* this.secureStorage.create('my_store_name')
* .then((storage: SecureStorageObject) => {
*
* storage.get('key')
* .then(
* data => console.log(data),
* error => console.log(error)
* );
*
* storage.set('key', 'value')
* .then(
* data => console.log(data),
* error => console.log(error)
* );
*
* storage.remove('key')
* .then(
* data => console.log(data),
* error => console.log(error)
* );
*
* });
*
*
* ```
* @classes
* SecureStorageObject
*/
var SecureStorage = SecureStorage_1 = (function (_super) {
__extends(SecureStorage, _super);
function SecureStorage() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Creates a namespaced storage.
* @param store {string}
* @returns {Promise<SecureStorageObject>}
*/
SecureStorage.prototype.create = function (store) {
return new Promise(function (res, rej) {
var instance = new (SecureStorage_1.getPlugin())(
function () {
res(new SecureStorageObject(instance));
},
function () {
rej(new SecureDeviceObject(instance));
},
store);
});
};
return SecureStorage;
}(IonicNativePlugin));
SecureStorage.decorators = [
{ type: Injectable },
];
/** @nocollapse */
SecureStorage.ctorParameters = function () { return []; };
__decorate([
CordovaCheck(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", Promise)
], SecureStorage.prototype, "create", null);
SecureStorage = SecureStorage_1 = __decorate([
Plugin({
pluginName: 'SecureStorage',
plugin: 'cordova-plugin-secure-storage',
pluginRef: 'cordova.plugins.SecureStorage',
repo: 'https://github./Crypho/cordova-plugin-secure-storage',
platforms: ['Android', 'Browser', 'iOS', 'Windows']
})
], SecureStorage);
export { SecureStorage };
var SecureStorage_1;
//# sourceMappingURL=index.js.map
Then you'll be able to use:
private createSecureStorage() {
this.secureStorageAPI.create(this.storeName).then(
(storage: SecureStorageObject) => {
console.log("secure");
this.secureStorage = storage;
}).catch(
(secureDeviceObject) => {
this.dialogs.alert( 'Please enable the screen lock on your device. This app cannot operate securely without it.').then(
() => {
// Alert Dismissed, should open the secure lockscreen settings here
secureDeviceObject.secureDevice().then(
() => {
// Try again
console.log("Success");
this.createSecureStorage();
} ).catch( () => {
// Try again
console.log(" Error ")
this.createSecureStorage();
})
} );
} );
}
What has changed?
What i've done is moving the secureDevice function to a new object called SecureDeviceObject and changed the decorators. By doing this you cannot use this object to try to call the get and set functions etc.
This is the new object:
var SecureDeviceObject = (function () {
function SecureDeviceObject(_objectInstance) {
this._objectInstance = _objectInstance;
}
/**
* Brings up the screen-lock settings
* @returns {Promise<any>}
*/
SecureStorageObject.prototype.secureDevice = function () { return; };
return SecureDeviceObject;
}());
Then i've changed the decorater:
__decorate([
CordovaInstance(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], SecureDeviceObject.prototype, "secureDevice", null);
The last change is making the reject promise return the secureDeviceObject:
SecureStorage.prototype.create = function (store) {
return new Promise(function (res, rej) {
var instance = new (SecureStorage_1.getPlugin())(
function () {
res(new SecureStorageObject(instance));
},
function () {
rej(new SecureDeviceObject(instance));
},
store);
});
};
I suppose this is not the best possible fix, but it was the best i can do :D Tested on android 4 till 8. Working on all these!
Hope it helps someone :)
Thanks @JudgeFudge for pointing me in the right direction
This problem is already tracked as an issue, see: https://github./ionic-team/ionic-native/issues/1944.
If you need a quick solution for this you can try one of the following steps:
1) Downgrade the Ionic SecureStorage plugin, maybe this issue does not occur in a previous version.
2) Try to fix the problem yourself. You can find the sources in your node_modules folder right here (if you need help with that, I can try to have to look at this later):
node_modules\cordova-plugin-secure-storage\src\android\SecureStorage.java node_modules\cordova-plugin-secure-storage\src\ios\SecureStorage.m
.
Here i sent a pull request that fix this bug.
Here:
create(store: string): Promise<SecureStorageObject> {
return getPromise<SecureStorageObject>((res: Function, rej: Function) => {
const instance = new (SecureStorage.getPlugin())(
() => res(new SecureStorageObject(instance)),
rej,
store
);
});
}
Simple change the reject callback:
() => rej(new SecureStorageObject(instance)),
Inside ionic-native/src/@ionic-native/plugins/secure-storage/index.ts
then:
npm install
npm run build
and at the end copy the plugin piled on you npm_modules folder:
cp -r ionic-native/dist/@ionic-native/plugins/secure-storage/ /your_project/node_modules/@ionic-native/
UPDATE:
They merge the PR.
Here how to use it:
{ this.storage = await this.secureStorage.create('my_storage'); } catch (e) { await e.secureDevice(); }