Reputation: 10232
It seems there is an issue using the encrypt option of redux-persist in react-native:
https://github.com/maxdeviant/redux-persist-transform-encrypt/issues/15
Can anyone help with any solution/workaround to use redux persist to encrypt and store a login token in react-native?
When I try to use the redux persist with the redux-persist-transform-encrypt i get
Redux-persist-transform-encrypt: expected outbound state to be a string error
import { createStore, compose, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import { persistStore, autoRehydrate } from 'redux-persist';
import { AsyncStorage } from 'react-native';
import createEncryptor from 'redux-persist-transform-encrypt';
import reducers from './reducers';
const store = createStore(
reducers,
{},
compose(
applyMiddleware(ReduxThunk),
autoRehydrate(),
),
);
const encryptor = createEncryptor({
secretKey: 'my-super-secret-key-999',
});
persistStore(
store,
{
storage: AsyncStorage,
whitelist: ['auth'],
transforms: [encryptor],
},
);
export default store;
My auth state is something like this:
const INITIAL_STATE = {
user: null,
token: ''
};
Is there any solution to use redux-persist-transform encrypt or the transform and other package to encrypt the token when using redux persist?
Upvotes: 1
Views: 5659
Reputation: 1145
In my case,
I create a file encryptionTransform.js
var CryptoJS = require('crypto-js');
import {createTransform} from 'redux-persist';
const secureRandomKey = 'd5552d588d8c5b088f033296fffb7314';
// Custom encryption transform
const encryptionTransform = createTransform(
// Transform state on its way to being serialized and stored
(inboundState, key) => {
const jsonString = JSON.stringify(inboundState);
const encryptedData = CryptoJS.AES.encrypt(
jsonString,
secureRandomKey,
).toString();
return encryptedData;
},
// Transform state being rehydrated
(outboundState, key) => {
const bytes = CryptoJS.AES.decrypt(outboundState, secureRandomKey);
console.log('bytes :====== ', bytes);
const decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log('decryptedData :====== ', decryptedData);
return decryptedData;
},
);
export default encryptionTransform;
then import to my store
const persistConfig = {
version: 0,
key: 'root',
storage: AsyncStorage,
whitelist: persistWhitelist,
timeout: 10000,
transforms: [encryptionTransform],
};
const persistedReducer = persistReducer(persistConfig, reducers);
Upvotes: 0
Reputation: 2989
This is working fine and store data in session storage.
Use below to encript redux data.
1) install redux-persist-transform-encrypt module
yarn add redux-persist-transform-encrypt
npm install redux-persist-transform-encrypt --save
2) import redux files.
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import createEncryptor from 'redux-persist-transform-encrypt';
import storageSession from 'redux-persist/lib/storage/session';// store data in session storage
// import storage from 'redux-persist/lib/storage'; // store data in local storage
import promise from 'redux-promise';
import rootReducer from './path/reducers/';
const encryptor = createEncryptor({
secretKey: 'test@key12',
});
const persistConfig = {
key: 'root',
storage:storageSession,
// storage:storage,
transforms: [encryptor],
}
const persistedReducer = persistReducer(persistConfig, rootReducer)
export default () => {
let store = createStore(persistedReducer)
let persistor = persistStore(store)
return { store, persistor }
}
Upvotes: 0
Reputation: 1217
This worked for me:
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import createEncryptor from 'redux-persist-transform-encrypt';
import storage from 'redux-persist/lib/storage';
import rootReducer from '/path/to/your/rootReducer';
const encryptor = createEncryptor({
secretKey: 'omg-this-is-some-secret-stuff',
});
const persistConfig = {
key: 'root',
storage,
transforms: [encryptor],
};
const reducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(reducer);
export const persistor = persistStore(store);
Upvotes: 2
Reputation: 10232
I found a solution using the customTransform instead of redux-persist-transform-encrypt:
import { createStore, compose, applyMiddleware } from 'redux';
import ReduxThunk from 'redux-thunk';
import { persistStore, createTransform, autoRehydrate } from 'redux-persist';
import { AsyncStorage } from 'react-native';
import CryptoJS from 'crypto-js';
import reducers from './reducers';
const store = createStore(
reducers,
{},
compose(
applyMiddleware(ReduxThunk),
autoRehydrate(),
),
);
const encrypt = createTransform(
(inboundState, key) => {
if (!inboundState) return inboundState;
const cryptedText = CryptoJS.AES.encrypt(JSON.stringify(inboundState), 'secret key 123');
return cryptedText.toString();
},
(outboundState, key) => {
if (!outboundState) return outboundState;
const bytes = CryptoJS.AES.decrypt(outboundState, 'secret key 123');
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
return JSON.parse(decrypted);
},
);
persistStore(
store,
{
storage: AsyncStorage,
whitelist: ['auth'], // <-- keys from state that should be persisted
transforms: [encrypt],
},
);
export default store;
When using redux-persist initial state is triggered before rehydrating is finished so I had to apply this too:
Upvotes: 4