Access-Control-Allow-Origin Request blocked from Localhost:3000 on firebase - reactjs

I am getting an error on post method of axios for the code:
ERROR :
Access to XMLHttpRequest at 'https://identitytoolkit.googleapis.com/v1/signupNewUser?key=AIzaSyAHO' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
CODE:
const authData = {
email: email,
password: password,
returnSecureToken:true
}
axios.post('https://identitytoolkit.googleapis.com/v1/signupNewUser?key=AIzaSyAHOBs', authData)
.then( response => {
console.log(response);
dispatch(authSuccess(response.data));
})
.catch(err => {
console.log(err);
dispatch(authFail(err));
});

I was using different URL for post method, ie
https://identitytoolkit.googleapis.com/v1/signupNewUser?key=[API_KEY]
But the correct URL is same you posted and it even works without modification of headers :
https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]
code snippets :
export const auth = (email, password) => {
return (dispatch) => {
dispatch(authStart());
const authData = {
email: email,
password: password,
returnSecureToken: true,
};
const config = {
headers: {
"Content-Type": "application/json",
},
};
axios.post(
"https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyAHOBsv31rdWYhCr15gRS727QuCnajk2CU",
authData,
config
)
.then((response) => {
console.log(response.data);
dispatch(authSuccess(response.data));
})
.catch((err) => {
console.log(err);
dispatch(authFail(err));
});
};
};
thank you so much
Happy coding :)

I am doing the same course and facing the same error.
after a long time, I found that the problem was where we call the function (Auth.js file).
while we handle the onSubmit method we call the onAuth method from mapDispatchToProps like this
const mapDispatchToProps = dispatch =>{
return {
onAuth: (email, pass) => dispatch(actions.auth(email,pass))
}
}
on the course video, the submit handler was like this. that was not correct and indicating an object instead of a string value.
submitHandler = (event) => {
event.preventDefault();
this.props.onAuth(this.state.controls.email, this.state.controls.password);
}
the correct handler would be like this ...
submitHandler = (event) => {
event.preventDefault();
this.props.onAuth(this.state.controls.email.value, this.state.controls.password.value);
}

Related

Post form-data on Axios (React)

I've got the following component in React:
const login = async (username, password) => {
const response = await axios.post('/auth/jwt/login', {
username,
password
});
const {accessToken, user} = response.data;
setSession(accessToken);
dispatch({
type: 'LOGIN',
payload: {
user,
},
});
};
Now, the problem is my API is expecting a form, whereas this request is sending a json on the body, thus I'm getting a 422 error (unprocessable entity).
I've tried creating a FormData() object but no luck so far:
const formData = new FormData();
const login = async () => {
const response = await axios.post('/auth/jwt/login', {
username: formData.username,
password: formData.password
});
const {accessToken, user} = response.data;
setSession(accessToken);
dispatch({
type: 'LOGIN',
payload: {
user,
},
});
};
Can anyone please help me? Thanks!
Specifically you want to POST the data as application/x-www-form-urlencoded instead of as a JSON-encoded body. According to the documentation, in the browser you would use URLSearchParams for this. For example:
const params = new URLSearchParams();
params.append('username', username);
params.append('password', password);
const response = await axios.post('/auth/jwt/login', params);
(That same documentation provides other options as well, to include 3rd party libraries or to POST from NodeJS. The above is specific to in-browser code with no 3rd party libraries.)
The previous solution didn't work for me. This did:
const form = new FormData();
form.append('username', username)
form.append('password', password)
const response = await axios.post('/auth/jwt/login', form,
{ headers: { 'Content-Type': 'multipart/form-data' } }
);
In fact I could just do this:
const login = async (username, password) => {
const response = await axios.post('/auth/jwt/login', {
username,
password
},
{ headers: { 'Content-Type': 'multipart/form-data' } }
);
const {accessToken, user} = response.data;
setSession(accessToken);
dispatch({
type: 'LOGIN',
payload: {
user,
},
});
};

How to pass status codes to client side? (Redux asyncThunk)

