MISSING_REQUEST_URI firebase - reactjs

I am using firebae auth to log in and sign up for my react app. I can get sign up working but I am having issues with log in. I followed the https://firebase.google.com/docs/reference/rest/auth#section-sign-in-email-password for the api link.
I followed the same code for log in than I did for sign up but I keep getting issues with it.
This is the error message i get when i try to log in.
Object {
"error": Object {
"code": 400,
"errors": Array [
Object {
"domain": "global",
"message": "MISSING_REQUEST_URI",
"reason": "invalid",
},
],
"message": "MISSING_REQUEST_URI",
},
}
This is my user action page for my app for log in.
export const login = (email, password) => {
return async dispatch => {
const response = await fetch('https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=[API]', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ //javascript to json
//key value pairs of data you want to send to server
// ...
email: email,
password: password,
returnSecureToken: true
})
});
// console.log(await response.json());
const data = await response.json(); // json to javascript
console.log(data);
if (!response.ok) {
Alert.alert("There was a issue with logging in ")
} else {
await SecureStore.setItemAsync('email', data.email);
await SecureStore.setItemAsync('token', data.idToken);
dispatch({ type: SIGNUP, payload: { email: data.email, idToken: data.idToken } })
}
};
}
This is my user action page for my app for sign in.
export const signup = (email, password) => {
return async dispatch => {
const response = await fetch('https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API]', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ //javascript to json
//key value pairs of data you want to send to server
// ...
email: email,
password: password,
returnSecureToken: true
})
});
// console.log(await response.json());
const data = await response.json(); // json to javascript
console.log(data);
if (!response.ok) {
Alert.alert("There was a issue with signing in ")
} else {
await SecureStore.setItemAsync('email', data.email);
await SecureStore.setItemAsync('token', data.idToken);
dispatch({ type: SIGNUP, payload: { email: data.email, idToken: data.idToken } })
}
};
};
Then this is my log in screen.
const LoginScreen = ({ navigation }) => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const dispatch = useDispatch()
async function load() {
let emailFromSecureStore = await SecureStore.getItemAsync('email');
let tokenFromSecureStore = await SecureStore.getItemAsync('token');
if (emailFromSecureStore && tokenFromSecureStore) {
console.log("success", emailFromSecureStore);
// dispatch(restoreUser(emailFromSecureStore, tokenFromSecureStore));
} else {
console.log("failure");
}
}
useEffect(() => {
load(); // uncomment to read from secure store
}, [])
return (
<View style={styles.ViewStyle}>
<TextInput placeholder='Email'
onChangeText={setEmail}
value={email}
style={styles.loginText}/>
<TextInput placeholder='Password'
onChangeText={setPassword}
value={password}
style={styles.loginText}/>
<View style={styles.gap}>
</View>
<Pressable style={styles.buttonStyle} onPress={() => dispatch(login(email, password))}>
<Text style={styles.text}>Log in</Text>
</Pressable>
</View>
);
}

Related

How to apply authentication with passport-google-oauth in a mern app with json web token

