how to get user id after token authentication - REACT - reactjs

I'm new at coding so hoping this is something simple. I am trying to create delete/update functions for the user when they go to their profile. To delete and update my api needs the user id for:
fetch(${process.env.REACT_APP_API_URL}users/${id}/,
Token authentication works and is stored in the localhost but I can't seem to access the id of the user after login. How can I store the id and call it in this function?
**Notes: the 'userData' const was an attempt at calling the api by:
fetch(${process.env.REACT_APP_API_URL}users/${userData.id}/,
(didn't work)
my ProfilePage code:
const Profile = () => {
const [userData, setUserData] = useState({
username: "",
email: "",
password: "",
});
const { id } = useParams();
const navigate = useNavigate();
const EditAccount = () => {
navigate("/edit-account");
};
const addCar = () => {
navigate("/home");
};
useEffect(() => {
fetch(`${process.env.REACT_APP_API_URL}users/${id}/`)
.then((results) => {
console.log("results", results);
return results.json();
})
.then((data) => {
setUserData(data);
});
});
const Logout = () => {
localStorage.clear();
window.location.href = "/";
};
const DeleteUser = async () => {
fetch(`${process.env.REACT_APP_API_URL}users/${id}/`, {
method: "delete",
headers: {
Authorization: `Token ${localStorage.getItem("token")}`,
},
});
navigate("/");
};

Related

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');
}
});
};

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;
},

Why is UseEffect not launching the entire async function?

I am using Auth0 on a react application for authentication. After authenticating, I am trying to save the data from authentication to the database (I'm using node.js and mongoose/mongodb). I created a function that makes a post request and also accesses a token with an Auth0 function. When I execute the function in useEffect, the token gets created, as I can see it in the network tab on the Chrome debugger. But, the response api call never gets made. Do you know why this is? Here is my code:
const [data, setData] = useState({
message: '',
error: null,
loading: true
});
const [userData, setUserData] = useState(null);
const serverUrl = 'http://localhost:5000';
const loginOrCreateUser = useCallback(async () => {
try {
const token = await getAccessTokenSilently();
const response = await fetch(`${serverUrl}/users/login`, {
headers: {
Authorization: `Bearer ${token}`,
},
method: "POST",
body: {
name: user.name,
email: user.email,
_id: user.sub
}
});
const responseData = await response.json();
setUserData(responseData);
console.log(userData);
} catch (error) {
setData({...data, error: error.error});
}
});
useEffect(()=> {
loginOrCreateUser();
}, []);
return (
isAuthenticated && (
<div>
<img src={user.picture} alt={user.name} />
<h2>{user.name}</h2>
<Button onClick={callApi}>Call API</Button>
<p>{JSON.stringify(data.message)}</p>
</div>
)
);
}

Authenticate my ReactJS SPA with laravel/sanctum using Axios

After a successful authentication (login + token), I'm still unable to request auth:sanctum routes and I get the following response:
LoginForm component
import React, { useState } from "react";
const LoginForm = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const loginHandler = (ev) => {
ev.preventDefault();
if (email.length > 0 && password.length > 0) {
axios.get("/sanctum/csrf-cookie").then(() => {
axios
.post("api/login", {
email: email,
password: password,
})
.then((response) => {
console.log(response.data);
})
.catch(function (error) {
console.error(error);
});
});
}
};
Login action
public function login(Request $request)
{
$request->validate(['email' => 'required', 'password' => 'required|string']);
$user = User::where('email', $request->email)->first();
if (!$user || !password_verify($request->password, $user->password)) {
return response(['message' => 'Bad credentials'], 401);
}
$token = $user->createToken('token')->plainTextToken;
return response(['user' => $user, 'token' => $token], 201);
}
Login Response
{
"user": {
"id": 7,
"email": "daphne19#example.com",
"email_verified_at": "2022-03-09T16:40:59.000000Z",
"created_at": "2022-03-09T16:40:59.000000Z",
"updated_at": "2022-03-09T16:40:59.000000Z"
},
"token": "5|oCnoaVBBYARcFXwdd7dXegchFLS6fckDgr2Bl0L0"
}
You need to pass Sanctum Token in Axios Header.
first you need to set user response in local storage.
const LoginForm = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const loginHandler = (ev) => {
ev.preventDefault();
if (email.length > 0 && password.length > 0) {
axios.get("/sanctum/csrf-cookie").then(() => {
axios
.post("api/login", {
email: email,
password: password,
})
.then((response) => {
//set response in local storage
localStorage.setItem('user', JSON.stringify(response.data))
})
.catch(function (error) {
console.error(error);
});
});
}
};
then you need to pass token in Axios Header
const user = JSON.parse(localStorage.getItem('user'));
const headers = {
accept: 'application/json',
Authorization: 'bearer ' + user.token
}
//set token in axios header
axios.get(API, {
headers: headers
})
.then((res) => { })
.catch((err) => { })
please change the bearer to Bearer while making an authentication requests using Axios.

Axios making 2 requests on refresh

When I navigate using Link (react router-dom) I don't have this problem, but if I refresh the browser I get a 403 error in console saying unauthorised and then I get the data in the next request with a 200 response. Why is this making what looks like 2 requests when refreshing the browser?
import { AuthContext } from "../../shared/context/auth-context";
const ContactEntries = () => {
const auth = useContext(AuthContext);
useEffect(() => {
const source = Axios.CancelToken.source();
setIsLoading(true);
const getContactEnquiries = async () => {
try {
const response = await Axios.get(
`${process.env.REACT_APP_BACKEND_URL}/v1/contact`,
{
cancelToken: source.token,
headers: { Authorization: "Bearer " + auth.token },
}
);
if (response.status === 200) {
setIsLoading(false);
setEnquiries(response.data.enquiries);
}
} catch (err) {
setIsLoading(false);
console.log(err.response);
}
};
getContactEnquiries();
return () => {
source.cancel();
};
}, [!!auth.token]);
}
Here is my authContext:
import { createContext } from "react";
export const AuthContext = createContext({
isLoggedIn: false,
userId: null,
token: null,
email: null,
firstName: null,
login: () => {},
logout: () => {},
});
This is because your useEffect is running twice on refresh. On first render it is not getting auth.token and may be it null. And on second render it is making call with 200 status code.
You have to check auth token it coming successfully.
You can check it this way
useEffect(() => {
const source = Axios.CancelToken.source();
setIsLoading(true);
const getContactEnquiries = async () => {
try {
const response = await Axios.get(
`${process.env.REACT_APP_BACKEND_URL}/v1/contact`,
{
cancelToken: source.token,
headers: { Authorization: "Bearer " + auth.token },
}
);
if (response.status === 200) {
setIsLoading(false);
setEnquiries(response.data.enquiries);
}
} catch (err) {
setIsLoading(false);
console.log(err.response);
}
};
if(auth.token) getContactEnquiries();
return () => {
source.cancel();
};
}, [!!auth.token]);

Resources