npm i aws-amplify --save
Using the AWS Console we'll create a Cognito User Group
We need to hook up our cognito pool to our code in the App.js
import { Amplify } from 'aws-amplify';
Amplify.configure({
"AWS_PROJECT_REGION": process.env.REACT_AWS_PROJECT_REGION,
"aws_cognito_identity_pool_id": process.env.REACT_APP_AWS_COGNITO_IDENTITY_POOL_ID,
"aws_cognito_region": process.env.REACT_APP_AWS_COGNITO_REGION,
"aws_user_pools_id": process.env.REACT_APP_AWS_USER_POOLS_ID,
"aws_user_pools_web_client_id": process.env.REACT_APP_CLIENT_ID,
"oauth": {},
Auth: {
// We are not using an Identity Pool
// identityPoolId: process.env.REACT_APP_IDENTITY_POOL_ID, // REQUIRED - Amazon Cognito Identity Pool ID
region: process.env.REACT_AWS_PROJECT_REGION, // REQUIRED - Amazon Cognito Region
userPoolId: process.env.REACT_APP_AWS_USER_POOLS_ID, // OPTIONAL - Amazon Cognito User Pool ID
userPoolWebClientId: process.env.REACT_APP_AWS_USER_POOLS_WEB_CLIENT_ID, // OPTIONAL - Amazon Cognito Web Client ID (26-char alphanumeric string)
}
});
Inside our HomeFeedPage.js
import { Auth } from 'aws-amplify';
// set a state
const [user, setUser] = React.useState(null);
// check if we are authenicated
const checkAuth = async () => {
Auth.currentAuthenticatedUser({
// Optional, By default is false.
// If set to true, this call will send a
// request to Cognito to get the latest user data
bypassCache: false
})
.then((user) => {
console.log('user',user);
return Auth.currentAuthenticatedUser()
}).then((cognito_user) => {
setUser({
display_name: cognito_user.attributes.name,
handle: cognito_user.attributes.preferred_username
})
})
.catch((err) => console.log(err));
};
// check when the page loads if we are authenicated
React.useEffect(()=>{
loadData();
checkAuth();
}, [])
We'll want to pass user to the following components:
<DesktopNavigation user={user} active={'home'} setPopped={setPopped} />
<DesktopSidebar user={user} />
We'll rewrite DesktopNavigation.js
so that it it conditionally shows links in the left hand column
on whether you are logged in or not.
Notice we are passing the user to ProfileInfo
import './DesktopNavigation.css';
import {ReactComponent as Logo} from './svg/logo.svg';
import DesktopNavigationLink from '../components/DesktopNavigationLink';
import CrudButton from '../components/CrudButton';
import ProfileInfo from '../components/ProfileInfo';
export default function DesktopNavigation(props) {
let button;
let profile;
let notificationsLink;
let messagesLink;
let profileLink;
if (props.user) {
button = <CrudButton setPopped={props.setPopped} />;
profile = <ProfileInfo user={props.user} />;
notificationsLink = <DesktopNavigationLink
url="/notifications"
name="Notifications"
handle="notifications"
active={props.active} />;
messagesLink = <DesktopNavigationLink
url="/messages"
name="Messages"
handle="messages"
active={props.active} />
profileLink = <DesktopNavigationLink
url="/@andrewbrown"
name="Profile"
handle="profile"
active={props.active} />
}
return (
<nav>
<Logo className='logo' />
<DesktopNavigationLink url="/"
name="Home"
handle="home"
active={props.active} />
{notificationsLink}
{messagesLink}
{profileLink}
<DesktopNavigationLink url="/#"
name="More"
handle="more"
active={props.active} />
{button}
{profile}
</nav>
);
}
We'll update ProfileInfo.js
import { Auth } from 'aws-amplify';
const signOut = async () => {
try {
await Auth.signOut({ global: true });
window.location.href = "/"
} catch (error) {
console.log('error signing out: ', error);
}
}
We'll rewrite DesktopSidebar.js
so that it conditionally shows components in case you are logged in or not.
import './DesktopSidebar.css';
import Search from '../components/Search';
import TrendingSection from '../components/TrendingsSection'
import SuggestedUsersSection from '../components/SuggestedUsersSection'
import JoinSection from '../components/JoinSection'
export default function DesktopSidebar(props) {
const trendings = [
{"hashtag": "100DaysOfCloud", "count": 2053 },
{"hashtag": "CloudProject", "count": 8253 },
{"hashtag": "AWS", "count": 9053 },
{"hashtag": "FreeWillyReboot", "count": 7753 }
]
const users = [
{"display_name": "Andrew Brown", "handle": "andrewbrown"}
]
let trending;
if (props.user) {
trending = <TrendingSection trendings={trendings} />
}
let suggested;
if (props.user) {
suggested = <SuggestedUsersSection users={users} />
}
let join;
if (props.user) {
} else {
join = <JoinSection />
}
return (
<section>
<Search />
{trending}
{suggested}
{join}
<footer>
<a href="#">About</a>
<a href="#">Terms of Service</a>
<a href="#">Privacy Policy</a>
</footer>
</section>
);
}
import { Auth } from 'aws-amplify';
const [cognitoErrors, setCognitoErrors] = React.useState('');
const onsubmit = async (event) => {
setCognitoErrors('')
event.preventDefault();
try {
Auth.signIn(username, password)
.then(user => {
localStorage.setItem("access_token", user.signInUserSession.accessToken.jwtToken)
window.location.href = "/"
})
.catch(err => { console.log('Error!', err) });
} catch (error) {
if (error.code == 'UserNotConfirmedException') {
window.location.href = "/confirm"
}
setCognitoErrors(error.message)
}
return false
}
let errors;
if (cognitoErrors){
errors = <div className='errors'>{cognitoErrors}</div>;
}
// just before submit component
{errors}
import { Auth } from 'aws-amplify';
const [cognitoErrors, setCognitoErrors] = React.useState('');
const onsubmit = async (event) => {
event.preventDefault();
setCognitoErrors('')
try {
const { user } = await Auth.signUp({
username: email,
password: password,
attributes: {
name: name,
email: email,
preferred_username: username,
},
autoSignIn: { // optional - enables auto sign in after user is confirmed
enabled: true,
}
});
console.log(user);
window.location.href = `/confirm?email=${email}`
} catch (error) {
console.log(error);
setCognitoErrors(error.message)
}
return false
}
let errors;
if (cognitoErrors){
errors = <div className='errors'>{cognitoErrors}</div>;
}
//before submit component
{errors}
const resend_code = async (event) => {
setCognitoErrors('')
try {
await Auth.resendSignUp(email);
console.log('code resent successfully');
setCodeSent(true)
} catch (err) {
// does not return a code
// does cognito always return english
// for this to be an okay match?
console.log(err)
if (err.message == 'Username cannot be empty'){
setCognitoErrors("You need to provide an email in order to send Resend Activiation Code")
} else if (err.message == "Username/client id combination not found."){
setCognitoErrors("Email is invalid or cannot be found.")
}
}
}
const onsubmit = async (event) => {
event.preventDefault();
setCognitoErrors('')
try {
await Auth.confirmSignUp(email, code);
window.location.href = "/"
} catch (error) {
setCognitoErrors(error.message)
}
return false
}
import { Auth } from 'aws-amplify';
const onsubmit_send_code = async (event) => {
event.preventDefault();
setCognitoErrors('')
Auth.forgotPassword(username)
.then((data) => setFormState('confirm_code') )
.catch((err) => setCognitoErrors(err.message) );
return false
}
const onsubmit_confirm_code = async (event) => {
event.preventDefault();
setCognitoErrors('')
if (password == passwordAgain){
Auth.forgotPasswordSubmit(username, code, password)
.then((data) => setFormState('success'))
.catch((err) => setCognitoErrors(err.message) );
} else {
setCognitoErrors('Passwords do not match')
}
return false
}
## Authenticating Server Side
Add in the `HomeFeedPage.js` a header eto pass along the access token
```js
headers: {
Authorization: `Bearer ${localStorage.getItem("access_token")}`
}
In the app.py
cors = CORS(
app,
resources={r"/api/*": {"origins": origins}},
headers=['Content-Type', 'Authorization'],
expose_headers='Authorization',
methods="OPTIONS,GET,HEAD,POST"
)