Load the State from the Session
To make our login information persist we need to store and load it from the browser session. There are a few different ways we can do this, using Cookies or Local Storage. Thankfully the AWS Cognito JS SDK does that for us automatically and we just need to read from it and load it into our application state.
Get Current User and Token
We are going to do this step a couple of times, so let’s create a helper function for it.
Add the following to src/libs/awsLib.js
. Make sure to create the src/libs/
directory first.
import { CognitoUserPool } from "amazon-cognito-identity-js";
import config from "../config";
export async function authUser() {
const currentUser = getCurrentUser();
if (currentUser === null) {
return false;
}
await getUserToken(currentUser);
return true;
}
function getUserToken(currentUser) {
return new Promise((resolve, reject) => {
currentUser.getSession(function(err, session) {
if (err) {
reject(err);
return;
}
resolve(session.getIdToken().getJwtToken());
});
});
}
function getCurrentUser() {
const userPool = new CognitoUserPool({
UserPoolId: config.cognito.USER_POOL_ID,
ClientId: config.cognito.APP_CLIENT_ID
});
return userPool.getCurrentUser();
}
The authUser
method is getting the current user from the Local Storage using the Cognito JS SDK. We then get that user’s session and their user token in getUserToken
. The currentUser.getSession
also refreshes the user session in case it has expired. Finally in the authUser
method we return true
if we are able to authenticate the user and false
if the user is not logged in.
Load User Session in to the State
Now that we can ensure the session user is authenticated using the authUser
method, let’s load this when our app loads. We are going to do this in componentDidMount
. And since authUser
is going to be called async; we need to ensure that the rest of our app is only ready to go after this has been loaded.
To do this, let’s add a flag to our src/App.js
state called isAuthenticating
. The initial state in our constructor
should look like the following.
this.state = {
isAuthenticated: false,
isAuthenticating: true
};
Let’s include the authUser
method that we created by adding it to the header of src/App.js
.
import { authUser } from "./libs/awsLib";
Now to load the user session we’ll add the following to our src/App.js
.
async componentDidMount() {
try {
if (await authUser()) {
this.userHasAuthenticated(true);
}
}
catch(e) {
alert(e);
}
this.setState({ isAuthenticating: false });
}
All this does is check if there is a valid user in the session. It then updates the isAuthenticating
flag once the process is complete.
Render When the State Is Ready
Since loading the user session is an asynchronous process, we want to ensure that our app does not change states when it first loads. To do this we’ll hold off rendering our app till isAuthenticating
is false
.
We’ll conditionally render our app based on the isAuthenticating
flag.
Our render
method in src/App.js
should be as follows.
render() {
const childProps = {
isAuthenticated: this.state.isAuthenticated,
userHasAuthenticated: this.userHasAuthenticated
};
return (
!this.state.isAuthenticating &&
<div className="App container">
<Navbar fluid collapseOnSelect>
<Navbar.Header>
<Navbar.Brand>
<Link to="/">Scratch</Link>
</Navbar.Brand>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav pullRight>
{this.state.isAuthenticated
? <NavItem onClick={this.handleLogout}>Logout</NavItem>
: [
<RouteNavItem key={1} href="/signup">
Signup
</RouteNavItem>,
<RouteNavItem key={2} href="/login">
Login
</RouteNavItem>
]}
</Nav>
</Navbar.Collapse>
</Navbar>
<Routes childProps={childProps} />
</div>
);
}
Now if you head over to your browser and refresh the page, you should see that a user is logged in.
Unfortunately, when we hit Logout and refresh the page; we are still logged in. To fix this we are going to clear the session on logout next.
If you liked this post, please subscribe to our newsletter, give us a star on GitHub, and check out our sponsors.
For help and discussion
Comments on this chapterFor reference, here is the code so far
Frontend Source :load-the-state-from-the-session