How can I store my JWT token in userInfo? - javascript

I try a lot of things but I can´t go on .. I stucked ...
If I login in to my account it works I get also my userInfo but only userID and my password.. but I would have my token also ..
I wrote an if state where I catch my token but I want to set it also in the localStorage and I don´t know how to do it..
export const login = (userID, password) => async (dispatch) => {
try {
dispatch({ type: USER_LOGIN_REQUEST });
const url = "http://localhost:8080/authenticate/";
const config = {
auth: {
username: userID,
password,
},
};
const data = {};
const response = await axios.post(
url,
data,
config,
)
dispatch({ type: USER_LOGIN_SUCCESS, payload: config});
//localStorage.setItem("userInfo", JSON.stringify(config) );
if (response.status === 200) {
// Login succeeded
const token = response.data.token;
console.log("TOKEN\n" + token);
localStorage.setItem("userInfo", JSON.stringify(config) );
}
} catch (error) {
//alert("Sorry, login failed");
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.ErrorMessage
? error.response.data.ErrorMessage
: error.message,
});
}
};

try this
export const login = (userID, password) => async (dispatch) => {
try {
dispatch({ type: USER_LOGIN_REQUEST });
const url = "http://localhost:8080/authenticate/";
const config = {
auth: {
username: userID,
password, //this should not be saved in your local storage delete this from here
},
};
const data = {};
const response = await axios.post(
url,
data,
config,
)
dispatch({ type: USER_LOGIN_SUCCESS, payload: config});
if (response.status === 200) {
// Login succeeded
config.token = response.data.token;
}
localStorage.setItem("userInfo", JSON.stringify(config) );
} catch (error) {
//alert("Sorry, login failed");
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.ErrorMessage
? error.response.data.ErrorMessage
: error.message,
});
}
};

Related

I'm getting API Error when I try to login after added next.js to my react app