I want to access the status sent from my Express server in my React component. I am using redux to dispatch a login fetch request and want to conditionally render different childrens based on the status code received (eg. 'Incorrect Password' if status code 401)
loginmodal.js
const handleLogin = async (event) => {
event.preventDefault();
let result = await dispatch(login({ email, password }))
console.log(result) //payload is undefined if incorrect password.
}
userAuthSlice.js (Redux)
export const login = createAsyncThunk(
'userAuth/login',
async (payload, thunkAPI) => {
const { email, password } = payload
const result = await fetch(
loginPath, {
mode: 'cors',
credentials: 'include',
method: 'post',
body: JSON.stringify({ email, password }),
headers: {
'Content-Type': 'application/json'
},
}
)
console.log(result) // Response {type: 'cors', url: 'http://localhost:5000/login', redirected: false, status: 401, ok:
const response = await result.json()
console.log(response)
return response
}
)
const userAuthSlice = createSlice({
extraReducers: {
[login.pending]: (state) => {
state.isLoading = true
},
[login.fulfilled]: (state, action) => {
state.isLoading = false
state.isAuth = true
},
[login.rejected]: (state) => {
state.isLoading = false
},
}
server.js
app.post('/login', (req, res) => {
const email = req.body.email;
const plainTextPassword = req.body.password;
User.find({ email: email }).limit(1).exec(function (err, existingUser) {
if (existingUser.length === 0) {
res.sendStatus(401)
} else {
bcrypt.compare(plainTextPassword, existingUser[0].password, function (err, response) {
if (response === true) {
req.session.user = existingUser[0]._id
res.json(req.session)
} else {
res.sendStatus(401)
}
})
}
}
)
})
In my loginModal, i console.log the payload from dispatch. My payload is undefined if my promise is rejected from incorrect password. My payload includes the status code if its fulfilled eg correct password. How can i get the status code / payload, even if the promise is rejected? Or is there another approach to this problem?
You need to check the Response.ok and / or Response.status properties to determine if your request was successful.
If they are not, I would recommend returning a rejected value. The rejected object can have the properties you need like status
const res = await fetch(...);
if (!res.ok) {
// thunkApi.rejectWithValue
return rejectWithValue({
status: res.status,
message: await res.text(),
});
}
return res.json();
Then you can check for rejected promises and refer to the status in your consuming code
const handleLogin = async (event) => {
event.preventDefault();
try {
// needs the `.unwrap()` function call
const result = await dispatch(login({ email, password })).unwrap();
console.log(result);
} catch (err) {
console.warn(err);
switch (err.status) {
case 401:
// do something for 401
break;
default:
// default error handling
}
}
}

Axios post request is not working for a register form submission

I have a form built in react js and I am using an axios post request to register a user after form submission. I have tried to put a try catch block after the promise but i dont think i am getting passed the post request. I have imported axios and checked package json to make sure its downloaded. I have also implemented a catch block to catch errors but I am still getting
(TypeError: Cannot read properties of undefined (reading 'post'))
const handleSubmit = (e) => {
e.preventDefault();
axios.post('http://localhost:5000/api/users/register',{
name: data.name,
email:data.email,
password: data.password
})
.then((res) => {
console.log("server response:",res);
})
.catch((err) =>{
console.log("Server responded with error", err);
})
}
It is indeed correct to use axios.post in that way but you are not handling a response or an error from the server. For these axios provides you with the .then() and .catch() methods, which handle the results/error for you.
Here's an example:
(You can check the results of the post request in this example in the console tab or the network tab in the developer tools of your favorite browser).
const RegisterScreen = () => {
const [ data, setData ] = useState({
name: "",
email: "",
password: "",
});
const handleChange(e) => {
setData({...data, [e.target.name]: e.target.value});
}
const handleSubmit = (e) => {
e.preventDefault();
axios.post("YOUR/URL:5000", {
name: data.name,
email: data.email,
password: data.password
})
.then((res) => {
console.log("Server response: ", res);
})
.catch((err) => {
console.log("Server respondend with error: ", err);
})
}
}
return (
<>
<YourForm />
</>
);
}
You may have to specify the content type while sending a POST request.
const handleSubmit = (e) => {
e.preventDefault();
axios.post('http://localhost:5000/api/users/register',{
name: data.name,
email:data.email,
password: data.password
}, {
headers: {
'Content-Type': 'application/json' }
})
.then((res) => {
console.log("server response:",res);
})
.catch((err) =>{
console.log("Server responded with error", err);
})
}

called async function from state is not waiting (react)

I call a state function in my component, the function should change the state(and it does but late), i want to log the change but the log triggers before the state is changed
this is the function in the state:
const login = async (user, password) => {
const body = {
username: user,
password: password,
};
await axios
.post('/sessions', body, {
headers: { 'Content-Type': 'application/json' },
})
.then((resp) => {
dispatch({ type: LOGIN, payload: resp.data.data });
})
.catch((err) => {
console.log(err.response.data);
});
};
and this is the call in the component
const onSubmit = (e) => {
e.preventDefault();
login(user, password);
console.log(credes);
};
"credes" is the state for that response, but it keeps printing the initial state witch is an empty object
the function triggers on the form submission but logs first and updates the state later.
As pointed out by bubulledu93, ronakvp and coreyward, I was butchering the syntax. I was trying to perform two actions in one function, so I moved the log into a useEffect to watch for changes in the "credes" hope is the right way but is working as I needed it.
const login = (user, password) => {
const body = {
username: user,
password: password,
};
axios
.post('/sessions', body, {
headers: { 'Content-Type': 'application/json' },
})
.then((resp) => {
dispatch({ type: LOGIN, payload: resp.data });
})
.catch((err) => {
console.log(err.response.data);
});
};
and the call in the component + the useEffect
const onSubmit = (e) => {
e.preventDefault();
login(user, password);
};
useEffect(() => {
if (credes.success) {
console.log(credes.data);
}
}, [credes]);
There isn't any benefit to awaiting as the last call in a function. Instead of using async and await, simply return the Promise chain started by axios.post() to onSubmit and then chain on it (or use await there):
const login = (user, password) => {
const body = {
username: user,
password: password,
};
return axios
.post('/sessions', body, {
headers: { 'Content-Type': 'application/json' },
})
.then((resp) => {
dispatch({ type: LOGIN, payload: resp.data.data });
})
.catch((err) => {
console.log(err.response.data);
});
};
// Option 1:
const onSubmit = (e) => {
e.preventDefault();
login(user, password)
.then(() => {
console.log(credes);
});
};
// Option 2:
const onSubmit = async (e) => {
e.preventDefault();
await login(user, password);
console.log(credes)
}

Partial observable handling in Angular 2

I have a component which a login form: loginForm which calls my api:
onLogin(): void {
let username = this.loginForm.value.username;
let password = this.loginForm.value.password;
this.api.login(username, password);
.map(res => res.json())
.subscribe(
this._processData,
);
}
There is a service which calls an api: loginService.
login(username: string, password: string): Subscription<any> {
let headers = new Headers();
headers.append("Content-Type", "application/json");
return this.http.put("https://myapi.com", JSON.stringify({ username: username, password: password}), {
headers: headers
})
.map(res => res.json())
.subscribe(
data => console.log(data),
err => console.log(err),
() => console.log("Done")
);
}
What I want is the error to be handled inside the loginService. But the result back to the onLogin method.
I tried a variety of mapping handlers (as shown) in the onLogin but could not get it to work. Any thoughts about what I might do wrong?
In fact, you define a callback within the subscribe method to handle error in the login method (the second parameter). If you want to let errors to be propagated into your onLogin method you need to remove this callback (and even the call of subscribe).
return this.http.put("https://myapi.com",
JSON.stringify({ username: username, password: password}), {
headers: headers
})
.map(res => res.json());
If you want to log the error and then propagate it you can leverage the Observable.throw method:
return this.http.put("https://myapi.com",
JSON.stringify({ username: username, password: password}), {
headers: headers
})
.map(res => res.json())
.catch(err => {
console.log(err);
return Observable.throw(err);
});
In this case you need to add a callback to handle the error in the onLogin method:
onLogin(): void {
let username = this.loginForm.value.username;
let password = this.loginForm.value.password;
this.api.login(username, password)
.subscribe(
(data) => {
// Success
this._processData(data)
},
(err) => {
// Error
}
);
}
You can notice that there is a catch operator on Observable to catch error and in the case of errors, the map operator isn't called.
These answers could give you more details:
Angular2 http observables - how to work with undefined type
Observable Map function not running (Angular2, http)
Hope it helps you,
Thierry
You can define your error handler in your service, and just pass the error from component where you subscribe.
// component
onLogin(): void {
let username = this.loginForm.value.username;
let password = this.loginForm.value.password;
this.api
.login(username, password)
.subscribe(
this._processData, // success
this.api.onError // error
// if above doesn't work this should:
// error => this.api.onError(error)
);
}
_processData(...data) { console.log(data); }
// service
login(username: string, password: string): Subscription<any> {
let headers = new Headers();
headers.append("Content-Type", "application/json");
return this.http
.put("https://myapi.com", JSON.stringify({ username: username, password: password}), { headers: headers })
.map(res => res.json())
}
onError(...args) { console.log(args); }

Resources