Giter Club home page Giter Club logo

redux-persist-sensitive-storage's Introduction

redux-persist-sensitive-storage

npm version CircleCI License

Storage engine to use react-native-sensitive-info with redux-persist.

react-native-sensitive-info manages all data stored in Android Shared Preferences and iOS Keychain.

NOTE: Android Shared Preferences are not secure, but there is a branch of react-native-sensitive-info that uses the Android keystore instead of shared preferences. You can use that branch with redux-persist-sensitive-storage if you prefer.

Installation

You can install this package using either yarn or npm. You will also need to install and link react-native-sensitive-info.

Using Yarn:

yarn add redux-persist-sensitive-storage react-native-sensitive-info
react-native link react-native-sensitive-info

Using npm:

npm install --save redux-persist-sensitive-storage react-native-sensitive-info
react-native link react-native-sensitive-info

Usage

To use redux-persist-sensitive-storage, create a sensitive storage instance using createSensitiveStorage and then configure redux-persist according to its documentation using your instance as the storage argument in the configuration.

createSensitiveStorage takes an optional set of configuration options. These are used to configure the keychain service (iOS) and shared preferences name (Android) that react-native-sensitive-info uses. See their documentation for more information.

For redux-persist v5.x or later

import { compose, applyMiddleware, createStore } from "redux";
import { persistStore, persistCombineReducers } from "redux-persist";
import createSensitiveStorage from "redux-persist-sensitive-storage";
import reducers from "./reducers"; // where reducers is an object of reducers

const storage = createSensitiveStorage({
  keychainService: "myKeychain",
  sharedPreferencesName: "mySharedPrefs"
});

const config = {
  key: "root",
  storage,
};

const reducer = persistCombineReducers(config, reducers);

function configureStore () {
  // ...
  let store = createStore(reducer);
  let persistor = persistStore(store);

  return { persistor, store };
}

You may want to only persist some keys in secure storage, and persist other parts of your state in local storage. If that's the case, you can use redux-persist's Nested Persists support. Your configuration might look something like this:

import { AsyncStorage } from "react-native";
import { combineReducers } from "redux";
import { persistReducer } from "redux-persist";
import createSensitiveStorage from "redux-persist-sensitive-storage";

import { mainReducer, tokenReducer } from "./reducers";

const sensitiveStorage = createSensitiveStorage({
  keychainService: "myKeychain",
  sharedPreferencesName: "mySharedPrefs"
});

const mainPersistConfig = {
  key: "main",
  storage: AsyncStorage,
  blacklist: ["someEphemeralKey"]
};

const tokenPersistConfig = {
  key: "token",
  storage: sensitiveStorage
};

let rootReducer = combineReducers({
  main: persistReducer(mainPersistConfig, mainReducer),
  token: persistReducer(tokenPersistConfig, tokenReducer)
});

For redux-persist v4.x

Modify the persistStore call as follows:

import createSensitiveStorage from "redux-persist-sensitive-storage";

// ...

persistStore(store, { storage: createSensitiveStorage(options) });

Here is a more complete example:

import { compose, applyMiddleware, createStore } from "redux";
import { persistStore, autoRehydrate } from "redux-persist";
import createSensitiveStorage from "redux-persist-sensitive-storage";

const store = createStore(
  reducer,
  compose(
    applyMiddleware(...),
    autoRehydrate()
  )
);