I migrated and added Next.js to my React app. I getting the following error when I try to login. When I checked seems that I have to use promise.all. I tried different solutions without success. I want to know how it works. Your help and advice are highly appreciated.
error message;
Unhandled Runtime Error
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
src/action/auth.js;
import axios from 'axios';
import { setAlert } from './alert';
// import { API_URL } from '../config/index';
import {
LOGIN_SUCCESS,
LOGIN_FAIL,
SIGNUP_SUCCESS,
SIGNUP_FAIL,
ACTIVATION_SUCCESS,
ACTIVATION_FAIL,
USER_LOADED_SUCCESS,
USER_LOADED_FAIL,
AUTHENTICATED_SUCCESS,
AUTHENTICATED_FAIL,
PASSWORD_RESET_SUCCESS,
PASSWORD_RESET_FAIL,
PASSWORD_RESET_CONFIRM_SUCCESS,
PASSWORD_RESET_CONFIRM_FAIL,
LOGOUT
} from './types';
export const checkAuthenticated = () => async dispatch => {
if (typeof window !== 'undefined' ? window.localStorage.getItem('access') : false) {
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
};
const body = JSON.stringify({ token: typeof window !== 'undefined' ? window.localStorage.getItem('access') : false });
try {
const res = await axios.post(`${process.env.NEXT_PUBLIC_API_URL}/auth/jwt/verify/`, body, config)
if (res.data.code !== 'token_not_valid') {
dispatch({
type: AUTHENTICATED_SUCCESS
});
} else {
dispatch({
type: AUTHENTICATED_FAIL
});
}
} catch (err) {
dispatch({
type: AUTHENTICATED_FAIL
});
}
} else {
dispatch({
type: AUTHENTICATED_FAIL
});
}
};
export const load_user = () => async dispatch => {
if (typeof window !== 'undefined' ? window.localStorage.getItem('access') : false) {
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `JWT ${typeof window !== 'undefined' ? window.localStorage.getItem('access') : false}`,
'Accept': 'application/json'
}
};
try {
const res = await axios.get(`${process.env.NEXT_PUBLIC_API_URL}/auth/users/me/`, config);
dispatch({
type: USER_LOADED_SUCCESS,
payload: res.data
});
}catch (err) {
dispatch({
type: USER_LOADED_FAIL
});
}
} else {
dispatch({
type: USER_LOADED_FAIL
});
}
};
export const login = (email, password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email, password });
try {
const res = await axios.post(`${process.env.NEXT_PUBLIC_API_URL}/auth/jwt/create/`, body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
});
dispatch(setAlert('Authenticated successfully', 'success'));
dispatch(load_user());
}catch (err) {
dispatch({
type: LOGIN_FAIL
});
dispatch(setAlert('Error Authenticating', 'error'));
}
};
export const signup = (name, email, password, re_password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ name, email, password, re_password });
try {
const res = await axios.post(`${process.env.NEXT_PUBLIC_API_URL}/auth/users/`, body, config);
dispatch({
type: SIGNUP_SUCCESS,
payload: res.data
});
dispatch(setAlert('Check Your Email to Activate Your Account.', 'warning'));
} catch (err) {
dispatch({
type: SIGNUP_FAIL
})
}
};
export const verify = (uid, token) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ uid, token });
try {
await axios.post(`${process.env.NEXT_PUBLIC_API_URL}/auth/users/activation/`, body, config);
dispatch({
type: ACTIVATION_SUCCESS,
});
dispatch(setAlert('Account Activated Successfully.', 'success'));
} catch (err) {
dispatch({
type: ACTIVATION_FAIL
})
}
};
//Reset Password
export const reset_password = (email) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ email });
try {
await axios.post (`${process.env.NEXT_PUBLIC_API_URL}/auth/users/reset_password/`, body, config);
dispatch({
type: PASSWORD_RESET_SUCCESS
});
dispatch(setAlert('Check Your Email to Rest Password.', 'warning'));
} catch (err) {
dispatch({
type: PASSWORD_RESET_FAIL
});
}
};
// Reset Password Confirm
export const reset_password_confirm = (uid, token, new_password, re_new_password) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({ uid, token, new_password, re_new_password });
try {
await axios.post (`${process.env.NEXT_PUBLIC_API_URL}/auth/users/reset_password_confirm/`, body, config);
dispatch(setAlert('Password Rest Successful.', 'success'));
dispatch({
type: PASSWORD_RESET_CONFIRM_SUCCESS
});
} catch (err) {
dispatch({
type: PASSWORD_RESET_CONFIRM_FAIL
});
}
};
//Logout
export const logout = () => dispatch => {
dispatch(setAlert('Logout successful.', 'success'));
dispatch({
type: LOGOUT
});
};
src/pages/login.js;
import React, { useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { connect } from 'react-redux';
import { Button } from '#mui/material';
import { login } from '../actions/auth';
import styles from '../styles/Login.module.css';
import Head from 'next/head';
import WelcomePageFooter from '../components/WelcomePageFooter';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { useTranslation } from 'next-i18next';
import i18n from '../../i18n';
function Login({ login, isAuthenticated }) {
const { t } = useTranslation();
const navigate = useRouter();
const [formData, setFormData] = useState({
email: '',
password: ''
});
const { email, password } = formData;
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value});
const onSubmit = e => {
e.preventDefault();
login (email, password)
};
if (isAuthenticated) {
return (
navigate.replace('/')
);
}
return (
<main>
<div className={styles.login}>
<Head>
<title>Diploman - Login</title>
<meta
name='description'
content='login page'
/>
</Head>
<h1 className={styles.login__title}>{t('login_title')}</h1>
<p className={styles.login__lead}>{t('login_lead')}</p>
<form className={styles.login__form} onSubmit={e => onSubmit(e)}>
<div className={styles.login__form__group}>
<input
className={styles.login__form__input}
type='email'
placeholder={t('Form_email')}
name='email'
value={email}
onChange={e => onChange(e)}
required
/>
</div>
<div className={styles.login__form__group}>
<input
className={styles.login__form__input}
type='password'
placeholder={t('Form_pw')}
name='password'
value={password}
onChange={e => onChange(e)}
minLength='8'
required
/>
</div>
<Button className={styles.login__button__main} type='submit'>{t('login_title')}</Button>
</form>
<p className={styles.link__to__Signup}>
{t('login_text1')} <Link href='/signup' className={styles.login__link}>{t('login_register')}</Link>
</p>
<p className={styles.link__to__resetPassword}>
{t('login_text2')} <Link href='/reset-password' className={styles.reset__password__link}>{t('login_reset')}</Link>
</p>
</div>
<WelcomePageFooter/>
</main>
)
};
export const getServerSideProps = async ({ locale }) => (
{ props: {
...(await serverSideTranslations(
locale,
['common'],
i18n,
)),
} }
);
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect (mapStateToProps, { login }) (Login);
I really appreciate your help here

