401 ERROR with API sending blank basic auth - reactjs

I am creating an API to send a basic auth login request to my flask backend, however when sending a request I get
{username: "ww", password: "ww"}
POST http://localhost:5000/login 401 (UNAUTHORIZED)
i have logged the data entered to check is was being set, this response is returned via the js console on the browser, the logging in my flask console is as follows :
127.0.0.1 - - [10/Nov/2019 16:21:07] "OPTIONS /login HTTP/1.1" 200 -
{'username': '', 'password': ''}
127.0.0.1 - - [10/Nov/2019 16:21:07] "POST /login HTTP/1.1" 401 -
My flask login route looks like
#app.route('/login', methods =['POST'])
def login():
if request.method == 'POST':
auth = request.authorization
print(auth)
if not auth.username or not auth.password:
return make_response('Could not verify :(', 401, {'WWW-Authenticate' : 'Basic realm="Login Required"'})
user = User.query.filter_by(username = auth.username).first()
if not user:
return make_response('Could not verify', 401, {'WWW-Authenticate' : 'Basic realm="Login Required"'})
if check_password_hash(user.password, auth.password):
token = jwt.encode({'public_id' : user.public_id, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30) }, app.config['SECRET_KEY'])
return jsonify({'token' : token.decode('UTF-8')})
return make_response('Could not verify', 401, {'WWW-Authenticate' : 'Basic realm="Login Required"'})
this is the login component on my react front end
export class Login extends React.Component {
constructor(props){
super(props);
this.state = {
username: '',
password: '',
}
}
changeHandler = e => {
this.setState({[e.target.name]: e.target.value})
}
submitHandler = e => {
const headers = {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
}
var username = this.username
var password = this.password
e.preventDefault()
console.log(this.state)
axois.post('http://localhost:5000/login',this.state,{
headers: {
headers
}
,auth: {
username : username,
password: password
}
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
render() {
const {username, password} = this.state
return <div className = "base-container" ref={this.props.containerRef}>
<div className="content">
<div className="logo">
<img src={Logo} alt="Logo"/>
</div>
<form className="form" onSubmit={this.submitHandler}>
<div className="form-group">
<label htmlFor="username"> Username</label>
<input type="text"
name="username"
value ={username}
placeholder="Username"
onChange={this.changeHandler}/>
</div>
<div className="form-group">
<label htmlFor="password"> Password</label>
<input type="password"
name="password"
value={password}
placeholder="Password"
onChange ={this.changeHandler}/>
</div>
<button type="submit" className="btn">Login</button>
</form>
</div>
<div className="footer">
</div>
</div>
}
}
My request works through using postman so im unsure why it doesnt using React? I am using Flask-Cors to prevent CORS errors and storing the user data in auth header so im not sure why flask cant read it.
I am very new to this so any help would be great :) Thanks !

Related

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)
}```

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

How to authenticate user using Django-rest and React js

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.

fetch request not working with headers

I am working on login page with ReactJs,Spring Boot and rest web services.My Reactjs frontend application is running on port 8080 while my webservice/spring boot application is running on port 9090. I am trying to use the "fetch" method to connect with my backend code, but I am facing error while passing headers in fetch request. If I remove headers property, execution goes into the called backend method. I need to pass Headers in fetch method as it required to access them in web service method.
Please find Snapshot of network requests and responses. Without Headers With headers
Below is my code of React JSX file:
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state={
email:'',
password:''
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
var usernameFieldValue = this.refs.emailField.value;
var passwordFieldValue = this.refs.passwordField.value;
this.setState({email:usernameFieldValue})
this.setState({password:passwordFieldValue})
//var headers = 'Basic bmltZXNoLnBhdGVsQHRhdHZhc29mdC5jb206cGFzc3dvcmQ=';
//alert(headers);
fetch('http://192.168.0.239:9090/ws/login',{
mode: 'cors',
method: 'get',
headers: {
"Content-Type": "application/json",
"Authorization": "Basic bmltZXNoLnBhdGVsQHRhdHZhc29mdC5jb206cGFzc3dvcmQ="
}
}).then((response) => response.json())
.then((responseJson) => {
alert(" responseJson : " + responseJson);
})
.catch((error) => {
alert("Error : " +error);
});
}
render() {
return (
<div id="loginFrame">
<div className="container">
<div id="loginHeader" className="row">
<div className="col-xs-12 text-center">
<img src="" alt="'Logo" />
</div>
</div>
<div id="loginBody" className="row">
<div className="col-xs-6 col-xs-offset-3">
<div className="center-block">
<div id="login-panel">
<form id="loginForm" className="form-horizontal" role="form">
<div className="form-group">
<input type="text" className="form-control input-lg" id="email" name="email" ref="emailField" placeholder="Email address"/>
</div>
<div className="form-group">
<input type="password" className="form-control input-lg" id="password" name="password" ref="passwordField" placeholder="Password"/>
</div>
<div className="form-group">
<button onClick={this.handleClick} className="btn btn-lg btn-success pull-right">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
var url = "https://yourUrl";
var bearer = 'Bearer '+ bearer_token;
fetch(url, {
method: 'GET',
withCredentials: true,
credentials: 'include',
headers: {
'Authorization': bearer,
'X-FP-API-KEY': 'iphone',
'Content-Type': 'application/json'}
}).then((responseJson) => {
var items = JSON.parse(responseJson._bodyInit);
})
.catch(error => this.setState({
isLoading: false,
message: 'Something bad happened ' + error
}));
You don't need mode: cors, this is default.
const headers = new Headers({
"Content-Type": "application/json",
"Authorization": "Basic bmltZXNoLnBhdGVsQHRhdHZhc29mdC5jb206cGFzc3dvcmQ="
});
fetch('http://192.168.0.239:9090/ws/login', {
method: 'GET',
headers,
}).then().then().catch();
Based on your comments, it sounds like the underlying problem is that you're doing a CORS request from your react app, which is being served from a different server than your spring backend. I don't know Spring, but adding a Access-Control-Allow-Origin HTTP header (as well as some other CORS related headers) will clear up the problem. I'm not 100% sure why when you fetch with no headers, it works. There may be a deeper configuration issue or you need to configure it to allow requests with those headers you're passing (Access-Control-Allow-Headers). Note that if you don't plan to allow cross-origin requests in production you may want to add those headers except when in development.
You can also fetch in no CORS mode (pass {mode: 'no-cors'}), but there's a lot of limitations to that and I doubt that's what you want.

ReactJS How To Set Cookie From Fetch Request to Back End

I have a react front end that is talking to a Node Back End. I am able to make requests and such . However, I noticed that I cannot set the cookie that I am getting back. My back end will respond upon logging in, with a message and a cookie. How should I be doing this?
Relevant code:
import React from "react";
import Fetch from 'react-fetch';
export class Loginform extends React.Component{
constructor(){
super();
this.state = {message : ""};
this.state = {cookie : ""};
}
Login(e){
e.preventDefault();
var Email_Address = this.refs.Email.value;
var Password = this.refs.Password.value;
fetch("http://localhost:5000/api/form", {
method: "POST",
headers: {
"Content-Type":"application/json",
"Accept":"application/json"
},credentials: "include",
body: JSON.stringify({
Email_Address: Email_Address,
Password: Password
})
}).then(response=>response.json())
.then(response => this.setState({message: response.Message, cookie :response['x-access-token']}));
}
render(){
return(
<div className="LoginContainer">
<form name="Loginform" method="post" action="http://localhost:5000/api/tavern" onSubmit={this.Login.bind(this)}>
<div className="block">
<label><i className="fa fa-envelope"></i></label>
<input ref="Email" type="email" placeholder="E-Mail" required title="Enter Valid E-Mail Address"/>
<i className="fa fa-check" aria-hidden="true"></i>
</div>
<div className="block">
<label><i className="fa fa-lock"></i></label>
<input ref="Password" type="password" placeholder="Enter Your Password" pattern=".{9,}" required title="9 Characters Minimum"/>
<i className="fa fa-check" aria-hidden="true"></i>
</div>
<div className="returnmessage"> {this.state.message}</div>
<div className="buttons"> <button type="submit" value="Submit">Login</button></div>
</form>
</div>
);
}
}
I had to add this to make the answer below applicable :
npm install react-cookies --save
import cookie from 'react-cookies'
Here is my code after.
fetch("http://localhost:5000/api/tavern", {
method: "POST",
headers: {
"Content-Type":"application/json",
"Accept":"application/json"
},credentials: "include",
body: JSON.stringify({
Email_Address: Email_Address,
Password: Password
})
}).then(response=>response.json())
.then(function (data){
console.log(data);
cookie.save('x-access-token', data['x-access-token']);
this.setState({message: data.Message, cookie :data['x-access-token']})
}.bind(this)
)
}
What you are doing is not setting the cookie. You are just creating a variable in state called cookie.
Install this package.
The correct syntax is
Cookies.set('access_token', response.headers['x-access-token'])
Now it is actually stored in to your browser cookies. You can go ahead and access it back using
Cookies.get('access_token')
For react you can also use react-cookie package. And if the React version >16.8.0 you can use React Hooks.
import { useCookies } from 'react-cookie';
const [cookies, setCookie] = useCookies(['name']); // getting react hooks
cookie2.set('access_token', 'content of cookie');
cookie = cookies.get('access_token');
console.log(cookie)

Resources