Search code examples
reactjslocal-storageamazon-cognitosession-storage

Storing CognitoUser in cache make him lose some properties


I'm currently using AWS Cognito in my application.

When a user first connects whit his account, Cognito returns NEW_PASSWORD_REQUIRED as a challenge, which is fine.

I want to redirect to a page where the user can set his new password, so I put the response from Auth.signIn in storage (I tried local storage, session storage and Cache from AWS Amplify) but when I get it back on the other page, it lose some properties and Auth.completeNewPassword returns the error : 'user.completeNewPasswordChallenge is not a function'

Login.js :

try {
  var authPromise = Auth.signIn(this.state.email, this.state.password);
  authPromise.then((result) => {
    console.log(result);
    if (result.challengeName === 'NEW_PASSWORD_REQUIRED') {
      Cache.setItem("CognitoUser", result);
      this.props.history.push("/login/newPassword");
    }
    else {
      this.props.userHasAuthenticated(true);
      this.props.history.push("/");
    }
  });
} catch (e) {
  alert(e.message);
  this.setState({ isLoading: false });
}

NewPassword.js :

    try {
        var user = Cache.getItem("CognitoUser");
        if (user) {
            await Auth.completeNewPassword(user, this.state.newPassword);
            this.props.history.push("/");
            Cache.removeItem("CognitoUser");
        }
    } catch (e) {
        alert(e.message);
        this.setState({ isChanging: false });
    }

Any ideas ?


Solution

  • It's javascript so when you write to your localcache and serializes your result into the "CognitoUser" key , it's stored as a a string, which afterwards deserialized will be a plain old Object unaware of the original type before serialization.

    Original cause is maybe that your "result" type may expose functions which are not serializable (if not a getter, or if a getter with arguments). I suggest you to call and store all the data you want into separate keys and re-read them later.

    Cache.setItem("CognitoUser", result);
    Cache.setItem("CognitoUser-value-1", result.myFunction1("myArg1"));
    Cache.setItem("CognitoUser-value-2", result.myFunction2("myArg2"));
    
    // ..
    
    var user = Cache.getItem("CognitoUser");
    var myVal1 = Cache.getItem("CognitoUser-value-1");
    var myVal2 = Cache.getItem("CognitoUser-value-2");
    

    You can also keep one single key "CognitoUser" in your localStorage if you make all said functions serializable. For instance, extend the type of your result adding prototypes getter functions (no arguments), each calling and returning respective myFunctionX("myArgX") functions, so that they'll appear in the JSON.stringify process.