persistStore(store, {
  storage: createSensitiveStorage({
    keychainService: "myKeychain",
    sharedPreferencesName: "mySharedPrefs"
  });
);

redux-persist-sensitive-storage's People

Contributors

acuppy avatar casto101 avatar frank-west-iii avatar mkilp avatar randycoulman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redux-persist-sensitive-storage's Issues

Update react-native-sensitive-info to v6

From the docs on v6:

This version uses by default keystore to encrypt/decrypt data on Android.

This should mean that using the keystore branch is no longer necessary.

The upgrade should include a major version update of this package, as it is not backwards compatible.

Error storing data TypeError: Cannot read property 'setItem' of undefined

Hi,

I am receiving this exception at some point.

Error storing data TypeError: Cannot read property 'setItem' of undefined.

store.js

**
 * Storage config for authReducer
 */
const sensitiveStorage = createSensitiveStorage({
    keychainService: 'myKeychain',
    sharedPreferencesName: 'mySharedPrefs'
});

const tokenPersistConfig = {
    key: 'token',
    storage: sensitiveStorage,
    whitelist: ['authReducer']
};


export default (initialState) => {
    let reducer = persistReducer(tokenPersistConfig, reducers);

    let enhancer;
    if (__DEV__) {
        enhancer = compose(applyMiddleware(thunk, logger));
    } else {
        enhancer = compose(applyMiddleware(thunk));
    }
    const store = createStore(reducer, initialState, enhancer);

    return store;

};

package.json

"react": "16.0.0",
"react-native": "0.51.0",
"redux-persist": "^5.9.1",
"redux-persist-sensitive-storage": "^1.0.0",
"react-native-sensitive-info": "^5.1.0"

_reactNativeSensitiveInfo.default.setItem is not a function

Sample code

import { combineReducers } from 'redux'
import { persistReducer } from 'redux-persist'
import AsyncStorage from '@react-native-community/async-storage'
import AuthReducer from '@redux-sections/auth/reducer'
import ProfileReducer from '@redux-sections/profile/reducer'
import createSensitiveStorage from 'redux-persist-sensitive-storage'

const sensitiveStorage = createSensitiveStorage({
  keychainService: 'myAppKeychain',
  sharedPreferencesName: 'myAppPrefs',
})

const mainPersistConfig = {
  key: 'mainPersist',
  storage: AsyncStorage,
  whitelist: ['profile'],
}

const securePersistConfig = {
  key: 'securePersist',
  storage: sensitiveStorage,
}

const rootReducer = combineReducers({
  auth: persistReducer(securePersistConfig, AuthReducer),
  profile: persistReducer(mainPersistConfig, ProfileReducer),
})

export default rootReducer

Error

image

Info

  • react-native: 0.60.4
  • redux-persist: 5.10.0
  • redux-persist-sensitive-storage: ^1.0.0
  • react-native-sensitive-info: ^5.5.0

Will secure storage be created if configuration option is NOT passed?

I have the following code.
import createSensitiveStorage from 'redux-persist-sensitive-storage';
const storage = createSensitiveStorage();

Note that I haven't passed any configuration options to the createSensitiveStorage() function.
What happens if I don't pass the configuration? Will I still get secured storage by default or do I get an unsecured one?

Clarification on authentication

The docs for react-native-sensitive-info, on which this package relies, suggests that the user has to provide authentication info before it allows access to the keychain or shared preferences (eg. fingerprint, touch ID, face recognition). I've deployed this to various devices through testfairy and never get prompted to further authenticate, so am puzzled as to when and why this extra layer of security would kick in. Some clarification would be useful, we'd have to advise our users what to expect if we rolled this out to the stores.

I'm slightly scared where the docs say "Every time the app wants to access the protected keychain item, a prompt by iOS will show up." - we wouldn't want to annoy our users by them having to respond to repeated prompts.

Behaviour of storage on app deletion

Can you please help me understand as to what happens to the data when the app is uninstalled. Does redux-persist-sensitive-storage keep the data or does it just destroy it ??

Why not use the secure branch?

You mention in the README that there is a branch which is more secure for Android.
What is the reasoning for it not being the standard?

Thanks in advance,
Alberto

Improve ES6 compatibility

When using this library in a react-native project that uses Jest for testing, I had to ensure that this module gets transpiled by Jest using its transformIgnorePatterns setting.

There are a number of other libraries that have the same problem, but it should be possible to make this library more universally-usable, perhaps using the module key in package.json. I'm not (yet) clear on the details, but I know there are a number of articles and blog posts around about how to do this well.

Migrate pre-existing storage on first use

This library is great and works well, but it seems doesn't handle pre-existing state (persisted with standard redux-persist) on first use after deployment. This is a big issue for us because we don't want to have to force users to enter pre-login account info again. Are there any guidelines to help with migrating pre-existing state?

Because I only want secure storage one one of my keys, I've moved to using nested persists - could that be the reason I'm losing pre-existing state or is this a generic issue?

Losing Data on IOs

Hi,
I don't know if that's a common issue or not but I had a few users reporting a total loss of their data on IOs after updating the OS or updating apps.
It might be something in my code but maybe you get similar problems in the past and is a known issue.
I'm not sure if this library is still alive...

Android Release fails

Hi,

Using this library crashes my Android release build at the opening of the app.
"react": "16.3.1",
"react-native": "0.55.4",
"react-native-sensitive-info": "^5.2.4",
"redux-persist-sensitive-storage": "^1.0.0",

It works fine on the emulator and also when I connect my phone directly to the computer.
I tried using assemble debug which also works but release does not work at all.

How to use this with android keystore?

Im looking at the different branch of react-native-sensitive-info but I can't figure out how to use that with this module. Additionally, that branch examples' seem to continue using sharedPrefs - how can I use the android keystore with this?

Key values clarification

The readme suggests specific values for keyChainService and sharedPreferencesName:

const storage = createSensitiveStorage({
  keychainService: "myKeychain",
  sharedPreferencesName: "mySharedPrefs"
});

But offers no reasoning for these values and whether you should consider changing them, and to what. For those like myself that is not familiar with keychain, it could do with some explanation. I've also seen some examples in the issues where encrypt: true is included in the object passed into this function - is that documented anywhere?

Another question: in running this in debug mode on a macbook what (if anything) is used instead of keychain? I certainly can't see any new keys added to the mac's keychain.

How to verify it is working?

Hey!

I followed the README and used the secured storage.
But how can I be sure it is working correctly?

Regards

implement redux-persist-sensitive-storage redux-persist react-native-sensitive-info keystore

Hello,
What is the best pratices to implement the library.
There @randy Coulman said

We only store API tokens in sensitive storage. Everything else goes in normal storage (AsyncStorage in react-native, for example). You can call redux-persist's persistStore function multiple times. Unfortunately, I don't have a code example I can share quickly, but if you could create an issue on the repo, that's something we can look at adding to the documentation.

I want to store 2 tokens, here is my redux/index.js

import { combineReducers } from 'redux'
import configureStore from './CreateStore'
import rootSaga from '../Sagas/'
import { persistReducer } from 'redux-persist'
import createSensitiveStorage from "redux-persist-sensitive-storage";


const tokenPersistConfig = {
    key: 'token',
    storage: createSensitiveStorage({
        keychainService: "myKeychain",
        sharedPreferencesName: "mySharedPrefs",
        encrypt: true
    })
};

export default () => {
  /* ------------- Assemble The Reducers ------------- */
  const rootReducer = combineReducers({
    nav: require('./NavigationRedux').reducer,
    github: require('./GithubRedux').reducer,
    login: require('./LoginRedux').reducer,
    search: require('./SearchRedux').reducer,
    filter: require ('./FilterRedux').reducer,
    map: require ('./MapRedux').reducer,
    token: persistReducer(tokenPersistConfig, require('./TokenRedux').reducer),
  });

  return configureStore(rootReducer, rootSaga)
}

Here's my package.json

    "react": "16.0.0",
    "react-native": "0.50.4",
    "react-native-sensitive-info": "git://github.com/mCodex/react-native-sensitive-info.git#keystore",
    "redux-persist": "^5.4.0",
    "redux-persist-sensitive-storage": "^1.0.0",

Regarding [React Native Sensitive Info](React Native Sensitive Info)
Do I use anywhere setItem getItem deleteItem getAllItems ?

How do I know the encrypt worked?
Where the data are stored exactly?

Promise based api

redux-persist just switched to requiring promise based storage in v5.0.0-beta.13

Unfortunately it is going to be a pain to get everyone updated. Technically the storage can support both (like AsyncStorage and localforage) but since this module is specific to redux-persist may was well just go 100% promises and make the peer dep be redux-persist@5

Hydration doesn't always hydrate properly.

Hi, been using this package alongside redux-persist for a while now... Was working great until recently...

In the last couple of days I've noticed that during hydration all of the data is missing. This occurs infrequently. Usually have to force quit the app over a couple of minutes to reproduce. Not really sure what's causing it - switched to Asyncstorage and everything working fine - so I think it might be something to do with react-persist-sensitive-storage.

Package:
react-native-sensitive-info: 5.5.1
redux-persist: 6.0.0
"redux": "^4.0.4"

Here's what my store looks like:

import {createStore, applyMiddleware, compose} from 'redux';
import {persistStore, persistReducer} from 'redux-persist';
import createSensitiveStorage from 'redux-persist-sensitive-storage';
import thunk from 'redux-thunk';
import reducer from './src/reducers';

const initialState = {};
const middleware = [thunk];

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const storage = createSensitiveStorage({
  keychainService: 'appNameKeychain',
  sharedPreferencesName: 'appNameKeystore',
});

const persistConfig = {
  key: 'root',
  storage,
};
const pReducer = persistReducer(persistConfig, reducer);

export const store = createStore(
  pReducer,
  initialState,
  composeEnhancers(applyMiddleware(...middleware)),
);
export const pStore = persistStore(store);

and my App.js (entry point):

...

const App: () => React$Node = () => {
  return (
    <>
      <Provider store={store}>
        <PersistGate loading={null} persistor={pStore}>
          <Navigation />
        </PersistGate>
      </Provider>
    </>
  );
};

and my root reducer looks something like this:

import {combineReducers} from 'redux';
import xreducer from './xreducer';
import xreducer1 from './xreducer1';

export default combineReducers({
  xreducer,
  xreducer1
});

Any help with diagnosing this issue would be welcome.

Update README for redux-persist 5

redux-persist v5.x has changed the API, so the example in our README is now outdated. We need to update the example to match the latest version.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.