Load the State from the Session

From @jayair on Mon Apr 10 2017 01:03:55 GMT+0000 (UTC)

Link to chapter - http://serverless-stack.com/chapters/load-the-state-from-the-session.html

Copied from original issue: https://github.com/AnomalyInnovations/serverless-stack-com/issues/40

From @jayair on Thu Jul 27 2017 19:03:21 GMT+0000 (UTC)

@yashg5 The token does expire after an hour but the way the app is set up, when the user refreshes the page we check the session in the Local Storage (the SDK does this) and re-load it.

However, there is a corner case that we are not handling. If the user does not refresh the page within an hour, then the token will expire and you’ll get an error. We are going to put out an update to address this soon. But you can easily handle this yourself.

From @teejK on Sat Oct 07 2017 00:00:04 GMT+0000 (UTC)

Hey, I’m new to javascript, so maybe this is a noob question.
But, we seem to define componentDidMount without calling it?

Do async class methods get called automatically? I can’t seem to suss out where it gets called.

EDIT: Nevermind, found it:

From @jayair on Sat Oct 07 2017 01:38:49 GMT+0000 (UTC)

@teejK No worries. Yup part of the React component lifecycle.

From @TheDagger on Sun Dec 10 2017 21:58:37 GMT+0000 (UTC)

I have a newbie question as well, the line !this.state.isAuthenticating && proceeds after the && to follow with the page to be rendered and a bunch of the html’ish code. How is this working exactly? The way I understand return functions is they return content, true or false. So if the state is currently authenticating it will return true && the content? How do you return both? This is the part that doesn’t make sense to me. Likewise how does it return false and the content at the same time? Can a return statement return 2 things back like that? I come from PHP where you could only return 1 thing or you’d have to return a JSON or Array to return multiple types

From @jayair on Mon Dec 11 2017 11:59:23 GMT+0000 (UTC)

@TheDagger Yeah that line is basically using short-circuit evaluation to conditionally render our component.

The short-circuit expression x and y is equivalent to the conditional expression if x then y else false…

So if !this.state.isAuthenticating is true then render our component (return the JSX) or just return false.

Here is a bit more info on it - https://reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator

Hopefully that makes sense.

const childProps = {
    isAuthenticated: this.state.isAuthenticated,
    userHasAuthenticated: this.userHasAuthenticated
  };

Wouldn’t you normally use a Redux Store for sharing the state across containers, rather than depend on props in so many layers?

It is okay to lift your state up this way. You don’t have to rely on Redux for this. Redux can be quite useful but might not be a great choice when you are first starting out. This article can help you decide if you want to use Redux.

I haven’t been able to get the session loading working properly. I have no clue what’s wrong. I have gone to the point where I literally copy and pasted the file from github and it still does not save my session upon refresh.

I confirmed that isAuthenticated is changing to false after the refresh.

Any ideas? the only page that was edited in this chapter is App.js and I literally have that copied off of the github page for this project

The “isAuthenticated” variable is true but nothing is saved to local storage

What is not working for the session loading? It doesn’t log the user out or doesn’t keep them logged in?

It logs the user out upon refresh

Figured it out. I had gone back and manually created a user in the console. This meant that my user was still on status FORCE_CHANGE_PASSWORD. That was the problem :frowning:

2 Likes

I see. Glad you figured it out.

Thanks for clearing this. I ran into the same issue.

This is quite a weird case as the account seems to be in limbo - it can be signed in without errors, but is unusable (at least in this Lessons context).

2 Likes

Hi, I have a question regarding Auth.currentSession(). It always returns a state of “rejected” with the reason being “No userPool”.

I have checked both of my Cognito User Pool and my Identity Pool. The admin@example.com user has an Account Status of “Enabled / CONFIRMED” and the Identity Pool has been properly configured.

I also tried testing Invoking the API Gateway using the IAM Policy Simulator and when I ran the simulation, I got “allowed” as the result so it seems that it should be fine. But when I tried actually testing it out on the browser, I always get the “no userPool” error upon the component mounting.

I was wondering if you guys have encountered this problem before or know of a way to fix it?

Just an update to the situation. I seemed to have found out the reason why it wasn’t working. I did not configure Amplify before rendering App.

I mistakenly added Amplify.configure() below ReactDOM.render() in the index.js file. After moving Amplify.configure() above ReactDOM.render(), the “No userPool” error went away.

2 Likes

Oh good catch. Glad you figured it out.

1 Like

While I understand what the conditional expression is supposed to accomplish here, I am confused about the actual implementation. The docs state isAuthenticating it’s there because “loading the user session is an asynchronous process” but we’re using await before Auth.currentSession() and then setting state.isAuthenticated to true via userHasAuthenticated(true) so shouldn’t the user session be guaranteed to have already loaded by the time isAuthenticating is set to false? I also see that userHasAuthenticated() calls setState() which we can’t be sure will run right away due to batching, but I don’t see anything else that triggers another render() prior to that specific setState() being set…?

Separate but related, the only time state.isAuthenticating = true is right after the App is constructed. Assuming someone explains what I am missing above, shouldn’t we set this back to true at some point when the user logs out in preparation for another async user session call?

Just thought I’d chime in here to say I had the same issue, which I fixed by changing my user’s password.

AWS wouldn’t let me do it via the console, so I ended up working out how to do it via the CLI.

For anyone else who wants to do this, here’s the command to run:

aws cognito-idp admin-set-user-password --user-pool-id [User pool ID] --username [Username] --password [New password] --permanent