Recently i am working for a organization. they told me use oauth with jwt, no local authentication. i used passport-google-oauth20 and jsonwebtoken package. I am having problem in frontend react part. how to to get the data from backend with fetch or axios?
here is my code
server.js
app.get(
"/auth/google",
passport.authenticate("google", {
scope: ["profile", "email"],
})
);
app.get(
"/auth/google/callback",
passport.authenticate("google", { session: false }),
generateAccessToken,
function (req, res) {
if (req.token) {
const email = req.user.email;
const token = req.token;
return res.status(200).json({ email, token });
} else res.status(400).json({ message: "Something went wrong" });
}
);
token.js
exports.generateAccessToken = (userId) => {
const token = jwt.sign({ _id: userId }, process.env.JWT_SECRET, {
expiresIn: "1h",
issuer: process.env.JWT_ISSUER,
});
return token;
};
Uselogin hook
export const useLogin = () => {
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(null);
const { dispatch } = useAuthContext;
const login = async () => {
setIsLoading(true);
setError(null);
const response = await fetch("localhost:4000/auth/google/callback", {
method: "GET",
credentials: "include",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"Access-Control-Allow-Credentials": true,
},
});
const json = await response.json;
if (!response.ok) {
setIsLoading(false);
setError(json.error);
}
if (response.ok) {
localStorage.setItem("user", JSON.stringify(json));
dispatch({ type: "LOGIN", payload: json });
setIsLoading(false);
}
};
return { login, isLoading, error };
};
how can i get the user mail and token from the backend?
I know i can access the page through window.open("localhost:4000/auth/google,"_self"), but then how can i retrive the data.

How to use query string in fetch post?

Newbie here. Building a React site. I'm struggling to get my authentication to go through a fetch post. It keeps returning "No such user" error, but when I have verified the user DOES exist.
I'm using passport on the backend.
const handleSubmit = (event) => {
event.preventDefault();
const data = {
Username: username,
Password: password
};
fetch('https://cthulhuflix.onrender.com/login', {
method: 'POST',
body: new URLSearchParams(JSON.stringify(data))
})
.then ((response) => response.json())
.then ((data) => {
console.log('Login response: ', data);
if (data.user) {
onLoggedIn(data.user, data.token);
} else {
alert('Dave\'s not here! No such user.');
}
})
.catch((e) => {
alert('Something went wrong');
});
};
Here's what I ended up with:
export const LoginView = ({ onLoggedIn }) => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (event) => {
event.preventDefault();
const data = {
Username: username,
Password: password
};
fetch('https://cthulhuflix.onrender.com/login?' + new URLSearchParams(data).toString(), {
method: 'POST',
body: JSON.stringify(data)
}).then ((response) => {
if (response.ok) {
onLoggedIn(username);
} else {
alert('Login failed');
}
});
};

React admin not asking for password

Simple page given
import { fetchUtils, Admin, Resource, ListGuesser } from 'react-admin';
import * as React from "react";
import apiDataProvider from './apiDataProvider';
import apiAuthProvider from './apiAuthProvider';
const dataProvider = apiDataProvider('https://example.com/api/v1');
const App = () => (
<Admin dataProvider={dataProvider} authProvider={apiAuthProvider}>
<Resource name="campaign" list={ListGuesser} />
</Admin>
);
export default App;
apiDataProvider used for url customization, probably there's better solution
const endPoint = 'https://example.com/api/v1'
const apiAuthProvider = {
login: ({ username, password }) => {
console.log('login');
const request = new Request(endPoint+'/sign-in/', {
method: 'POST',
body: JSON.stringify({ username: username, password: password }),
headers: new Headers({ 'Content-Type': 'application/json' }),
});
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(auth => {
localStorage.setItem('auth', JSON.stringify(auth));
})
.catch(() => {
throw new Error('Network error')
});
},
logout: () => {
console.log('logout');
localStorage.removeItem('username');
const request = new Request(endPoint+'/sign-out/', {
method: 'POST',
body: JSON.stringify({ }),
headers: new Headers({ 'Content-Type': 'application/json' }),
});
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(auth => {
localStorage.setItem('auth', JSON.stringify(auth));
})
.catch(() => {
throw new Error('Network error')
});
},
checkAuth: () => {
console.log('checkAuth', localStorage.getItem('username'));
return localStorage.getItem('username') ? Promise.resolve() : Promise.reject();
},
checkError: (error) => {
console.log('checkError');
const status = error.status;
if (status === 401 || status === 403) {
localStorage.removeItem('username');
return Promise.reject();
}
// other error code (404, 500, etc): no need to log out
return Promise.resolve();
},
getIdentity: () => {
try {
const { id, fullName, avatar } = JSON.parse(localStorage.getItem('auth'));
return Promise.resolve({ id, fullName, avatar });
} catch (error) {
return Promise.reject(error);
}
},
getPermissions: () => Promise.resolve(''),
};
export default apiAuthProvider;
On load "/" it calls logout twice, queries for campaign list (custom url), gets 401 and calls logout url again.
On the page I can see "Please login to continue" message, but no login window. Login form is available on /login. Why RA doesn't redirect to login form?

NextJs creating user document in mongodb after google sign in

i want to create a user document after i sign in with google in my nextjs application. I can sign in but it's not creating the document after it. This is my function
const handleSignIn = async () => {
try {
await signIn("google");
await addUser();
} catch (error) {
console.log("Erro");
}
};
The addUser function is
const addUser = async () => {
if (status === "authenticated") {
const user = {
name: session.user.name,
email: session.user.email,
avatar: session.user.image,
};
try {
await fetch("/api/new_user", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(user),
});
} catch (error) {
console.log(error);
}
} else {
console.log("Not logged in");
}
};
This is how i'm creating the new document in my new_user.ts file in the api folder
export default async function handleNewUser(req:NextApiRequest, res:NextApiResponse){
const client = await clientPromise;
const db = client.db("bookdb");
const coll: Collection = db.collection("users");
const user = req.body
console.log(user)
try {
await coll.insertOne(user)
res.status(200).json({response:'Success'})
} catch (error) {
res.status(500).json({error:'Erro'})
To make sure it was working, i triggered manually the addUser function after signing in and it worked.
What am i doing wrong here?
this is my snippet for google auth sign in with mongodb and nextjs using typescript and prisma.
signIn: async ({user, account}) => {
if (account?.provider === 'google') {
const googleAuthData = {
name: user.name,
email: user.email,
image: user.image,
authProvider: 'google',
password: ''
}
const exist = await prisma.user.findFirst({
where: {email: user.email},
});
if (exist) {
const result = await prisma.user.update({
where: {email: user.email},
data: {image: user.image},
});
} else {
const result = await prisma.user.create({
data: googleAuthData,
});
}
}
return true;
},

How to Resolve 401 unAuthorized error even though Tokens and everything is set? and postman returns no issue at all while testing -MERN Stack

i am new to react and I've been trying to make this api work,(following you tube tutorial), when i test the routes via postman the response i receive is 'OK-working' but then when i try to login from my react app, it turns to unauthorized, i don't know how to deal with this *** i have done everything i could possibily upto my understanding ***, I've explored as much stack Overflow as i could as well as Googled it but still not found something understandable enough.
p.s this is very critical issue for me as this is part of my web Class at college and it holds a great deal of grades!
Attaching the link to github directory as well in case you need it :
https://github.com/nescafestar/twitter-clone
this is my AuthActions.js file
```
//authAction.js
import axios from 'axios';
import {GET_ERRORS, SET_CURRENT_USER} from '../constants';
import setAuthHeader from '../utils/setAuthHeader'
export const registerUser = (userData, history) => dispatch => {
axios.post('http://localhost:5000/api/users/register', userData,{
headers: {
'Authorization': 'Bearer'+ localStorage.getItem('jwtToken')
}
})
.then(res => {
console.log('----> registering')
const { token } = res.data
localStorage.setItem('jwtToken', token)
if(token){
axios.defaults.headers.common['Authorization']='Bearer : '+ token
}
history.push('/')})
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}))
}
export const loginUser = (userData) => dispatch => {
axios.post('http://localhost:5000/api/users/login',userData,{
headers: {
'Authorization': 'Bearer : ' +localStorage.getItem('jwtToken')
}
})
.then(res => {
// console.log(userData)
const { token } = res.data
localStorage.setItem('jwtToken', token)
if(token){
axios.defaults.headers.common['Authorization']='Bearer : ' +token
}
console.log('---> hit dispatch')
dispatch(getCurrentUser())
})
.catch(err => {
// console.log(err);
// dispatch({
// type: GET_ERRORS,
// payload: err.response.data
// })
})
}
export const getCurrentUser = () => dispatch => {
axios.get('http://localhost:5000/api/users',{
headers: {
'Authorization': 'Bearer : ' +localStorage.getItem('jwtToken')
}
})
.then(res => dispatch(setCurrentUser(res.data)))
.catch(err => dispatch({
type: GET_ERRORS,
payload: err.response.data
}))
}
export const setCurrentUser = (data) => {
console.log('----> setting user!')
return {
type: SET_CURRENT_USER,
payload: data
}
}
export const logoutUser=()=>dispatch=>{
localStorage.removeItem('jwtToken')
setAuthHeader()
dispatch(setCurrentUser())
}
```
this is the set Auth Header one:
```
import axios from 'axios'
// const jsonwebtoken=require('jsonwebtoken')
export default function(token){
console.log(token)
if(token){
console.log('Token has been set-properly')
return axios.defaults.headers.common['Authorization']='Bearer'+ token
}else{
return axios.defaults.headers.common['Authorization']=null
}
}
```
and lastly this is my POST.js file which is also returning the same issue of being unAuthorized
import axios from 'axios'
// const jsonwebtoken=require('jsonwebtoken')
export default function(token){
console.log(token)
if(token){
console.log('Token has been set-properly')
return axios.defaults.headers.common['Authorization']='Bearer'+ token
}else{
return axios.defaults.headers.common['Authorization']=null
}
}
``` ```
////////////////////////*** ROUTER ***
``` ```
// also the Routes/User.js file in case someone wants to know about it as well
const router = require("express").Router();
const User = require("../models/User");
const jwt=require('jsonwebtoken');
const passport = require("passport");
//validation
const validateRegisterInput = require("../validation/register");
const validateLoginInput = require("../validation/login");
//handling password hasing
const bcrypt = require("bcryptjs");
// const utils = require("../utils/utils");
//routing requests
//handling post request
router.route("/register").post((req, res) => {
const { isValid, errors } = validateRegisterInput(req.body);
if (!isValid) {
return res.status(404).json(errors);
}
//test arguments
// return res.send('OKKKK!!');
//register user is it does not exist in db
User.findOne({ email: req.body.email }).then((user) => {
if (user) {
errors.email = "Email already Registered!";
return res.status(404).json(errors);
}
bcrypt.genSalt(10, function (err, salt) {
bcrypt.hash(req.body.password, salt, function (err, hash) {
//adding new User to DB is Not Exist
const newMember = new User({
username: req.body.username,
email: req.body.email,
password: hash,
});
newMember
.save()
.then((newMember) => res.json(newMember))
.catch((err) => console.log(err));
});
});
});
}); //register route ends
//Login Route
router.route('/login')
.post((req, res) => {
const { errors, isValid } = validateLoginInput(req.body)
if (!isValid) {
return res.status(404).json(errors)
}
User.findOne({ email: req.body.email })
.then(user => {
if (!user) {
errors.email = 'User not found/not exist'
return res.status(404).json(errors)
} else {
bcrypt.compare(req.body.password, user.password)
.then(isMatch => {
if (isMatch) {
const token = jwt.sign({ id: user._id }, process.env.SECRET, { expiresIn: '1d' }, function (err, token) {
return res.json({
success: true,
token: token
})
})
} else {
errors.password = 'Password is incorrect'
return res.status(404).json(errors)
}
})
}
})
})
//returning route for logged in user
router.route('/')
.get( passport.authenticate('jwt', { session: false }),(req, res) => {
console.log('here! in home redirect')
res.json({
_id: req.user._id,
email: req.user.email,
username: req.user.username,
followers: req.user.followers,
following: req.user.following
})
})
module.exports = router;
You are not populating the Authorization header consistently or correctly. Assume your jwtToken value is AAAA for simplicity. In some cases you send BearerAAAAAA, in others you send Bearer : AAAA. The standard should be to use the string "Bearer", followed by one space, followed by the base64 encoding of the token (Bearer AAAA). See the RFC for more information: https://www.rfc-editor.org/rfc/rfc6750
When setting the header, you could use something like this:
const token = localStorage.getItem('jwtToken') //Or however you choose to get it
const headers = {
Authorization: `Bearer ${token}`
}

Resources