how are you?
Im doing a proof of concept using React and Cognito Hosted UI. I have this code here using react router dom:
return ( <div> <main> <Switch> < Route path='/' exact> { (localStorage.getItem('access_token') && localStorage.getItem('access_token')!=='undefined') ? history.replace('/home'): ( <div> <b>You are not logged in Igor, please log in using Google or User and Password. </b> <b></b> <a href="https://<MY_DOMAIN>.auth.us-east-1.amazoncognito.com/login?client_id=<MY_CLIENT_ID>&response_type=code&scope=aws.cognito.signin.user.admin+email+openid+phone+profile&redirect_uri=<MY_CLOUDFRONT_DISTRIBUTION_APEX>">Sign in</a> </div> ) } </Route> <Route path='/calculator'> <Calculator/> </Route> <Route path='/home/'> <Welcome/> </Route> <Route path='/welcome/'> <RedirectPage/> </Route> </Switch> </main> </div> );
Im using S3 as a static website hosting, thats why i point to S3 cloudfront distribution apex. Then, in my App function (residex inside App.js file), i make this validation every times the user access, to verify if this comes from a redirect, and if comes, i exchange the auth_code for a JWT token, that will be used with API Gateway:
const location = useLocation(); const history = useHistory(); let authCode = new URLSearchParams(location.search).get('code'); console.log(authCode) if(authCode){ fetch('https://<GATEWAY_ID>.execute-api.us-east-1.amazonaws.com/dev/auth',{ method: 'POST', body: JSON.stringify(authCode), headers: { 'Content-Type': 'application/json' } }).then((res)=>{return res.json()}).then(data=>{ console.log('access token is:'); console.log(data.result['access_token']); console.log('id token is:'); console.log(data.result['id_token']); localStorage.setItem('access_token',data.result['access_token']); history.replace('/home') }); }
The problem is that after i make the authentication, either using google or login and password, i receive the code, i authenticate on cognito using a lambda on backend (on /dev/auth route, behind the Gateway), the lambda performs the authentication well, but my frontend page enters in a loop, and after print null a bunch of times (from the line console.log(authCode), i receive an error, telling that im in a loop). Im very newbie in react, im doing this POC to understand the concept and to show this proccess to a client.
Thanks in advance! I can’t share the code as entire because that are stored in private company repository.
My complete code:
import React from 'react'; import { Route, Switch } from 'react-router-dom'; import Calculator from './pages/Calculator'; import Welcome from './pages/Welcome'; import {useHistory, useLocation} from 'react-router-dom'; import RedirectPage from './pages/Loading'; function App() { const location = useLocation(); const history = useHistory(); let authCode = new URLSearchParams(location.search).get('code'); console.log(authCode) if(authCode){ fetch('https://<GATEWAY_ID>.execute-api.us-east-1.amazonaws.com/dev/auth',{ method: 'POST', body: JSON.stringify(authCode), headers: { 'Content-Type': 'application/json' } }).then((res)=>{return res.json()}).then(data=>{ console.log('access token is:'); console.log(data.result['access_token']); console.log('id token is:'); console.log(data.result['id_token']); localStorage.setItem('access_token',data.result['access_token']); history.replace('/home') }); } return ( <div> <main> <Switch> < Route path='/' exact> { (localStorage.getItem('access_token') && localStorage.getItem('access_token')!=='undefined') ? history.replace('/home'): ( <div> <b>You are not logged in Igor, please log in using Google or User and Password. </b> <b></b> <a href="<HOSTED_UI_COGNITO>">Sign in</a> </div> ) } </Route> <Route path='/calculator'> <Calculator/> </Route> <Route path='/home/'> <Welcome/> </Route> <Route path='/welcome/'> <RedirectPage/> </Route> </Switch> </main> </div> ); } export default App;
UPDATE 1: I think that the error is here:
localStorage.getItem('access_token') && localStorage.getItem('access_token')!=='undefined') ? history.replace('/home')
when the Lambda API returns an error, the workflow goes well, but the localStorage isn’t filled with the JWT token.
I need to wait the response from the lambda function, insert JWT in localStorage, and then moves the user to /home url.
UPDATE 2: After some hours of debugging, and a lot of help, i finaly discover the problem. The problem was related to this line:
return ( <div> <main> <Switch> < Route path='/' exact> { (localStorage.getItem('access_token') && localStorage.getItem('access_token')!=='undefined') ? history.replace('/home')
Cause we already have a useEffect statement that looks for the code and perform some actions, using this same code we enter in a loop statement. I just delete that and it works! thanks.
Advertisement
Answer
I can see that you have written you api call code inside a functional component and i am assuming you want hit the api only once to achieve that you can write ur code inside useEffect
useEffect(()=>{ if(authCode){ fetch('https://<GATEWAY_ID>.execute-api.us-east-1.amazonaws.com/dev/auth',{ method: 'POST', body: JSON.stringify(authCode), headers: { 'Content-Type': 'application/json' } }).then((res)=>{return res.json()}).then(data=>{ console.log('access token is:'); console.log(data.result['access_token']); console.log('id token is:'); console.log(data.result['id_token']); localStorage.setItem('access_token',data.result['access_token']); history.replace('/home') }); } },[authCode])