How to authenticate user using Django-rest and React js - reactjs

I am trying to authenticate user with django rest and simple react js without redux
User is successfully authenticated at django rest endpoint (email,password) but when I try to authenticate from react it doesn't show any results and I am unable to find it.From react end I take user input via form and save in state and send the states to endpoint using POST method.But at django end nothing happens.Here's below my logic:
class login extends React.Component{
constructor(props){
super(props);
this.state={
email:"",
password:"",
}
}
submitForm=(evt)=>{
evt.preventDefault();
const form= {
email: this.state.email,
password: this.state.password
};
this.loginUser(form)
};
loginUser=(payload)=>{
console.log("In fetch request");
console.log(payload);
fetch(`http://127.0.0.1:8000/chauffeur/login_user/`,
{
method:'POST',
body: JSON.stringify(payload),
headers:{
'Content-Type':'application/json'
}
}).then(response =>{
if (response.status===200){
return response.json().then(data=>{
return {status:"ok",data}
})
}
else
{
console.log("Unable to access")
}
}).catch(error => console.error('Error:', error))
setInputValue = (e, inputName) => {
this.setState({[inputName]: e.target.value})
};
render(){
return(
<div>
<form onSubmit={this.submitForm}>
<input type='email' placeholder="email" value={this.state.email} onChange={(e) => this.setInputValue(e, 'email')}/>
<input type='password' placeholder="password" value={this.state.password} onChange={(e) => this.setInputValue(e, 'password')}/>
<button type="submit">SignIn</button>
</form>
</div>
)
}
I tried to see json response after request but nothing comes on console.Kindly give some suggestions how to fix this.

Related

400 bad request during axios call

Not sure why but the POST request is coming back 400. Postman says my django backend is doing fine. It all happens at the post_flashcards method any help would be great and I am willing to show any other code as requested. although there shouldnt be the need to since this component acts mostly on its own.
class CreateFlashCard extends Component {
constructor(props) {
super(props);
this.state = {
title: '',
collection_id: '',
term: '',
definition: '',
}
this.handleSubmit = this.handleSubmit.bind(this)
}
onChange = (e) => {
this.setState({[e.target.name]: e.target.value});
}
handleSubmit(e) {
e.preventDefault();
this.post_flashcard()
}
async post_flashcard() {
const card = this.state;
const col_id = parseInt(this.state.collection_id)
try{
await axios.post(`http://127.0.0.1:8000/flashcardsapp/${col_id}`, card)
.then(response => console.log(response.status))
}catch(er){
console.log('ERROR in post_flashcard', er)
}
}
render() {
const {title, collection_id, term, definition} = this.state
return (
<form onSubmit={this.handleSubmit}>
<h2>Create a Card</h2>
<label for="title">Enter Collection Title</label>
<input type="text" name="title" value={title} onChange={this.onChange} ></input>
<label for="collection_id">Enter Collection ID</label>
<input type="number" name="collection_id" value={collection_id} onChange={this.onChange} ></input>
<label for="term">Enter Term</label>
<input type="text" name="term" value={term} onChange={this.onChange} ></input>
<label for="definition">Enter Definition</label>
<input type="text" name="definition" value={definition} onChange={this.onChange} ></input>
<input type="submit"></input>
</form>
);
}
}
export default CreateFlashCard;
If you are doing post processing, you can convert the Data to Json format and send it.
var post_data = {
your_post_name: this.state
};
axios
.post(url, JSON.stringify(post_data))
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
or
axios
.post(url,JSON.stringify({your_post_name:this.state}))
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
I solved the issue state had typo in title needed to be collection_title.

React JS: problem in receiving cookie with axios, which is received from JWT Django

First of all, I had made a POST APIView function using Django and added JWT token in it. This api is basically made for the login purpose. I can transfer all the details in it and recieve a cookie in return.
class LoginView(APIView):
def post(self, request):
email = request.data['email']
password = request.data['password']
user = User.objects.filter(email=email).first()
if user is None:
raise AuthenticationFailed('user not found')
if not user.check_password(password):
raise AuthenticationFailed('Incorrect password')
payload = {
'id': user.id,
'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=60),
'iat': datetime.datetime.utcnow()
}
token = jwt.encode(payload, 'secret', algorithm='HS256').decode('utf-8')
response = Response()
response.set_cookie(key='jwt', value=token, httponly=True)
response.data = {
'jwt': token
}
return response
I used POST request using axios in react js and trying to recieve cookie too with the help of "withCredentials: true" yet unable to get the cookie.
import React, { Component } from 'react';
import axios from 'axios';
class Login extends Component {
state = {
email: '',
password: '',
};
handleSubmit(event){
event.preventDefault();
axios({
method: 'post',
url: 'http://127.0.0.1:8000/user/login ',
withCredentials: true,
data: {
email: this.state.email,
password: this.state.password
}
})
.then(data => console.log(data));
}
handleChange(event){
const target = event.target;
const value = target.value;
const name = target.name;
this.setState({[name]:value})
}
render() {
return (
<div>
<h1>LOGIN</h1>
<form onSubmit={this.handleSubmit.bind(this)}>
<div>
<label>Email: </label>
<br />
<input
type="text"
name="email"
onChange={this.handleChange.bind(this)}
value={this.state.email}
/>
</div>
<br />
<div>
<label>Password: </label>
<br />
<input
type="password"
name="password"
onChange={this.handleChange.bind(this)}
value={this.state.password}
/>
</div>
<br />
<button type="submit">Submit</button>
</form>
</div>
);
}
}
export default Login;
I am getting this issue in the console.
Rather than using axios. I had used fetch() which worked for me.
event.preventDefault();
const response = await fetch('http://localhost:8000/user/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
credentials: 'include',
body: JSON.stringify({
email: this.state.email,
password: this.state.password
})
});
console.log(response)
}```

Redirect React Router Route From onClick in Modal

Below is code for the body of a sign up modal. How I would like it to work would be the user enters credentials and when they click submit they are automatically taken to the route "/secret" which is their dashboard.
Currently, when the user clicks submit an error is thrown and the alert "('Error logging in please try again')" appears. I only want this to happen if there is an error with their input (i.e. nonunique entry, not hitting requirements ect.)
This alert is thrown every time the user clicks submit regardless if the input hits requirements and is pushed to the database. Also for some reason react seems to over look the line of code to redirect the user to the desired route.
if (res.status === 200)
{ this.props.history.push('/secret');
}
Is there a way to redirect the route if I receive a res.status === 200 while also keeping the condition to throw the error if it occurs?
signup.js (modal body)
import React, { Component } from 'react';
import API from "../utils/API.js";
import { Container, Row, Col, Button, Alert, Modal, ModalHeader, ModalBody, ModalFooter, Label, Input } from 'reactstrap';
export default class Signup extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
username: ''
};
}
handleInputChange = (event) => {
const { value, name } = event.target;
this.setState({
[name]: value
});
}
onSubmit = (event) => {
event.preventDefault();
API.signUpUser(this.state.email, this.state.username, this.state.password)
.then(res => {
if (res.status === 200) {
this.props.history.push('/secret');
} else {
const error = new Error(res.error);
throw error;
}
})
.catch(err => {
console.error(err);
alert('Error logging in please try again');
});
}
render() {
console.log(this.state)
return (
<form onSubmit={this.onSubmit}>
Email: <input
type="email"
name="email"
placeholder="Enter email"
value={this.state.email}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
Username: <input
type="text"
name="username"
placeholder="Enter username"
value={this.state.username}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
Password: <input
type="password"
name="password"
placeholder="Enter password"
value={this.state.password}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
<Button type="submit" value="Submit" color="primary" className="btn btn-warning">Sign Up</Button>
</form>
);
}
}
app.js (react routes)
<Switch>
<Route path="/" exact component={Home} />
<Route path="/hometwo" exact component={Home2} />
<Route path="/secret" component={withAuth(Secret)} />
<Route path="/login" component={Login} />
<Route path="/signup" component={Signup} />
<Route path="/signout" component={Signout} />
<Route path="/loggedIn" component={withAuth(loggedIn)} />
</Switch>
Signup User API
signUpUser: function (email, username, password) {
const signUpURL = "/api/user"
// console.log("username " + username + "password " + password)
return axios.post(signUpURL, { email,username, password }).then(result => result.data);
// return axios.post(signUpURL, { email, username, password }).then(result => result.data);
// .then(result => result.data);
},
NEW Signup.js
import React, { Component } from 'react';
import API from "../utils/API.js";
import { Container, Row, Col, Button, Alert, Modal, ModalHeader, ModalBody, ModalFooter, Label, Input } from 'reactstrap';
export default class Signup extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
username: '',
};
}
handleInputChange = (event) => {
const { value, name } = event.target;
this.setState({
[name]: value
});
}
onSubmit = (event) => {
event.preventDefault();
// API.signUpUser(this.state.email, this.state.username, this.state.password)
fetch('/api/authenticatesignup', {
method: 'POST',
body: JSON.stringify(this.state),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => {
console.log("THIS IS res " + JSON.stringify(res.status));
if (res.status === 200) {
// alert("You can now go to your dashboard")
// window.location.reload();
// // alert("You can now go to your dashboard")
this.props.history.push('/secret')
} else {
const error = new Error(res.error);
// console.log("This is error on client side " + error)
throw error;
// alert('Error logging in please try again');
}
})
.catch(err => {
console.error(err);
alert('Error logging in please try again');
});
}
render() {
console.log(this.state)
return (
<form onSubmit={this.onSubmit}>
Email: <input
type="email"
name="email"
placeholder="Enter email"
value={this.state.email}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
Username: <input
type="text"
name="username"
placeholder="Enter username"
value={this.state.username}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
Password: <input
type="password"
name="password"
placeholder="Enter password"
value={this.state.password}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
<Button type="submit" value="Submit" color="primary" className="btn btn-warning">Sign Up</Button>
</form>
);
}
}
API endpoint of signup in server
//authenticate checker signup
app.post('/api/authenticatesignup', function (req, res) {
const { email, username, password } = req.body;
User.create({
email: req.body.email,
username: req.body.username,
password: req.body.password
},
function (err, user) {
if (err) {
console.error(err);
res.status(500)
.json({
error: 'Internal error please try again'
});
}
else {
// Issue token
const payload = { username };
const token = jwt.sign(payload, secret, {
expiresIn: '1h'
});
res.cookie('token', token, { httpOnly: true })
.sendStatus(200);
console.log("New USER!" + req.body.email + req.body.password)
}
})
});
You need to wrap the component with withRouter.
You can get access to the history object’s properties and the closest 's match via the withRouter higher-order component. withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
import React, { Component } from 'react';
import { withRouter } from "react-router";
import API from "../utils/API.js";
import { Container, Row, Col, Button, Alert, Modal, ModalHeader, ModalBody, ModalFooter, Label, Input } from 'reactstrap';
class SignupComp extends Component {
constructor(props) {
super(props)
this.state = {
email: '',
password: '',
username: '',
};
}
handleInputChange = (event) => {
const { value, name } = event.target;
this.setState({
[name]: value
});
}
onSubmit = (event) => {
event.preventDefault();
// API.signUpUser(this.state.email, this.state.username, this.state.password)
fetch('/api/authenticatesignup', {
method: 'POST',
body: JSON.stringify(this.state),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => {
console.log("THIS IS res " + JSON.stringify(res.status));
if (res.status === 200) {
// alert("You can now go to your dashboard")
// window.location.reload();
// // alert("You can now go to your dashboard")
this.props.history.push('/secret')
} else {
const error = new Error(res.error);
// console.log("This is error on client side " + error)
throw error;
// alert('Error logging in please try again');
}
})
.catch(err => {
console.error(err);
alert('Error logging in please try again');
});
}
render() {
console.log(this.state)
return (
<form onSubmit={this.onSubmit}>
Email: <input
type="email"
name="email"
placeholder="Enter email"
value={this.state.email}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
Username: <input
type="text"
name="username"
placeholder="Enter username"
value={this.state.username}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
Password: <input
type="password"
name="password"
placeholder="Enter password"
value={this.state.password}
onChange={this.handleInputChange}
required
/>
<br></br>
<br></br>
<Button type="submit" value="Submit" color="primary" className="btn btn-warning">Sign Up</Button>
</form>
);
}
}
const Signup = withRouter(SignupComp);
export default Signup;

Passing data from front end to route in backend React

I am currently new to using React and express, I wish to send data which i have received from a form. The data i would like to send back is the UserInfo or email which is in the state. However I am extremely unsure how I am supposed to go about this request.
class ForgotPassword extends Component {
constructor() {
super()
this.state = {
email:'',
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
componentDidMount = () =>{
// this.fetchUserInfo();
}
handleChange = (e) => {
this.setState ({
[e.target.id]: e.target.value
})
console.log(this.state);
}
handleSubmit = async (e) => {
e.preventDefault();
const userInfo = {
email : this.state.email
};
fetch("/forgotpassword", {
method: "POST",
body: JSON.stringify(userInfo),
headers: { "Content-Type": "application/json" }
})
.then(response => {
return response.json();
})
.then(jsonData => {
console.log(jsonData);
})
.catch(err => {
console.log("Error with data fetch " + err);
});
};
This is my form...
<div className='row'>
<div className='col'></div>
<div className='col card form'>
<h1 id="title">Reset Password</h1>
<h5 id="passinstruc">Please enter your email to reset your password</h5>
<form id="forgotpass" onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email </label>
<input onChange={this.handleChange} type="email" className="form-control" id="email" aria-describedby="emailHelp" placeholder="Enter email" value={this.state.email} />
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<button id="loginbtn" type="submit" className="btn btn-primary btn-lg btn-block" >Submit</button>
<br/>
<div className='division'>
<Link to="/register" className='btn btn-primary btn-lg btn-block' id="registerbtn" > Create your account here</Link>
</div>
</form>
</div>
In my backend I am getting a POST /forgotpassword 404 message but I dont know why. Help would be much appreciated.
This is my backend route where I will be sending the information
var express = require('express');
var router = express.Router();
var connection = require ('../connection');
var email = require ('./sendEmail');
router.post('/forgotpassword', function(req, res, next) {
console.log(req.email);
var userEmail = req.email;
var text = "Follow the instructions below to reset your password"
email.sendEmailWithTemplate(userEmail,'PetS.o.S Password Reset', text);
});
For sending data you will need the domain name or ip address of your server.
Once you obtained that, you can use jQuery.get - https://api.jquery.com/jQuery.get/
or jQuery.post -
https://api.jquery.com/jQuery.post/
Or if you are not using jQuery, use XMLHttpRequest -
https://www.w3schools.com/xml/xml_http.asp
Instead of sending data in body send it in response.
https://www.freecodecamp.org/news/create-a-react-frontend-a-node-express-backend-and-connect-them-together-c5798926047c/
fetch('/api/getList')
.then(res => res.json())
.then(list => this.setState({ list }))
https://dev.to/nburgess/creating-a-react-app-with-react-router-and-an-express-backend-33l3

'Uncaught SyntaxError: Unexpected token <' on Login Form

In my NextJS app.I'm developing a login page and now I'm getting the following error.
Uncaught SyntaxError: Unexpected token <
This was not appearing before and it started appearing yesterday.I googled the error message and browsed through many SO answers but none of them were helpful.I removed all form related onSubmit and onChange code but the error is still there.Since which code causes this error,I will post entire Login component here.
import React, { Component } from 'react';
import Heading from '../components/Heading';
class Login extends Component{
constructor(props) {
super(props);
this.onChangeInput = this.onChangeInput.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
date: new Date().toJSON().slice(0,10),
username: '',
password: ''
}
}
onChangeInput(e) {
this.setState({
[e.target.name]: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
const t = {
date: new Date().toJSON().slice(0,10),
username: this.state.username,
password: this.state.password
}
fetch('/server', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify(this.state)
})
this.setState({
username: '',
password: ''
});
}
render(){
return(
<div>
<div style={{textAlign: "center"}}>
<h1>PackMasters Ceylon (Pvt) Ltd</h1>
<h2>Inventory Management System</h2>
<h3>Login</h3>
</div>
<form onSubmit={this.onSubmit} onChange={this.onChangeInput} className={"col-md-4 col-md-offset-4"}>
<Heading title="Login | PackMasters Ceylon (Pvt) Ltd" />
<div className={"form-group"}>
<label htmlFor="username">Username</label>
<input type="text" name="username" value={this.state.username} className={"form-control"} id="username"/>
</div>
<div className={"form-group"}>
<label htmlFor="passsword">Password</label>
<input type="password" name="password" value={this.state.password} className={"form-control"} id="password" />
</div>
<div className={"form-group"}>
<input type="submit" className={"form-control"} value="Log In"/>
</div>
</form>
</div>
);
}
}
export default Login;
After struggling a lot, I found out that it is caused by the browser cache.The problem was solved after clearing browser cache on Chrome.Still I'm not able to explain the exact reason for that.However I will mention here how to clear cache on Google Chrome.
On your computer, open Chrome.
At the top right, click More.
Click More tools > Clear browsing data.
At the top, choose a time range. To delete everything, select All time.
Next to "Cookies and other site data" and "Cached images and files," check the boxes.
Click Clear data
A few issues:
The change handler should go on each input, not on the form
A bad idea to set the timestamp in the constructor... Seems you were already going in the right direction...
If you convert the handlers into arrow functions (no this context) no need to bind in the constructor (that's just a side note...)
Try this:
import React, { Component } from 'react';
import Heading from '../components/Heading';
class Login extends Component {
state = { username: '', password: '' };
handleChange = e => {
this.setState({ [e.target.name]: e.target.value });
};
handleSubmit = e => {
e.preventDefault();
const user = {
date: new Date().toJSON().slice(0, 10),
username: this.state.username,
password: this.state.password,
};
fetch('/server', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user),
});
this.setState({ username: '', password: '' });
};
render() {
return (
<div>
<div style={{ textAlign: 'center' }}>
<h1>PackMasters Ceylon (Pvt) Ltd</h1>
<h2>Inventory Management System</h2>
<h3>Login</h3>
</div>
<form
onSubmit={this.handleSubmit}
className={'col-md-4 col-md-offset-4'}
>
<Heading title="Login | PackMasters Ceylon (Pvt) Ltd" />
<div className={'form-group'}>
<label htmlFor="username">Username</label>
<input
type="text"
name="username"
value={this.state.username}
className={'form-control'}
id="username"
onChange={this.handleChange}
/>
</div>
<div className={'form-group'}>
<label htmlFor="passsword">Password</label>
<input
type="password"
name="password"
value={this.state.password}
className={'form-control'}
id="password"
onChange={this.handleChange}
/>
</div>
<div className={'form-group'}>
<input type="submit" className={'form-control'} value="Log In" />
</div>
</form>
</div>
);
}
}
export default Login;
Edit: Add a then and a catch block to fetch:
fetch('/server', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user),
}).then(res => res.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.error('Error:', error));
Also, I noticed you are using Next.js... You need to install Isomorphic Unfetch https://github.com/developit/unfetch/tree/master/packages/isomorphic-unfetch
In my case, static files were not being served due to global authentication enabled. which was also authenticating static files. So I had to apply #Public() metadata to that route to allow into JwtAuthGuard.
#Public()
#Get('/_next/static/*')
async getStaticContent(
#Req() req: IncomingMessage,
#Res() res: ServerResponse,
) {
await this.appService.handler(req, res);
}
More details on public metadata below.
https://docs.nestjs.com/security/authentication#enable-authentication-globally
And make sure your "esversion":6 is 6 for that follow below flow
For Mac VSCode : Code(Left top corner) => Prefrences => Settings => USER SETTINGS. and check at right side and write below Code
{
"workbench.colorTheme": "Visual Studio Dark",
"git.ignoreMissingGitWarning": true,
"window.zoomLevel": 0,
// you want to write below code for that
"jshint.options": {
"esversion":6
},
}

Resources