React Native - Variable does not update correctly when retrieving data from AsyncStorage

I'm trying to store and get data that I fetch from an API. The user is supposed to get a token on the login screen, and the token will be shown in an Alert dialog on home screen when the user press a button. But the token is not shown in the Alert dialog. the token is shown after I reload(not refresh the app. I used Live Server extension) the screen three times.
Login.js
const _userLogin = () => {
fetch(URLs._login, {
method: "POST",
headers, body,
})
}).then((response) => response.json())
.then((result) => {
if(result.message !== "Unauthorized / Access Token Expired" && result.message !== "The given data was invalid."){
storeData(result.access_token, result.token_type);
navigation.navigate('HomeScreen');
} else {
Alert.alert("Error", result.message);
}
});
};
const storeData = async (accessToken, tokenType) => {
try {
await AsyncStorage.setItem('#access_token', accessToken);
await AsyncStorage.setItem('#token_type', tokenType);
await AsyncStorage.setItem('#user_auth', tokenType + " " + accessToken);
} catch (e) {
console.log(e);
}
}
Home.js [UPDATE]
const [inputs, setInputs] = React.useState({
userToken: '',
userPointsBalance: '',
expiringOn: '',
});
useEffect (() => {
_dashboard();
})
const getToken = async () => {
inputs.userToken = await AsyncStorage.getItem('#user_auth');
}
const _dashboard = () => {
getToken();
fetch(URLs._dashboard, {
method: "GET",
headers: {
'Authorization': inputs.userToken,
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then(async (result) => {
storeData(result.code, result.name, result.member_name, result.user_points_balance, result.expiring_on, result.status, result.token_id);
getData();
});
};
const storeData = async (code, name, memberName, userPointsBalance, expiringOn, status, tokenId) => {
try {
await AsyncStorage.setItem('#user_points_balance', userPointsBalance.toString());
await AsyncStorage.setItem('#expiring_on', expiringOn.toString());
} catch (e) {
console.log(e);
}
}
const getData = async () => {
const userPointsBalance = await AsyncStorage.getItem('#user_points_balance');
const expiringOn = await AsyncStorage.getItem('#expiring_on');
setInputs({userPointsBalance: userPointsBalance, expiringOn: expiringOn});
}
return (
<Text>{inputs.expiringOn}<Text>
)
i hope it works
.then(async(result) => {
if(result.message !== "Unauthorized / Access Token Expired" && result.message !== "The given data was invalid."){
await storeData(result.access_token, result.token_type)
.then(res=>
navigation.navigate('HomeScreen')
)
} else {
Alert.alert("Error", result.message);
}
});

How to use async await in React using the axios in the API call

I am new to the web development. I am using react.js.So, Here I want to use the async/awaitfor the API call. I am using axios.
Now,
what I have is like
export function fetchToken(bodyjson) {
return (dispatch) => {
let url = LOGIN_PATH + "username=" + bodyjson.userName + "&password" + "=" + bodyjson.password;
return post(url, bodyjson)
.then((response) => {
if (response.status === 200) {
localStorage.setItem('user', bodyjson.userName);
localStorage.setItem('access_token', response.payload.access_token);
history.push('/');
dispatch({
type: LOGIN_SUCCESS,
data: response.payload,
})
}
else {
dispatch({
type: LOGIN_FAILED,
data: response.status,
});
}
})
}
}
and my post service is like,
export const post = (url, post_data) =>
axios.post(
apiGatewayEndpoint.apiGatewayEndpoint + url,
post_data,
{
headers: {
"Authorization": localStorage.getItem("access_token") !== null ? `Bearer ` + localStorage.getItem("access_token") : null,
"Content-Type": "application/json"
}
}
).then(data => {
if (data.status === HttpStatus.OK) {
return {
status: data.status,
payload: data.data
};
}
}).catch(err => {
return {
status: err.response.data,
payload: null
};
});
Now, I want to use the async await over here. I am very confused between this. I have gone through lots of the tutorials.
I want to call an API immediately after the login. on that basis I want to redirect user to the diff pages.
So, can any one help me with this async-await
THANKS:-)
Now I am using it like,
export function fetchToken(bodyjson) {
return async (dispatch) => {
let url = LOGIN_PATH + "username=" + bodyjson.userName + "&password" + "=" + bodyjson.password;
let response = await post(url, bodyjson)
if (response.status === 200) {
localStorage.setItem('user', bodyjson.userName);
localStorage.setItem('access_token', response.payload.access_token);
let fetchJd = FETCH_JD_ROOT_URL + page + "&" + size;
let newApiResponse = await get(fetchJd)
if (newApiResponse.status === 200) {
dispatch({
type: LOGIN_SUCCESS,
data: response.payload,
})
dispatch(sendUserJd(newApiResponse.payload));
}else {
dispatch({
type: LOGIN_FAILED,
data: response.status,
});
}
}
else {
dispatch({
type: LOGIN_FAILED,
data: response.status,
});
}
}
for get requests, you can use params to send data etc etc.
export const getData = async () => {
try {
const { data } = await axios({
method: 'get', //you can set what request you want to be
url: `yoururl`,
params: {
// key values pairs
}
headers: {
'token': token
}
});
// run some validation before returning
return data;
} catch (e) {
console.log(e);
return .. some error object;
}
};
for post request
export const getData = async (params) => {
try {
const { data } = await axios({
method: 'post', //you can set what request you want to be
url: `url`,
data: params,
headers: {
'x-auth-Token': token
}
});
// run some validation before returning
return data;
} catch (e) {
console.log(e);
return .. some error object;
}
};
error object example
{
status: 'error',
message: 'failed with something'
}
then you can call any api like this,
async componentDidMount() {
const data = await getData();
if(data.status === 'Something') {
// do something
}
}
You dont exactly need async await for this purpose.
With then chain approach
export function fetchToken(bodyjson) {
return (dispatch) => {
let url = LOGIN_PATH + "username=" + bodyjson.userName + "&password" + "=" + bodyjson.password;
return post(url, bodyjson)
.then((response) => {
if (response.status === 200) {
localStorage.setItem('user', bodyjson.userName);
localStorage.setItem('access_token', response.payload.access_token);
history.push('/');
dispatch({
type: LOGIN_SUCCESS,
data: response.payload,
})
//next api call
return post(newUrl, newBodyjson)
}
else {
dispatch({
type: LOGIN_FAILED,
data: response.status,
});
}
})
.then((newApiResponse) => {
//Do stuffs with new api response
})
}
}
But if you want to use async-await approach only
export function fetchToken(bodyjson) {
return async (dispatch) => {
let url = LOGIN_PATH + "username=" + bodyjson.userName + "&password" + "=" + bodyjson.password;
let response = await post(url, bodyjson)
if (response.status === 200) {
localStorage.setItem('user', bodyjson.userName);
localStorage.setItem('access_token', response.payload.access_token);
history.push('/');
dispatch({
type: LOGIN_SUCCESS,
data: response.payload,
})
let newApiResponse = await post(newUrl, newBodyjson)
//Do stuffs with new api response
}
else {
dispatch({
type: LOGIN_FAILED,
data: response.status,
});
}
}
}

“SyntaxError: Unexpected end of JSON input”

Trying to fetch data from API using async/await, but facing the above error after session expiration, how to handle that error and show user session expired or any other helpful error?
export const walletAddCardRequest = async (dispatch, token, payload, url) => {
try {
persist.store.dispatch(setLoader(true));
const headers = {Authorization: token}
const response = await api(url, "POST", payload, headers);
console.log("wallet add card ", response);
persist.store.dispatch(setLoader(false));
if (response.status === 200) {
const user = await response.json();
if (user) {
persist.store.dispatch(setLoader(false));
Alert.alert(
"",
"Your card added successfully."
);
navigateTo("wallet");
} else {
throw new Error("Error. Please try again");
}
} else {}
} catch (e) {
persist.store.dispatch(setLoader(false));
Alert.alert(e.message);
console.log("console:",e);
dispatch({
type: AUTH_ERROR
});
}
}

ReactJS: How to implement react-cookie properly in an action?

I have read articles that saving the token in localstorage is dangerous to XSS attack. So I have decided to store my tokens in cookies. And I am using react-cookie. I saw the examples and I am trying to do it but my auth.js consists of const and is not a class, so I do not know how to use the withCookies() with it, this is my auth.js where I want to store the token to the cookies:
import {
LOGIN,
LOGIN_SUCCESS,
LOGIN_FAILED,
GET_USER_DATA,
GET_USER_DATA_SUCCESS,
GET_USER_DATA_FAILED,
LOGOUT,
LOGOUT_SUCCESS,
LOGOUT_FAILED,
} from './types'
import axios from 'axios'
var api = require ('./../api.js');
export const login = (email, pass) => {
return (dispatch) => {
dispatch({
type: LOGIN
})
var url = api.logInApi
axios.post(url, {
email: email,
password: pass
})
.then(res => {
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
localStorage.setItem('token', res.data.token)
dispatch(getUserData())
})
.catch(err => dispatch({
type: LOGIN_FAILED,
payload: err
}))
}
}
export const getUserData = () => {
return (dispatch) => {
dispatch({
type: GET_USER_DATA
})
var url = api.getUserDataApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${localStorage.getItem("token")}`
}})
.then(res => {
dispatch({
type: GET_USER_DATA_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: GET_USER_DATA_FAILED,
payload: err
}))
}
}
export const logout = () => {
return (dispatch) => {
dispatch({
type: LOGOUT
})
var url = api.logoutApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${localStorage.getItem("token")}`
}})
.then(res => {
window.location.replace("")
dispatch({
type: LOGOUT_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: LOGOUT_FAILED,
payload: err
}))
}
}
Now, I tried doing this and of course it doesn't work:
import {
LOGIN,
LOGIN_SUCCESS,
LOGIN_FAILED,
GET_USER_DATA,
GET_USER_DATA_SUCCESS,
GET_USER_DATA_FAILED,
LOGOUT,
LOGOUT_SUCCESS,
LOGOUT_FAILED,
} from './types'
import axios from 'axios'
import { withCookies, Cookies } from 'react-cookie'; <<added this
var api = require ('./../api.js');
const login = (email, pass) => {
return (dispatch) => {
dispatch({
type: LOGIN
})
const { cookies } = props; <<added this
var url = api.logInApi
axios.post(url, {
email: email,
password: pass
})
.then(res => {
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
cookies.set('token', res.data.token, { path: '/' }); <<added this
dispatch(getUserData())
})
.catch(err => dispatch({
type: LOGIN_FAILED,
payload: err
}))
}
}
export default withCookies(login) <<added this(wrong)
const getUserData = () => {
return (dispatch) => {
dispatch({
type: GET_USER_DATA
})
const { cookies } = props; <<added this
var token = cookies.get('token'); <<added this
var url = api.getUserDataApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${token}` <<added this(this is where I wanna get the cookie)
}})
.then(res => {
dispatch({
type: GET_USER_DATA_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: GET_USER_DATA_FAILED,
payload: err
}))
}
}
export default withCookies(getUserData) <<added this(wrong)
const logout = () => {
return (dispatch) => {
dispatch({
type: LOGOUT
})
const { cookies } = props;
var token = cookies.get('token');
var url = api.logoutApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${token}` <<added this
}})
.then(res => {
window.location.replace("")
dispatch({
type: LOGOUT_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: LOGOUT_FAILED,
payload: err
}))
}
}
export default withCookies(logout) <<added this(wrong)
this one is wrong because there should only be one export default. But I don't know how to implement withCookies to const and there are also these ones that are included in the example and I don't know if I need them or where do I put them:
static propTypes = {
cookies: instanceOf(Cookies).isRequired
};
constructor(props) {
super(props);
const { cookies } = props;
this.state = {
name: cookies.get('name') || 'Ben'
};
}
and also, another question is that, I can access my cookies anywhere in my project right? just like how localstorage is accessible to my project?
I hope someone can help me and I am a newbie to this. I have never used cookies before so thank you for your consideration.
I personally would rather using js-cookie to write/read cookies.
It has a very basic API:
Cookie.set('cookie_name', 'value') // will set "cookie_name" to "value"
Cookie.get('cookie_name') // will return "value"
Which means:
const login = (email, pass, cookie) => {
return (dispatch) => {
dispatch({
type: LOGIN
})
var url = api.logInApi
axios.post(url, {
email: email,
password: pass
})
.then(res => {
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
cookies.set('token', res.data.token);
dispatch(getUserData())
})
.catch(err => dispatch({
type: LOGIN_FAILED,
payload: err
}))
}
}
Passing to the login funuction js-cookie's Cookie in the 3rd argument.
Now, you can still use the same react-cookie package to read the cookie values (I believe there shouldn't be any conflicts). Or you can replace it with js-cookie. To do that, however, you will have to pass the Cookie object to props. I probably would do that using mapStateToProps if you're using Redux or just by simply passing it through JSX

Categories